A case study in dual-stack parsing bugs
Late in November 2022, Cloudflare’s bug bounty program received a critical report: certain DNS records could be used to bypass network policy controls and reach services bound to loopback addresses or other non-routable IPs on internal infrastructure. The report arrived on November 27, triggering incident response within the Security Incident Response Team (SIRT). A hotpatch went out three hours later, and a deeper fix and internal investigation followed.
A tricky interaction between DNS and proxy logic
The root cause turned out to be two separate bugs that, when combined, created a path around the company's security filters. The vulnerability centered on IPv4-mapped IPv6 addresses, which RFC 4291 defines as a way to embed an IPv4 address inside an IPv6 address. For example, 127.0.0.1 can be expressed as ::ffff:127.0.0.1.
::ffff:127.0.0.1| 80 bits | 16 | 32 bits | +--------------------------------------+--------------------------+ |0000..............................0000|FFFF| IPv4 address | +--------------------------------------+----+---------------------+The chain of events began in Cloudflare’s internal DNS system, which handles hostname-to-IP mapping for origin servers. When the DNS system received a query for a record that held an IPv4-mapped IPv6 address, it serialized the address as a string. The Go
netlibrary automatically converted::ffff:10.0.0.1into the string"10.0.0.1", but the DNS system still treated the record as an IPv6 response. The result was a DNS response containing{ipv6: "10.0.0.1"}.That malformed response was passed to the internal HTTP proxy responsible for forwarding traffic to customer origin servers. The proxy maintains two deny lists—one for IPv4 and one for IPv6—containing localhost and private IP ranges. Because the DNS response placed the address in the IPv6 field, the proxy compared the string
10.0.0.1against the IPv6 deny list. It didn’t match any entries there, so the address was allowed as an origin IP.The flaw wasn’t a question of failing to block a known-bad address, but rather a semantic mismatch: the address was checked against the wrong deny list entirely.
The proof-of-concept
The researcher’s exploit used two components: a DNS record and a Cloudflare Worker. The DNS record was an
AAAAentry pointing to an IPv4-mapped loopback address:exploit.example.com AAAA ::ffff:127.0.0.1The Worker contained code that attempted to make an HTTP connection to that hostname. When the Worker called a URL like
http://exploit.example.com, the proxy resolved the hostname, misidentified the IP family, and allowed the connection attempt to proceed to127.0.0.1on the server's loopback interface.curl https://proxy.example.com/json -d '{"url":"http://exploit.example.com:80/url_path"}'The attack could be scripted to probe multiple ports on the server. A similar DNS entry using an address like
::ffff:10.0.0.1could be used to reach services on internal, non-routable IPs as well.The practical impact depended on what the attacker could reach. A successful connection to a service on loopback or on another internal server would allow the attacker to attempt to bypass any authentication or security controls on that service. In practice, network ACLs have a small set of ports that must remain open, so the achievable access was limited to those allowed ports.
Containing the issue
The first patch addressed what the team believed was the fastest way to stop exploitation: preventing creation of DNS records that contained IPv6 addresses mapping to loopback or RFC 1918 IPv4 ranges. The fix was fully deployed and confirmed within three hours of the original report.
That measure was later determined to be incomplete. Attackers could host the same kind of records on external DNS servers, so the protection needed to be applied at the proxy layer as well.
Investigation and final fix
Two investigations ran in parallel. The first focused on root cause analysis, reproducing the issue with a proof-of-concept to debug the interaction between the DNS system and the proxy. The second reviewed logs for evidence that the vulnerability had been exploited in the wild prior to the report.
The log review turned up no evidence of prior exploitation. Cloudflare also scanned its DNS records for IPv4-mapped IPv6 addresses and found that all existing entries appeared to be for testing purposes.
The lasting fix was implemented in the proxy service. The proxy now validates IP addresses against the deny list for the actual parsed address family, rather than the family claimed by the DNS API response. The fix was verified in both test and production environments.
The broader lesson
This vulnerability is a useful reminder that network code often makes assumptions about data formats that don’t survive contact with real-world inputs. IP family identification and string serialization need to be handled consistently at every layer of the stack.
Cloudflare encourages security researchers to continue reporting issues through its bug bounty program on HackerOne, and says it supplements those reports with regular internal security reviews and third-party audits.



