Skip to main content

CoreDNS EUVDEUVD-2026-27493

| CVE-2026-35579 HIGH
Improper Authentication (CWE-287)
2026-04-28 https://github.com/coredns/coredns GHSA-vp29-5652-4fw9
8.2
CVSS 4.0 · Vendor: https://github.com/coredns/coredns
Share

Severity by source

Vendor (https://github.com/coredns/coredns) PRIMARY
8.2 HIGH
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
SUSE
9.8 CRITICAL
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Red Hat
7.5 HIGH
qualitative

Primary rating from Vendor (https://github.com/coredns/coredns).

CVSS VectorVendor: https://github.com/coredns/coredns

CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
X

Lifecycle Timeline

3
Patch available
May 05, 2026 - 22:02 EUVD
CVSS changed
May 05, 2026 - 21:22 NVD
7.5 (HIGH) 8.2 (HIGH)
CVE Published
Apr 28, 2026 - 22:54 nvd
HIGH 7.5

DescriptionCVE.org

Summary

The gRPC, QUIC, DoH, and DoH3 transports in CoreDNS incorrectly handle TSIG authentication.

For gRPC and QUIC, CoreDNS checks whether the TSIG key name exists in the config, but does not actually verify the TSIG HMAC. If the key name matches, tsigStatus remains nil and the tsig plugin treats the request as "verified".

For DoH and DoH3, the issue is worse: TSIG is not verified at all. The DoH response writer has TsigStatus() hardcoded to return nil, so any request containing a TSIG record is treated as authenticated, even if the key name is invalid and the MAC is garbage.

As a result, attackers may bypass TSIG authentication on affected transports and access TSIG-protected functionality such as AXFR/IXFR zone transfers, dynamic updates, or other TSIG-gated plugin behavior.

Details

In server_grpc.go and server_quic.go, the TSIG handling checks whether the TSIG key name exists, but does not call dns.TsigVerify().

Relevant code before fix:

go
if tsig := msg.IsTsig(); tsig != nil {
    if s.tsigSecret == nil {
        w.tsigStatus = dns.ErrSecret
    } else if _, ok := s.tsigSecret[tsig.Hdr.Name]; !ok {
        w.tsigStatus = dns.ErrSecret
    }
    // key found -> nothing happens -> tsigStatus stays nil -> "verified"
}

This means that for gRPC and QUIC, a request with a known TSIG key name but an invalid MAC is accepted as authenticated.

PRs #7943 and #7947 partially addressed this area by adding key name checks for gRPC and QUIC, but did not add HMAC verification.

The DoH and DoH3 paths have an even weaker failure mode. In https.go, DoHWriter.TsigStatus() returned nil unconditionally:

go
func (d *DoHWriter) TsigStatus() error {
    return nil
}

In server_https.go, the incoming DNS message is unpacked from the HTTP request and passed directly into ServeDNS() without checking msg.IsTsig(), without looking up the TSIG key name, and without calling dns.TsigVerify().

The same pattern exists in the DoH3 path in server_https3.go.

The effective DoH/DoH3 flow before the fix was:

  1. HTTP or HTTP/3 request arrives.
  2. DNS message is unpacked from the request.
  3. A DoHWriter is created.
  4. The message is passed to ServeDNS().
  5. The tsig plugin checks w.TsigStatus().
  6. TsigStatus() returns nil.
  7. nil is interpreted as successful TSIG verification.

This means that for DoH and DoH3, CoreDNS did not even require a valid TSIG key name. Any TSIG record was enough to satisfy the tsig plugin, regardless of key name or MAC contents.

PoC

Setup: built CoreDNS from master at commit 12d9457 and also verified against the v1.14.2 release binary. Configured a single test zone with 9 records and tsig { require all }.

Listeners used the same TSIG configuration and key:

  • TCP on port 1053, using the normal dns.Server path where TSIG HMAC verification works correctly
  • gRPC on port 1443, using manual TSIG handling
  • DoH on port 8443
  • DoH3 with the same TSIG configuration
gRPC / QUIC behavior

A test client sent AXFR requests over gRPC with a valid TSIG key name but forged MAC values. The same requests were sent over TCP for comparison.

MAC usedgRPCTCP
32 zero bytesBYPASS, 9 records returnedBADSIG
32 random bytesBYPASS, 9 records returnedBADSIG
HMAC computed with wrong secretBYPASS, 9 records returnedBADSIG
truncated to 16 bytesBYPASS, 9 records returnedBADSIG
single byte 0x41BYPASS, 9 records returnedBADSIG
empty MACBYPASS, 9 records returnedBADSIG
wrong key name + zero MACREJECTED, NOTAUTH/BADKEYREJECTED, NOTAUTH/BADKEY

6 out of 7 forged TSIG requests bypassed authentication over gRPC and returned a full zone transfer. The only rejected case was the wrong key name, because the gRPC path checked whether the key name existed.

The same class applied to QUIC.

DoH / DoH3 behavior

For DoH, a test client sent DNS queries over HTTPS POST to /dns-query with forged TSIG records. These requests were also compared against TCP.

TSIG variantDoH resultTCP result
32 zero bytesBYPASS, NOERRORBADSIG
32 random bytesBYPASS, NOERRORBADSIG
HMAC computed with wrong secretBYPASS, NOERRORBADSIG
truncated to 16 bytesBYPASS, NOERRORBADSIG
single byte 0x41BYPASS, NOERRORBADSIG
empty MACBYPASS, NOERRORBADSIG
bad key nameBYPASS, NOERRORNOTAUTH/BADKEY
no TSIG recordREJECTED, REFUSEDREJECTED, REFUSED

7 out of 8 cases bypassed authentication over DoH. Every request containing a TSIG record was accepted, including requests with an invalid key name.

An AXFR request over DoH with a forged TSIG record using a zero-byte MAC returned the full test zone.

The same pattern applies to DoH3 because it used the same DoHWriter TSIG behavior and did not verify TSIG before passing the message into the plugin chain.

To confirm that the tsig plugin itself was enforcing policy, requests with no TSIG record were rejected with REFUSED. The bypass happens because the transport layer reports successful TSIG verification when verification either did not happen or only checked the key name.

Impact

An unauthenticated network attacker may bypass TSIG authentication on affected CoreDNS transports.

Depending on configuration, this may allow an attacker to:

  • perform AXFR or IXFR zone transfers over affected transports
  • dump TSIG-protected zone data
  • submit dynamic DNS updates if enabled
  • bypass other TSIG-gated plugin behavior
  • authenticate over DoH or DoH3 without knowing a valid TSIG key name

The DoH and DoH3 variants have a lower exploitation bar than gRPC and QUIC because the attacker does not need to know a configured TSIG key name. Any TSIG record is treated as valid.

Affected transports

  • gRPC
  • QUIC
  • DoH
  • DoH3

Workarounds

If upgrading is not immediately possible:

  • Disable gRPC, QUIC, DoH, and DoH3 listeners where TSIG authentication is required.
  • Restrict network-level access to affected transport ports to trusted sources only.
  • Avoid exposing TSIG-protected functionality such as AXFR, IXFR, or dynamic updates over affected transports.

Fix

Affected transports must verify TSIG before passing the DNS message into the plugin chain.

For requests containing a TSIG record, the transport should:

  1. check whether TSIG secrets are configured
  2. verify that the TSIG key name exists
  3. call dns.TsigVerify() against the original wire-format message
  4. store the resulting status in the response writer
  5. return that status from TsigStatus()

A successful key name lookup alone is not sufficient. A nil TSIG status must only be returned after successful HMAC verification.

Analysis

Summary

The gRPC, QUIC, DoH, and DoH3 transports in CoreDNS incorrectly handle TSIG authentication.

For gRPC and QUIC, CoreDNS checks whether the TSIG key name exists in the config, but does not actually verify the TSIG HMAC. If the key name matches, tsigStatus remains nil and the tsig plugin treats the request as "verified".

For DoH and DoH3, the issue is worse: TSIG is not verified at all. The DoH response writer has TsigStatus() hardcoded to return nil, so any request containing a TSIG record is treated as authenticated, even if the key name is invalid and the MAC is garbage.

As a result, attackers may bypass TSIG authentication on affected transports and access TSIG-protected functionality such as AXFR/IXFR zone transfers, dynamic updates, or other TSIG-gated plugin behavior.

Details

In server_grpc.go and server_quic.go, the TSIG handling checks whether the TSIG key name exists, but does not call dns.TsigVerify().

Relevant code before fix:

go
if tsig := msg.IsTsig(); tsig != nil {
    if s.tsigSecret == nil {
        w.tsigStatus = dns.ErrSecret
    } else if _, ok := s.tsigSecret[tsig.Hdr.Name]; !ok {
        w.tsigStatus = dns.ErrSecret
    }
    // key found -> nothing happens -> tsigStatus stays nil -> "verified"
}

This means that for gRPC and QUIC, a request with a known TSIG key name but an invalid MAC is accepted as authenticated.

PRs #7943 and #7947 partially addressed this area by adding key name checks for gRPC and QUIC, but did not add HMAC verification.

The DoH and DoH3 paths have an even weaker failure mode. In https.go, DoHWriter.TsigStatus() returned nil unconditionally:

go
func (d *DoHWriter) TsigStatus() error {
    return nil
}

In server_https.go, the incoming DNS message is unpacked from the HTTP request and passed directly into ServeDNS() without checking msg.IsTsig(), without looking up the TSIG key name, and without calling dns.TsigVerify().

The same pattern exists in the DoH3 path in server_https3.go.

The effective DoH/DoH3 flow before the fix was:

  1. HTTP or HTTP/3 request arrives.
  2. DNS message is unpacked from the request.
  3. A DoHWriter is created.
  4. The message is passed to ServeDNS().
  5. The tsig plugin checks w.TsigStatus().
  6. TsigStatus() returns nil.
  7. nil is interpreted as successful TSIG verification.

This means that for DoH and DoH3, CoreDNS did not even require a valid TSIG key name. Any TSIG record was enough to satisfy the tsig plugin, regardless of key name or MAC contents.

PoC

Setup: built CoreDNS from master at commit 12d9457 and also verified against the v1.14.2 release binary. Configured a single test zone with 9 records and tsig { require all }.

Listeners used the same TSIG configuration and key:

  • TCP on port 1053, using the normal dns.Server path where TSIG HMAC verification works correctly
  • gRPC on port 1443, using manual TSIG handling
  • DoH on port 8443
  • DoH3 with the same TSIG configuration
gRPC / QUIC behavior

A test client sent AXFR requests over gRPC with a valid TSIG key name but forged MAC values. The same requests were sent over TCP for comparison.

MAC usedgRPCTCP
32 zero bytesBYPASS, 9 records returnedBADSIG
32 random bytesBYPASS, 9 records returnedBADSIG
HMAC computed with wrong secretBYPASS, 9 records returnedBADSIG
truncated to 16 bytesBYPASS, 9 records returnedBADSIG
single byte 0x41BYPASS, 9 records returnedBADSIG
empty MACBYPASS, 9 records returnedBADSIG
wrong key name + zero MACREJECTED, NOTAUTH/BADKEYREJECTED, NOTAUTH/BADKEY

6 out of 7 forged TSIG requests bypassed authentication over gRPC and returned a full zone transfer. The only rejected case was the wrong key name, because the gRPC path checked whether the key name existed.

The same class applied to QUIC.

DoH / DoH3 behavior

For DoH, a test client sent DNS queries over HTTPS POST to /dns-query with forged TSIG records. These requests were also compared against TCP.

TSIG variantDoH resultTCP result
32 zero bytesBYPASS, NOERRORBADSIG
32 random bytesBYPASS, NOERRORBADSIG
HMAC computed with wrong secretBYPASS, NOERRORBADSIG
truncated to 16 bytesBYPASS, NOERRORBADSIG
single byte 0x41BYPASS, NOERRORBADSIG
empty MACBYPASS, NOERRORBADSIG
bad key nameBYPASS, NOERRORNOTAUTH/BADKEY
no TSIG recordREJECTED, REFUSEDREJECTED, REFUSED

7 out of 8 cases bypassed authentication over DoH. Every request containing a TSIG record was accepted, including requests with an invalid key name.

An AXFR request over DoH with a forged TSIG record using a zero-byte MAC returned the full test zone.

The same pattern applies to DoH3 because it used the same DoHWriter TSIG behavior and did not verify TSIG before passing the message into the plugin chain.

To confirm that the tsig plugin itself was enforcing policy, requests with no TSIG record were rejected with REFUSED. The bypass happens because the transport layer reports successful TSIG verification when verification either did not happen or only checked the key name.

Impact

An unauthenticated network attacker may bypass TSIG authentication on affected CoreDNS transports.

Depending on configuration, this may allow an attacker to:

  • perform AXFR or IXFR zone transfers over affected transports
  • dump TSIG-protected zone data
  • submit dynamic DNS updates if enabled
  • bypass other TSIG-gated plugin behavior
  • authenticate over DoH or DoH3 without knowing a valid TSIG key name

The DoH and DoH3 variants have a lower exploitation bar than gRPC and QUIC because the attacker does not need to know a configured TSIG key name. Any TSIG record is treated as valid.

Affected transports

  • gRPC
  • QUIC
  • DoH
  • DoH3

Workarounds

If upgrading is not immediately possible:

  • Disable gRPC, QUIC, DoH, and DoH3 listeners where TSIG authentication is required.
  • Restrict network-level access to affected transport ports to trusted sources only.
  • Avoid exposing TSIG-protected functionality such as AXFR, IXFR, or dynamic updates over affected transports.

Fix

Affected transports must verify TSIG before passing the DNS message into the plugin chain.

For requests containing a TSIG record, the transport should:

  1. check whether TSIG secrets are configured
  2. verify that the TSIG key name exists
  3. call dns.TsigVerify() against the original wire-format message
  4. store the resulting status in the response writer
  5. return that status from TsigStatus()

A successful key name lookup alone is not sufficient. A nil TSIG status must only be returned after successful HMAC verification.

Vendor StatusVendor

SUSE

Severity: Critical
Product Status
openSUSE Leap 16.0 Fixed

Share

EUVD-2026-27493 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy