Listen to this Post
How CVE-2025-47950 (incomplete fix regression) works:
The CoreDNS DoQ server uses a global worker pool (streamProcessPool) to limit concurrent stream processing. When the pool is full, the server still spawns a new goroutine per accepted QUIC stream that waits indefinitely for a worker token via a select default branch. This creates an unbounded backlog of waiting goroutines. Additionally, the DoQ message framing uses blocking io.ReadFull() calls with no per-stream read deadline when reading the 2-byte length prefix and message body. An attacker opens many QUIC streams (e.g., 60 connections × 256 streams = 15360 streams) but sends only 1 byte on each stream. The io.ReadFull() blocks waiting for the second byte, pinning all worker goroutines. Because each blocked stream consumes a goroutine (either worker or waiter), memory and goroutine count grow without bound. Even with a small configured worker_pool_size, the server cannot reject or timeout stalled streams. This leads to memory exhaustion and OOM-kill, causing a denial of service. The issue is a regression of the earlier CVE-2025-47950 fix, which did not fully address the per-stream blocking reads nor the unbounded waiter goroutines.
dailycve form:
Platform: CoreDNS
Version: All prior
Vulnerability: DoQ stream
Severity: Medium
date: 2026-04-28
Prediction: Patch 2026-05-12
What Undercode Say:
Monitor CoreDNS memory and goroutines during attack
watch -n 1 'ps aux | grep coredns | grep -v grep | awk "{print \$6}" && curl -s http://localhost:9153/metrics | grep go_goroutines'
Simulate partial-stream flood (PoC)
git clone https://github.com/coredns/coredns && cd coredns
Edit consts in doq-dos-repro.py: COREDNS_BIN, streams_per_conn=256, conns=60
python3 ./doq-dos-repro.py
Check RSS and goroutine explosion
cat /tmp/vh-f003-doq-mem-regression/results.json
Expected: rss_kib >130000, go_goroutines >15000
Exploit:
Remote attacker sends multiple QUIC connections, each opening hundreds of streams. On each stream, transmit exactly one byte (partial DoQ length prefix) then halt. The server’s io.ReadFull() blocks forever, consuming worker tokens and spawning waiting goroutines. No authentication required. Example using quic-go client with custom stream write of [bash] and no close.
Protection from this CVE:
- Apply vendor patch when available (add per-stream read deadlines, e.g., SetReadDeadline in readDOQMessage).
- Limit total QUIC streams per connection via quic.Config.MaxStreams.
- Deploy network rate limiting for UDP/443 (DoQ port) to restrict flood rate.
- Monitor goroutine count and OOM-kill events, auto-restart service.
Impact:
Unauthenticated remote denial of service. Memory exhaustion leads to OOM-kill of CoreDNS process, causing DNS resolution outage for all clients relying on the DoQ server. Encrypted DNS transport becomes unavailable. Attack scales with minimal bandwidth (1 byte per stream). No recovery without manual restart or fix.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

