Mar 6, 2026·5 min read·3 visits
The CoreDNS `loop` plugin < 1.14.2 generates predictable loop detection queries using `math/rand` seeded with the current time. Attackers can guess the query name or read it from logs, then send matching packets to the server. This triggers a false positive loop detection that calls `log.Fatalf`, crashing the DNS service instantly.
CoreDNS, the default DNS server for Kubernetes, contains a critical Denial of Service (DoS) vulnerability in its `loop` detection plugin. The plugin uses a non-cryptographically secure pseudo-random number generator (PRNG) seeded with the current timestamp to generate self-test query names. An unauthenticated remote attacker can predict this seed or observe the query in logs to craft a matching UDP packet. Upon receiving a response that matches the predictable query name, the CoreDNS process triggers a fatal error and terminates, leading to a complete service outage.
CoreDNS is the standard DNS server for Kubernetes clusters, handling service discovery and internal name resolution. To prevent infinite forwarding loops—where CoreDNS forwards a query to itself or a cycle of upstream servers—the loop plugin performs a self-test during startup. It generates a random query name (qname) and sends an HINFO query to its own listening address. If the server receives this specific query back, it assumes a forwarding loop exists.
The vulnerability, tracked as CVE-2026-26018, resides in how this self-test is implemented. The mechanism relies on a predictable random number generator to create the qname. Furthermore, the failure state for detecting a loop is catastrophic: the plugin invokes log.Fatalf(), which calls os.Exit(1). This design flaw transforms a logic check into a kill switch that can be triggered remotely by any attacker capable of sending UDP packets to the DNS port, resulting in a denial of service.
The vulnerability stems from the intersection of two distinct weaknesses: Insecure Randomness (CWE-337) and Improper Handling of Exceptional Conditions (CWE-755).
1. Predictable Seed Generation
The loop plugin initializes its random number generator using Go's math/rand package, seeded with time.Now().UnixNano(). In computing environments like Kubernetes, the startup time of a pod is often predictable or observable via API events. An attacker can narrow down the seed search space to a few milliseconds, allowing them to brute-force the sequence of random numbers used to generate the qname. Additionally, in configurations where logs are centralized (e.g., ELK stacks), the query name is often logged during retries, leaking the secret directly.
2. Fatal Error on Trigger
The most critical flaw is the reaction to a positive detection. When the plugin's counter (l.seen()) exceeds the threshold of 2 events, it executes log.Fatalf. In the Go standard library, this function logs the message and immediately terminates the process with exit code 1. There is no recovery mechanism, no backoff, and no graceful degradation. The process simply dies, forcing the container orchestrator to restart it, potentially leading to a CrashLoopBackOff if the attack persists.
The following analysis highlights the vulnerable logic in plugin/loop/setup.go and plugin/loop/loop.go compared to the remediation strategies employed in version 1.14.2.
In the vulnerable version, the PRNG is seeded with the current time, making the sequence deterministic if the startup time is known. The detection logic uses a fatal exit.
// plugin/loop/setup.go
// VULNERABILITY: PRNG seeded with predictable timestamp
var r = rand.New(time.Now().UnixNano())
func qname(zone string) string {
// Generates a predictable sequence based on the timestamp seed
l1 := strconv.Itoa(r.Int())
l2 := strconv.Itoa(r.Int())
return dnsutil.Join(l1, l2, zone)
}
// plugin/loop/loop.go
if l.seen() > 2 {
// VULNERABILITY: Fatalf calls os.Exit(1), killing the server
log.Fatalf("Loop (%s -> %s) detected for zone %q...", ...)
}The fix replaces the insecure PRNG with crypto/rand, which uses the operating system's entropy source, making prediction impossible. Crucially, the fatal exit is replaced with a standard error log, preventing the process from terminating.
// plugin/loop/setup.go
import "crypto/rand"
func qname(zone string) string {
// FIX: Use cryptographically secure random number generation
// No longer relies on time-based seeding
b := make([]byte, 8)
rand.Read(b)
return dnsutil.Join(hex.EncodeToString(b), zone)
}
// plugin/loop/loop.go
if l.seen() > 2 {
// FIX: Replaced Fatalf with Errorf. The server stays alive.
// The plugin disables itself for this zone but does not crash CoreDNS.
log.Errorf("Loop (%s -> %s) detected for zone %q, disabling loop check", ...)
l.disable()
}Exploiting this vulnerability requires sending UDP packets that mimic the loop detection probe. The attack is highly effective during periods of network instability when the plugin enters a retry loop.
Prerequisites
Attack Vector 1: Log Leakage
In many Kubernetes clusters, logs are aggregated to a system visible to developers. During network degradation, the loop plugin logs failed probes, including the specific qname (e.g., 182739485.92837465.example.org). An attacker simply reads this log entry and sends 3 HINFO queries with that name to the server. The server counts these as "seen" and terminates.
Attack Vector 2: Seed Brute-forcing
ContainerStarted event to get the exact nanosecond timestamp.math/rand with the observed timestamp +/- a small delta.qnames and sprays HINFO queries to the DNS server.The impact of this vulnerability is high (CVSS 7.5) because it affects the availability of the entire cluster's networking capability.
Operational Impact
service-name.namespace, causing cascading failures across applications.CrashLoopBackOff state.Security Posture This is a purely destructive attack (Availability). It does not grant the attacker data access (Confidentiality) or the ability to modify records (Integrity), but the loss of DNS is often sufficient to halt all business operations in a cluster.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
CoreDNS CNCF | < 1.14.2 | 1.14.2 |
| Attribute | Detail |
|---|---|
| CVE ID | CVE-2026-26018 |
| CVSS v3.1 | 7.5 (High) |
| Attack Vector | Network (UDP) |
| CWE | CWE-337 (Predictable Seed) |
| CWE | CWE-770 (Resource Allocation) |
| Exploit Status | PoC Available |
| KEV Listed | No |
Use of PRNG with predictable seed allowed attackers to guess internal state.