Build1 publisher3 min readPublished Updated
Cloudflare's DoH JSON set AD=true on 10 of 20 example.com A queries without the do parameter
Cloudflare's DNS-over-HTTPS JSON set the DNSSEC AD flag on only 10 of 20 queries for signed example.com, a dev.to test found. Google's resolver marked the same records as validated, so a browser tool that trusts one Cloudflare flag can call a signed zone unsigned.
The Engineer · Build desk
Drafted by a language model from the sources cited here and checked against its claim ledger before publication. How we use AISend a correction

What happened
- The JSON format both resolvers serve has no RFC, because RFC 8484 defines only the binary application/dns-message format.
- The same lookup over Cloudflare's DoH a minute later returned Status 2, SERVFAIL, with an EDE(9) comment about a missing DNSKEY.
- Cloudflare returns the Comment field as an array of strings, while Google returned it as one string reading "Response from 108.162.192.162."
- According to the post's author, Cloudflare's documentation does not say when its JSON endpoint sets the AD bit.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- decision A browser DNSSEC checker cannot mark a zone unsigned from one Cloudflare AD false. It needs repeat queries or agreement from a second resolver before it shows a verdict.
- exposure On machines running fake-IP proxies, local dig output shows the proxy's reply. DNS troubleshooting there has to go over DoH, where TLS ends at the resolver and the proxy cannot change the answer.
- constraint Cloudflare matches Google's schema by choice, and no RFC holds either provider to it. Clients have to be tested against both endpoints and tested again when either one changes.
Cloudflare's JSON documentation explains why the two look alike: "There is no agreed-upon JSON schema for DNS over HTTPS in the Internet Engineering Task Force (IETF), so Cloudflare has chosen to follow the same schema as Google's DNS over HTTPS resolver." [3] The same page warns that "behavior might be different between providers." [4] The dev.to post that tested both endpoints claims five differences [19]. Its author argues that reading either endpoint as dig with JSON output can report a signed zone as unsigned, break a DKIM key, or show NOERROR when nothing answered [19]. The available text of the post stops partway through the AD section, before the DKIM example and the remaining differences.
The AD field reports the Authenticated Data bit, meaning the resolver validated the answer with DNSSEC [22]. At 02:59:38 UTC Cloudflare returned AD false for example.com [13]. Then its value changed. The 20-query run behind the 50% rate [1] left out the do parameter, and a single query at 03:09 UTC came back true [14]. The post also counts AD over 30 runs per query between 03:05 and 03:08 UTC [20].
The NOERROR case comes from the laptop, which was running a proxy app in fake-IP mode [7]. The proxy caught the UDP packet addressed to 1.1.1.1 and answered it with an address from 198.18.0.0/15 and a TTL of 1 [8] [7]. RFC 5735 says that block "has been allocated for use in benchmark tests of network interconnect devices," and RFC 6890 marks it "Global: False" [9]. The example configuration in mihomo's DNS documentation sets fake-ip-range: 198.18.0.1/16 [10]. The test name, dnssec-failed.org, is broken on purpose. It is the failure example in Google's JSON API documentation, and a validating resolver returns SERVFAIL for it [11].
The DoH request went through the same proxy. TLS ends at Cloudflare, so the proxy could not change the answer [12]. The resolvers deserve credit for making that available to a plain web page. Both send access-control-allow-origin: *, so fetch() works without a backend [2]. RFC 8484 describes the use case as "allowing web applications to access DNS information via existing browser APIs in a safe way consistent with Cross Origin Resource Sharing (CORS)" [21].
The raw example.com replies also show smaller differences, and a parser hits these first. Cloudflare echoed the question name as "example.com". Google echoed it as "example.com." with a trailing dot [16]. The post's Cloudflare requests send an accept: application/dns-json header, and its Google request sends none [18]. Suppose a client compares names by exact string match, or expects Comment to always be the same type. It will pass tests against one provider and fail against the other.
Every figure comes from one macOS laptop running curl 8.7.1 and Node 24.14, over a 16-minute window on 2026-09-30 [6] [2]. The author notes that TTLs, signatures and CDN addresses change [6]. The 50% rate would only hold elsewhere if Cloudflare set AD the same way at every location and in every cache state, and the post measured one network path. In my context, a browser tool that shows a DNSSEC verdict, I would treat AD false from Cloudflare as unknown. I would show "unsigned" only when both resolvers agree.
What to watch
- Cloudflare documenting when its JSON endpoint sets AD for queries sent without the do parameter.
- A rerun of the AD counts from another network and date, to test whether the 50% rate holds beyond one laptop's path.
- The post's DKIM example, and whether it reproduces against both Cloudflare and Google.