The whole incident in one picture: same query, and the only difference is one signed record proving a negative.
DNSSEC is famous for signing what exists. This incident is about the other half of the job: proving what does not.
The setup: a perfectly ordinary delegation
The dnsdoh.art zone is DNSSEC-signed, with its chain anchored at the .art registry. One subdomain, leak.dnsdoh.art, is delegated by NS record to a separate nameserver: it powers our DNS leak test, which needs to observe queries for unique random names arriving from resolvers. The delegation is intentionally insecure - no DS record at the parent, so the child zone is outside the signed chain. That is not a misconfiguration. Delegating a subdomain to infrastructure that does not do DNSSEC, without breaking the parent's signatures, is exactly what insecure delegations are for, and the RFCs support the pattern explicitly.
For this to work, one thing must hold: when a validating resolver asks the parent "does leak.dnsdoh.art have a DS record?", the parent has to answer with proof. Not silence - proof. This incident is what happens when a provider serves the delegation but skips the proof.
The symptom: SERVFAIL with a diagnosis attached
In early May the zone was hosted on bunny.net's DNS. Names under the delegation started failing on every major validating resolver. This is what Google's 8.8.8.8 returned on 7 May (trace preserved from the incident):
$ dig @8.8.8.8 440b52664ed24b3c-06-haj18hw1-w1nrvb4.leak.dnsdoh.art DS +dnssec
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL
; EDE: 22 (No Reachable Authority):
; (At delegation leak.dnsdoh.art for …leak.dnsdoh.art/ds)Two details in that answer do the diagnostic work. SERVFAIL alone says almost nothing - it is DNS's shrug. But the EDE line is an Extended DNS Error (RFC 8914), a machine-readable diagnosis modern resolvers attach to failures: code 22 means the resolver could not establish a usable authority for the name, and the parenthetical even names the delegation where it gave up. If you debug DNS and are not reading EDE codes yet, start - they regularly turn an afternoon of guessing into one dig.
The site itself was fine. The parent zone validated. Only the delegated subtree was dead, and only through validating resolvers - which today means Google, Cloudflare, Quad9 and most ISP resolvers. A subtree that fails exactly there and nowhere else points at one layer: the security status of the delegation itself.
The rule: absence must be proven, not implied
DNSSEC validation walks down from the root: each zone's DS record at its parent vouches for the child's keys. When a delegation has no DS record, the resolver needs to know that securely, because the alternative is catastrophic: if "no DS in the answer" were simply taken at face value, an attacker in the middle could strip the DS record out of any referral and downgrade the entire subtree to unsigned, silently disabling DNSSEC for it. Spoofing the answer would become trivial again.
So RFC 4035 (section 3.1.4) requires the parent to prove the negative: a DS query for an unsigned delegation must be answered with an NSEC or NSEC3 record, signed by the parent, whose type bitmap shows that a DS record does not exist at that name. The resolver checks the signature, sees no DS bit, and concludes: this delegation is verifiably insecure - unsigned on purpose, not under attack. Resolution proceeds. NSEC and NSEC3 exist precisely for this kind of authenticated denial.
A provider that signs a zone but never emits that proof produces the failure we saw: the resolver cannot distinguish "no DS ever existed" from "the DS was just stripped by an attacker", must assume the worst, and marks the delegation bogus. One missing record, and the whole subtree returns SERVFAIL for the majority of the internet.
Six providers, one question
Because a DS query is answered by the parent's nameservers alone, the same zone hosted at different providers can be compared directly. During the incident we created identical test zones at several providers and asked each one the same question. The May results, from the incident traces:
| Provider | DS answer for the insecure delegation (May 2026) | Verdict |
|---|---|---|
| bunny.net | NS + RRSIG only, no NSEC | broken - subtree SERVFAILs |
| AWS Route 53 | NSEC … NS RRSIG NSEC | correct, minimal bitmap |
| IBM NS1 | NSEC … NS RRSIG NSEC | correct, minimal bitmap |
| Gcore | NSEC … A NS HINFO TXT AAAA LOC SRV CERT SSHFP … | correct - inflated bitmap, DS absent |
| deSEC | NSEC3 (white lie) … NS | correct, NSEC3 form |
| Google Cloud DNS | NSEC3 (salted) … NS | correct, NSEC3 form |
Five different implementations, five valid answers, one genuine bug. The broken one, verbatim from 7 May: the AUTHORITY section carried the delegation and its signature - and nothing else.
$ dig @kiki.bunny.net leak.dnsdoh.art DS +dnssec
;; status: NOERROR · ANSWER: 0, AUTHORITY: 2
;; AUTHORITY SECTION:
leak.dnsdoh.art. 300 IN NS ns.leak.dnsdoh.art.
leak.dnsdoh.art. 300 IN RRSIG NS 13 3 300 …
;; no NSEC, no NSEC3 - DS absence is asserted by silence, which validators rejectAnd a correct one from the same day, Route 53's minimal form - the NSEC's type bitmap lists only what exists at the delegation point (NS RRSIG NSEC), and DS is conspicuously not among them:
$ dig @ns-592.awsdns-10.net leak.dnsdoh.art DS +dnssec
;; status: NOERROR · ANSWER: 0, AUTHORITY: 4
;; AUTHORITY SECTION (SOA + RRSIG omitted):
leak.dnsdoh.art. 86400 IN NSEC leak\000.dnsdoh.art. NS RRSIG NSEC
leak.dnsdoh.art. 86400 IN RRSIG NSEC 13 3 86400 …Reporting it, and what made the report work
We opened a ticket with bunny.net on 6 May. Paraphrasing the exchange rather than reprinting it: the report stated the RFC requirement (4035 §3.1.4), gave a one-line reproduction against their own nameserver, showed the resulting SERVFAIL with EDE 22 from public resolvers, and - after a day without movement - added the same query answered correctly by four other providers. Support escalated it to their DNS team; within a day the team confirmed a fix was ready, and it was deployed platform-wide shortly after. The ticket closed on 27 May with the issue resolved globally. Meanwhile we had already migrated the production zone, first to Route 53 and eventually to Google Cloud DNS, because uptime could not wait on a vendor timeline - but the fix now benefits every bunny.net customer running a signed zone with delegations.
A parallel pre-sales question to Gcore produced a different kind of answer: their support confirmed NSEC support (not NSEC3), and we passed our observations about their inflated-but-conformant NSEC bitmap to their engineering team. No commitment was made, but the feedback was acknowledged.
The anatomy of the report that got a platform bug fixed in days, as a reusable checklist:
- A one-line reproduction against the vendor's own infrastructure - dig @their-ns yourzone DS +dnssec - that any engineer can run in ten seconds.
- The exact standard citation, not "DNSSEC seems broken". A section number turns a debate into a lookup.
- The observed impact from the user side: SERVFAIL + EDE 22 from named public resolvers, so the severity is undeniable.
- A cross-provider comparison proving the zone configuration is not the problem. Four providers answering correctly for the identical delegation removes every "works as intended" exit.
Nothing in that list requires insider access. Every piece is a public dig query.
Verified today: the fix is real
We told bunny.net we would verify the fix once deployed, and this article is that verification. Our old test zone still answers on their nameservers, which makes the before/after directly comparable. The same query that returned a bare delegation in May, executed on 10 July:
$ dig @kiki.bunny.net leak.dnsdoh.art DS +dnssec
;; status: NOERROR
;; AUTHORITY SECTION (SOA + RRSIGs omitted):
leak.dnsdoh.art. 900 IN NSEC \000.leak.dnsdoh.art. NS RRSIG NSEC
leak.dnsdoh.art. 900 IN RRSIG NSEC 13 3 900 …A minimal, correct NSEC - the same shape Route 53 and NS1 produce. Credit where due: the bug was real, the report was taken seriously, and the fix that shipped is the textbook one.
Gcore's answer changed too. In May their NSEC carried an inflated type bitmap (claiming A, TXT, TLSA and a dozen other types at a pure delegation point - untidy, though conformant, since the DS bit was correctly absent). Re-tested on 10 July, their nameservers now return the minimal form as well:
$ dig @ns1.gcorelabs.net leak.dnsdoh.art DS +dnssec
leak.dnsdoh.art. 300 IN NSEC \000.leak.dnsdoh.art. NS RRSIG NSECWe cannot attribute Gcore's change to our feedback with certainty - anycast fleets change for many reasons - but the shape we flagged is gone from every node we can reach. The production zone, meanwhile, lives on Google Cloud DNS, whose salted NSEC3 answer for the same question is in the next section.
Three shapes of a correct answer
Comparing providers surfaced something useful beyond the bug: authenticated denial comes in three valid dialects, and knowing them keeps you from mistaking a correct answer for a wrong one. All three below are real answers for our delegation, captured 10 July.
1. Minimal NSEC (Route 53, NS1, bunny.net post-fix). The bitmap lists exactly the types present at a delegation point and nothing more. The \000 next-name is the tightest possible span, disclosing no real neighbouring names:
leak.dnsdoh.art. IN NSEC \000.leak.dnsdoh.art. NS RRSIG NSEC2. White-lie NSEC (RFC 4470 family). The server synthesizes an NSEC on the fly covering only the queried name, to prevent zone walking. Gcore's May answer was this dialect with an over-generous bitmap; the technique itself is legitimate - what matters for the delegation is solely that DS is absent from the bitmap.
3. NSEC3 (deSEC, Google Cloud DNS). The name is hashed, so the proof leaks nothing about other names in the zone. Two live examples - deSEC's unsalted white-lie variant and Google Cloud DNS's salted form, which is what production answers today:
# deSEC - NSEC3, no salt, bitmap "NS" only
$ dig @ns1.desec.io leak.dnsdoh.art DS +dnssec
5ad2uleg…fsr.dnsdoh.art. IN NSEC3 1 0 0 - GU9Q1J29…BQC4 NS
# Google Cloud DNS - NSEC3 with salt and one extra iteration (production today)
$ dig @ns-cloud-e1.googledomains.com leak.dnsdoh.art DS +dnssec
7d3vj32a…5ke2.dnsdoh.art. IN NSEC3 1 0 1 7009EC2D54AAB8B6 8MB0V6NS…L1D5 NSDifferent privacy trade-offs, identical cryptographic effect: the parent proves, under its own signature, that no DS exists. Any of the three satisfies a validator. Only silence does not.
Audit your provider before you depend on it
If you run a signed zone and delegate any subdomain without a DS - or ever might - this is a five-minute pre-flight check, and it works on a throwaway test zone before you migrate anything:
# 1. in your (signed) zone at the candidate provider, create an insecure delegation:
# sub.example.com NS ns-of-anything.example.net (no DS record)
# 2. ask the provider's own nameserver for the DS:
$ dig @their-ns1 sub.example.com DS +dnssec
# PASS: AUTHORITY contains NSEC or NSEC3 (+RRSIG) whose bitmap has no DS
# FAIL: only NS/SOA/RRSIG, no NSEC record at all
# 3. confirm end to end through a validating resolver:
$ dig @8.8.8.8 sub.example.com NS +dnssec
# PASS: NOERROR
# FAIL: SERVFAIL with EDE 22 - the delegation is being treated as bogusStep 2 is the one that isolates responsibility: it queries the provider's authoritative server directly, so caches, forwarders and your own configuration are all out of the picture. Whatever comes back is what the provider generates, full stop. That is also why the same query made the bug report irrefutable.
The broader habit this incident reinforces: providers differ in the corners, and you should test the corner you depend on. Every provider in our matrix handles ordinary signed records flawlessly. The differences - and the one outright bug - lived in a boundary case that marketing pages never mention and most customers never trigger. One dig before migrating is cheaper than a deindexed subtree after.
The same table, two months later
To close the story where it started: the May matrix, re-executed on 10 July 2026 against the same nameservers. Our test zones still answer at every provider except Route 53, where we removed the zone after migrating (its May answer was correct).
| Provider | DS answer for the insecure delegation (10 July 2026) | Verdict |
|---|---|---|
| bunny.net | NSEC … NS RRSIG NSEC | fixed - correct minimal proof |
| AWS Route 53 | NSEC … NS RRSIG NSEC | correct - the reference answer (May; test zone since removed) |
| IBM NS1 | NSEC … NS RRSIG NSEC | correct, unchanged |
| Gcore | NSEC … NS RRSIG NSEC | correct - inflated bitmap gone, now minimal |
| deSEC | NSEC3 (white lie) … NS | correct, unchanged |
| Google Cloud DNS | NSEC3 (salted) … NS | correct - hosts the production zone |
In May this table held one genuine bug and one oddity. In July every nameserver we can still query answers correctly, and even the oddity is gone. That is the outcome worth reporting bugs for: the broken provider fixed its platform for every customer, and a public record of the fix now exists that anyone can re-run with a single dig.
The rest of the zone
This delegation is one corner of a zone built to be verifiable end to end - DNSSEC, DANE pins, ECH, discovery records - all public, all checkable with the same tool.
Anatomy of a Hardened DNS ZoneRelated reading: what DNSSEC is and what it signs, DNS record types including NSEC and DS, and the attacks that authenticated denial exists to stop.
Ozy-666 builds and operates dnsdoh.art, an encrypted DNS resolver serving DoH, DoH3, DoT and DoQ. This account is first-hand: the delegation, the failing zone, the provider tickets and the migrations were all his, and every dig trace in this article was executed against live infrastructure - the May traces during the incident, the July ones while writing.