DEV Community

takahiro hashito
takahiro hashito

Posted on

CVE-2026-81642: a DNSKEY compression pointer overflows Unbound's digest buffer

Background

I run a small fleet of static sites, and every day a scheduled job of mine picks one recent CVE (a public identifier assigned to one specific vulnerability) and writes up how to deal with it. Today the queue handed me an Unbound advisory, and I had to stop and read it twice.

I am not a DNS specialist. I keep a recursive resolver running because I want my own name resolution, not because I enjoy it. So when a DNS resolver gets a 9.8, I want to know exactly two things: am I in scope, and what do I turn off until I can patch.

This is that write-up. It is a summary of the primary sources, not original research.

What the bug is

CVE-2026-81642 affects NLnet Labs Unbound up to and including 1.26.0. NVD (the US National Vulnerability Database) publishes the affected range as "less than 1.26.1". Unbound is a validating, recursive, caching DNS resolver.

A few acronyms first, because the advisory assumes them:

  • CVSS (a 0-to-10 score for how severe a vulnerability is, where 7.0 and above counts as High) is v3.1 base score 9.8 here, rated CRITICAL.
  • DNSSEC is the signature layer on top of DNS. A DNSKEY record holds the public key a resolver uses to verify those signatures.
  • CWE-122 is the bug class: a heap-based buffer overflow.

The flaw is in the DNSSEC validator. When Unbound digests a DNSKEY, a record whose owner name is a compression pointer to its own RDATA can push the write past the end of the digest buffer.

Two things follow from the advisory. The reachable outcome is denial of service, and remote code execution is described as possible through attacker-controlled data. The attacker's path is to control a malicious zone and then get a vulnerable Unbound to query it.

That last part is why the score is what it is. The CVSS vector is CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H — network reachable, no privileges, no user interaction. A recursive resolver's whole job is to go and fetch names it has never seen, so "make it query my zone" is not a high bar.

Am I in scope

Check the version first. Anything below 1.26.1 is in scope.

unbound -V
Enter fullscreen mode Exit fullscreen mode

Then check that the running process is the binary you just inspected. If the package was upgraded but the service was never restarted, the on-disk version is new and the process is still old.

systemctl status unbound
unbound-control status
Enter fullscreen mode Exit fullscreen mode

If you installed from a distribution package, the version string may not match upstream, because distributions backport fixes onto older numbers. In that case the version alone will not answer the question — look for CVE-2026-81642 in the package changelog.

dpkg -l unbound
rpm -q unbound
Enter fullscreen mode Exit fullscreen mode

The bug lives in the DNSSEC validator, so it is worth confirming that validation is actually enabled in your config.

unbound-checkconf -o module-config
grep -E "trust-anchor|auto-trust-anchor-file|module-config" /etc/unbound/unbound.conf
Enter fullscreen mode Exit fullscreen mode

The thing I nearly missed: Unbound ships inside other things. Routers, appliances, container images, and bundled components. I have no memory of installing it on at least one box where it turned out to be running. Checking firmware and image manifests is not wasted effort here.

What I can do before patching

The advisory I read lists no workaround. So everything below is derived from the CVSS vector rather than from the vendor, and you should confirm side effects with your own vendor before applying any of it.

Stop being reachable by things that should not reach you. Restrict access-control to networks you manage. The cost is that legitimate clients outside that range stop resolving.

unbound-checkconf -o access-control
Enter fullscreen mode Exit fullscreen mode

Close 53/udp and 53/tcp at the perimeter. Obvious, but worth confirming rather than assuming.

Temporarily forward instead of recursing. If you forward to an already-patched upstream, you stop walking out to attacker-controlled zones yourself. The cost is that you now depend on that upstream's availability, and you need to know it is not carrying the same flaw.

Check the blast radius. Confirm the daemon runs as its own user and whether chroot is on. This does not fix the bug; it narrows what code execution would reach.

unbound-checkconf -o username
unbound-checkconf -o chroot
Enter fullscreen mode Exit fullscreen mode

I did consider disabling DNSSEC validation, since that is where the bug is. I would rather not. Turning it off trades a heap overflow for losing tamper detection on every answer, which is a bad swap if you can just upgrade instead.

The fix

Upgrade to 1.26.1 or later. That is the only version the NVD range supports calling fixed.

Notes from doing it:

  • Save your config and trust anchor files first.
  • Whether a restart is required depends on how you installed it, so I am not going to claim it either way. After upgrading, confirm the running version with unbound-control status.
  • If you have more than one resolver, do them one at a time and watch that resolution keeps working.

CISA's KEV catalog (the US government list of vulnerabilities with confirmed exploitation in the wild) does not list this CVE. Being on that list comes with a remediation deadline for US federal agencies. Not being on it means no deadline — it does not mean the bug is hard to reach. The vector still says no authentication and no user interaction. I would not use "no deadline" as a reason to defer this one.

Looking for signs you were hit

No public indicators of compromise that I could find. So this is inference from the bug class, not detection of a known pattern.

Heap corruption tends to show up as a crash before it shows up as anything clever. Start there.

journalctl -u unbound --since "7 days ago" | grep -iE "segfault|signal|core|killed|restart"
coredumpctl list unbound
dmesg -T | grep -iE "unbound|segfault"
Enter fullscreen mode Exit fullscreen mode

Then look at validation failures and SERVFAIL rates, in proportion to your normal traffic rather than as raw counts.

unbound-control stats_noreset | grep -E "num.answer.rcode.SERVFAIL|num.rrset.bogus"
Enter fullscreen mode Exit fullscreen mode

And on the host itself, the generic post-exploitation checks: unexpected child processes, new files where config lives.

ps -ef --forest | grep -A3 unbound
find /etc/unbound /var/lib/unbound -newermt "7 days ago" -type f
Enter fullscreen mode Exit fullscreen mode

If you want the same thing in Japanese, with the same fact-checked version numbers, my write-up is here: https://ai-news.autoarticles.net/article/post_1790134098643_3ok48m

Order I would do it in

Today: run unbound -V. If it is below 1.26.1, check what can reach port 53 and narrow access-control on the spot.

This week: upgrade to 1.26.1 or later, and verify the running version afterwards rather than the installed one.

After that: write down every device and image that bundles Unbound, and put them on the same version-tracking list as the resolvers you installed on purpose. The boxes I forgot about are the ones that will still be on 1.26.0 next year.


This article is about my own side project. It was written with AI assistance.

Top comments (0)