I Traced Unbound's DNSSEC Heap Overflow: 4 Checks to Run
DEV Community

I Traced Unbound's DNSSEC Heap Overflow: 4 Checks to Run

[ attacker's zone ] ──β–Ί ┌────────────────────────────┐
                          │ Unbound (recursive, DNSSEC) │
                          │ CVE-2026-81642  CWE-122    │
                          │ DNSKEY -> digest buffer     │
                          └────────────────────────────┘

A compression pointer inside a DNSSEC key record can overflow a heap buffer in the most security-conscious component of your resolver stack, and the vendor's own advisory says remote code execution is possible through attacker controlled data. That is CVE-2026-81642 in Unbound, and it shipped alongside a companion bug in CoreDNS, CVE-2026-86003, where the encrypted transports accept unauthenticated DNS UPDATEs that the plaintext transports correctly reject.

I found this pair while scanning this morning's threat feed, and what surprised me was not the bugs. It was the silence: as of this writing there is no Hacker News thread and no dev.to article on either CVE ID that I could find. A heap overflow in a DNSSEC validator is exactly the kind of thing this site's readers run in production.

One honesty note up front: I do not operate a public recursive resolver fleet, so everything below is built from the CVE records, the NLnet Labs advisory, and the CoreDNS advisory on GitHub, not from a lab box. Treat the checks as a triage plan, and adapt the commands to your environment.

What actually broke in the DNSSEC validator?

Per the NLnet Labs advisory, a DNSKEY record whose owner name uses a compression pointer into its own RDATA can overflow the digest buffer Unbound uses while validating. Compression pointers are a legal part of the DNS wire format; they exist to shrink repeated names in a message. The validator, it turns out, did not expect a key record to point at itself.

The precondition is uncomfortable: the attacker needs to control a malicious zone and get your resolver to query it. If your users click links in email, they can be pointed at attacker-owned domains, and their machines will dutifully ask your recursive resolver to resolve those domains. That is the whole delivery mechanism. No authentication, no user interaction beyond a click.

The vendor's wording matters and I want to quote it carefully: remote code execution is possible through attacker controlled data. Possible, not demonstrated. No public exploit exists as of this writing, no KEV listing, and CISA's SSVC assessment marks exploitation as none. I am stating those absences on purpose, because absent telemetry is not absent risk when the attack path is "resolve a hostile domain."

Why does a self-referencing pointer overflow a heap buffer?

The compressed form of the bug is worth understanding, because it explains why version checks beat generic hardening here. When Unbound builds the digest of a DNSKEY RRset during validation, it walks the record data and expands any compression pointers it encounters. A pointer that lands back inside the same record's own data creates a cycle, and the code that assembles the digest buffer kept writing without a bound check on that path. Heap overflow, CWE-122, attacker-controlled content in the overflow.

I have not reproduced this in a lab, and I will not pretend I have. The mechanism above is my reading of the advisory's description plus the CWE mapping. What is verified beyond my reading: the affected range is every release through 1.26.0, the fix is 1.26.1, and that release shipped on September 16 as a security release that also closes CVE-2026-81634 and CVE-2026-82717, both rated HIGH, plus two MEDIUM issues. Patch to 1.26.1 and you clear the whole batch in one move.

# check the exact Unbound version on a resolver host
unbound -V | head -n 1
# or, if it runs in a container:
docker exec unbound unbound -V | head -n 1

Anything through 1.26.0 is in the affected range; 1.26.1 is the fix.

Why is the second CVE about the encrypted transports?

CoreDNS CVE-2026-86003 is the more interesting design lesson, in my opinion. CoreDNS serves DNS over multiple transports, and the code path that unpacks incoming messages differs between them. The classic UDP, TCP, and DoT listeners apply a default message-acceptance function that filters unusual message types. The newer listeners, DoH, DoQ, HTTP/3, and gRPC, call the unpack routine directly and skip that filter. Result: an unauthenticated client on the encrypted transport can send a DNS UPDATE message, something the plaintext path would have dropped.

What can an attacker do with an accepted UPDATE? Here the advisory is careful, and so am I: the impact is conditional. It requires an upstream that trusts CoreDNS's connection and accepts updates without end-to-end TSIG authentication. In that configuration, the advisory lists taking over names among the possible outcomes. CVSS 3.1 puts it at 7.5, CWE-441, a confused deputy: CoreDNS is not the thing being attacked, it is the trusted middleman being misused. The fix is CoreDNS 1.14.7.

If your platform runs CoreDNS, and Kubernetes clusters often do, the transport audit is the part most teams will skip. The question most deployments get wrong: "Do we run CoreDNS?" usually gets answered with "no, that's a Kubernetes thing." Then someone checks and finds it fronting every internal service. The encrypted-transport listeners are exactly the ones modern platforms enable by default because DoH looks like a feature. Your feature list is your attack surface, and nobody audits features that were somebody else's default.

Which of your resolvers are actually Unbound or CoreDNS?

Where do resolvers hide in a typical stack? This is the check I expect most readers to fail, and I would have failed it last quarter. Resolvers are infrastructure that nobody owns. The recursive resolver in the datacenter was configured by a contractor in 2021. The one on the CI runner came with the base image. The one on the Kubernetes node is whatever the CNI shipped. So inventory before you patch:

# which DNS servers do our hosts actually talk to?
# Linux hosts:
grep -r "nameserver" /etc/resolv.conf /etc/netplan/ 2>/dev/null
# then, on each resolver host:
ps aux | grep -E "unbound|coredns|named|dnsmasq" | grep -v grep

Expect surprises. Unbound in particular is the default in several router firmwares and many Linux hardening guides, which means it tends to exist on machines nobody remembers provisioning.

What do the scores actually tell you here?

The scoring on CVE-2026-81642 is a small case study in why single numbers mislead. The vendor's CVSS 4.0 score is 9.1, and that is the number most headlines carried. NVD's primary CVSS 3.1 score is 9.8. Both are "critical," but the gap between them reflects different assumptions about scope and exploitation maturity, and if your patch queue sorts on the number, the number you pick changes the queue's order.

My honest position: neither number tells you the thing that matters, which is whether your resolver is reachable with attacker-influenced queries. A 9.8 on a resolver that only internal hosts query, with egress filtering, is a Tuesday patch. The same 9.8 on an anycast public resolver is a tonight patch. Context beats score, and I do not think that is a controversial claim, but patch queues behave as if it were.

What should you check before you patch?

Four checks, in the order I would run them:

  1. Version check on every resolver host. Unbound at or above 1.26.1, CoreDNS at or above 1.14.7. The two commands above cover the common shapes.

  2. Exposure check. For each Unbound instance: does it answer queries from networks that can reach attacker-controlled domains? Any recursive resolver your users' browsers reach is in scope, because the delivery mechanism is ordinary web browsing.

  3. CoreDNS transport audit. Which listeners are enabled? If DoH, DoQ, HTTP/3, or gRPC are on, check whether the upstream accepts DNS UPDATEs and whether TSIG protects that path end to end. If the upstream requires TSIG, the conditional impact mostly collapses.

  4. Log check for the interim. Neither CVE has known exploitation, but both are automatable per CISA's SSVC data, which means a scanner-friendly exploit is plausible. Watch for DNSKEY-heavy queries from unknown sources against your resolvers, and unusual UPDATE messages on encrypted transports.

One caveat on check 4: I derived those watch items from the vulnerability mechanics, not from any published detection guidance. I could not find IOCs for either CVE in the sources I checked. If a vendor or CERT publishes detection logic, prefer theirs.

Should the score or the blast radius drive the queue?

Here is the argument I expect in the comments, and I hold it loosely: I think the resolver deserves the same threat-model treatment as the CI system got last year, where the lesson was that choke points with trust spread wide deserve patch priority out of proportion to their CVSS. A recursive resolver sees every domain every user wants to visit. A heap overflow in its validation path, reachable by resolving an attacker's domain, is about as wide as trust spread gets.

The counterargument is fair too: no exploitation, no public exploit, twelve days of quiet, and resolvers are also annoying to restart. Reasonable people can order these two facts differently.

Where does your queue put a 9.8 with zero KEV presence on infrastructure everyone depends on?

Genuinely curious, because my own answer changed twice while writing this.

If this angle was useful, I have written before about the shape of same-day CVE batches in agent sandboxes ( 2 CVSS 9.8 Agent Sandbox CVEs Landed the Same Day ), about what a three-hour supply-chain window means for pinned dependencies ( the LiteLLM supply chain backdoor ), and about a scanner rule that only caught half its bug class ( two ways to reuse a privileged CI token ). Same habit in all three: read the record before the headline.

Primary sources: NLnet Labs advisory for CVE-2026-81642 , the NVD records for CVE-2026-81642 and CVE-2026-86003 , GHSA-9gm5-9rfh-m6vx for CoreDNS, and the oss-sec archive post (seclists.org, 2026/q3/800) confirming the full 1.26.1 fix list.

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.