Skip to content

GHSA-h75p-j8xm-m278 CVE-2026-26018 GO-2026-4635

CoreDNS Loop Detection Denial of Service Vulnerability

High Go
Severity
7.5 / 10
High · CVSS 3.1
Exploit chance (EPSS)
1.16%
Chance of exploitation in the next 30 days. Higher than 67.20% of scored vulnerabilities.
Known exploited
No
Not in CISA's catalog
Weakness
CWE-337 Predictable Seed in Pseudo-Random Number Generator (PRNG)
Fix
1.14.2
Upgrade github.com/coredns/coredns to this version or later

Description

Executive Summary

A Denial of Service vulnerability exists in CoreDNS's loop detection plugin that allows an attacker to crash the DNS server by sending specially crafted DNS queries. The vulnerability stems from the use of a predictable pseudo-random number generator (PRNG) for generating a secret query name, combined with a fatal error handler that terminates the entire process.


Technical Details

Vulnerability Description

The CoreDNS loop plugin is designed to detect forwarding loops by performing a self-test during server startup. The plugin generates a random query name (qname) using Go's math/rand package and sends an HINFO query to itself. If the server receives multiple matching queries, it assumes a forwarding loop exists and terminates.

The vulnerability arises from two design flaws:

  1. Predictable PRNG Seed: The random number generator is seeded with time.Now().UnixNano(), making the generated qname predictable if an attacker knows the approximate server start time.

  2. Fatal Error Handler: When the plugin detects what it believes is a loop (3+ matching HINFO queries), it calls log.Fatalf() which invokes os.Exit(1), immediately terminating the process without cleanup or recovery.

Affected Code

File: plugin/loop/setup.go

// PRNG seeded with predictable timestamp
var r = rand.New(time.Now().UnixNano())

// Qname generation using two consecutive PRNG calls
func qname(zone string) string {
    l1 := strconv.Itoa(r.Int())
    l2 := strconv.Itoa(r.Int())
    return dnsutil.Join(l1, l2, zone)
}

File: plugin/loop/loop.go

func (l *Loop) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
    // ... validation checks ...
    
    if state.Name() == l.qname {
        l.inc()  // Increment counter
    }

    if l.seen() > 2 {
        // FATAL: Terminates entire process
        log.Fatalf("Loop (%s -> %s) detected for zone %q...", ...)
    }
    
    // ...
}

File: plugin/pkg/log/log.go

func Fatalf(format string, v ...any) {
    logf(fatal, format, v...)
    os.Exit(1)  // Immediate process termination
}

Exploitation Window

The loop plugin remains active during the following conditions:

Condition Window Duration Attack Feasibility
Healthy startup 2 seconds Requires precise timing
Self-test failure (upstream unreachable) 30 seconds HIGH - Extended window
Network degradation Variable Depends on retry behavior

Attack Scenario

Primary Attack Vector: Network Degradation

When the upstream DNS server is unreachable (network partition, misconfiguration, outage), the loop plugin's self-test fails repeatedly. During this period:

  1. The loop plugin remains active for up to 30 seconds
  2. Each self-test attempt generates an HINFO query visible in CoreDNS logs
  3. An attacker with log access (shared Kubernetes cluster, centralized logging) can observe the qname
  4. The attacker sends 3 HINFO queries with the observed qname
  5. The server immediately crashes
┌──────────────────────────────────────────────────────────────────────────┐
│                         ATTACK TIMELINE                                  │
├──────────────────────────────────────────────────────────────────────────┤
│ T+0s     CoreDNS starts, PRNG seeded with UnixNano()                     │
│ T+0.5s   Self-test HINFO query sent (visible in logs)                    │
│ T+2s     Self-test fails (upstream timeout)                              │
│ T+3s     Retry #1 - counter resets, qname unchanged                      │
│ T+5s     Retry #2 - attacker observes qname in logs                      │
│ T+5.1s   ATTACKER: Send HINFO #1 → counter = 1                           │
│ T+5.2s   ATTACKER: Send HINFO #2 → counter = 2                           │
│ T+5.3s   ATTACKER: Send HINFO #3 → counter = 3 → os.Exit(1)              │
│ T+5.3s   SERVER CRASHES                                                  │
└──────────────────────────────────────────────────────────────────────────┘

Impact Assessment

Attack Requirements

Requirement Notes
Network Access Must be able to send UDP packets to CoreDNS port
Log Access Required to observe the qname (common in shared clusters)
Timing Extended window during network degradation
Authentication None required

Real-World Impact

CoreDNS is the default DNS server for Kubernetes clusters. A successful attack would:

  1. Disruption: All DNS resolution fails within the cluster
  2. Cascading Failures: Services unable to discover each other
  3. Restart Loop: If attack persists, CoreDNS enters crash-restart cycle
  4. Data Plane Impact: Application-level failures across the cluster

References

Affected versions

Go

PackageVulnerableFixed in
github.com/coredns/coredns
< 1.14.2
1.14.2

How to fix

Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.

github.com/coredns/coredns Go → 1.14.2

go
go get github.com/coredns/coredns@v1.14.2 && go mod tidy

Severity breakdown

CVSS 3.1 7.5

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
High

Weakness

CWE-337: Predictable Seed in Pseudo-Random Number Generator (PRNG)

A Pseudo-Random Number Generator (PRNG) is initialized from a predictable seed, such as the process ID or system time.

How to prevent it
  • Use non-predictable inputs for seed generation.
  • Architecture and Design, Requirements: Use products or modules that conform to FIPS 140-2 [REF-267] to avoid obvious entropy problems, or use the more recent FIPS 140-3 [REF-1192] if possible.
  • Implementation: Use a PRNG that periodically re-seeds itself using input from high-quality sources, such as hardware devices with high entropy. However, do not re-seed too frequently, or else the entropy source might block.

References

Timeline

  1. Published
  2. Last updated by the source
  3. Latest EPSS score
AdvisorySeverityWhy it's related
GHSA-9gm5-9rfh-m6vx
CoreDNS DoH/DoQ/gRPC bypass UPDATE rejection enforced on UDP/TCP
High Also affects github.com/coredns/coredns
GHSA-mrg3-qvqr-jw29
CoreDNS: Unauthenticated memory exhaustion in custom transports
High Also affects github.com/coredns/coredns
GHSA-74w3-63xv-x9mv
CoreDNS `k8s_external` headless AXFR can emit an empty transfer batch that panics the `transfer` plugin
Low Also affects github.com/coredns/coredns
GHSA-vp29-5652-4fw9
CoreDNS has TSIG authentication bypass on gRPC and QUIC transports
Critical Also affects github.com/coredns/coredns
GHSA-qhmp-q7xh-99rh
CoreDNS has TSIG authentication bypass on DoT, DoH, DoH3, DoQ, and gRPC
High Also affects github.com/coredns/coredns
GHSA-h8mm-c463-wjq3
CoreDNS' transfer stanza selection uses lexicographic compare (subzone ACL bypass)
High Also affects github.com/coredns/coredns
GHSA-63cw-r7xf-jmwr
CoreDNS DoH GET oversized dns= query parameter causes pre-validation CPU and memory amplification
High Also affects github.com/coredns/coredns
GHSA-2wpx-qpw2-g5h5
CoreDNS' DoQ worker pool does not bound stream backlog
High Also affects github.com/coredns/coredns
Is this in your code?

MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.

Check your repos with MergeHarbor