CVE-2026-35579: Github.com/coredns/coredns Authentication Bypass Vulnerability

HIGH
Advisory Identifier: GHSA-vp29-5652-4fw9
CVSS 7.5
CWE-287
Published
Advisory Summary

CVE-2026-35579 is a HIGH (CVSS 7.5) authentication bypass vulnerability (CWE-287: Improper Authentication) affecting Github.com/coredns/coredns libraries in the Go ecosystem. The issue involves coredns has tsig authentication bypass on grpc and quic transports. Remediation is available by upgrading affected packages to version 1.14.3.

CVE-2026-35579 at a Glance

CVE Identifier CVE-2026-35579
GHSA Identifier GHSA-vp29-5652-4fw9
Severity HIGH
CVSS v3.1 Base Score 7.5
CWE Classification CWE-287: Improper Authentication
Affected Product Github.com/coredns/coredns
Package Ecosystem Go
Published Date
Last Updated

Security Impact

CVSS: 7.5

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction None (UI:N)
Scope Unchanged (S:U)
Confidentiality High (C:H)
Integrity None (I:N)
Availability None (A:N)

How to Fix CVE-2026-35579

To remediate this vulnerability, upgrade all affected Github.com/coredns/coredns dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

github.com/coredns/coredns fixed: 1.14.3
Upgrade github.com/coredns/coredns to 1.14.3
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for github.com/coredns/coredns

How to Check if You Are Affected

To determine whether your application is affected by CVE-2026-35579, inspect your project dependencies for Github.com/coredns/coredns:

inspect dependencies for github.com/coredns/coredns

Analyze the terminal output to locate any version of Github.com/coredns/coredns in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 1.14.3), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-287: Improper Authentication, where when an actor claims to have a given identity, the product does not prove or insufficiently proves that the claim is correct. In Github.com/coredns/coredns, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

### 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 used | gRPC | TCP | |----------|------|-----| | 32 zero bytes | BYPASS, 9 records returned | BADSIG | | 32 random bytes | BYPASS, 9 records returned | BADSIG | | HMAC computed with wrong secret | BYPASS, 9 records returned | BADSIG | | truncated to 16 bytes | BYPASS, 9 records returned | BADSIG | | single byte `0x41` | BYPASS, 9 records returned | BADSIG | | empty MAC | BYPASS, 9 records returned | BADSIG | | wrong key name + zero MAC | REJECTED, NOTAUTH/BADKEY | REJECTED, 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 variant | DoH result | TCP result | |-------------|------------|------------| | 32 zero bytes | BYPASS, NOERROR | BADSIG | | 32 random bytes | BYPASS, NOERROR | BADSIG | | HMAC computed with wrong secret | BYPASS, NOERROR | BADSIG | | truncated to 16 bytes | BYPASS, NOERROR | BADSIG | | single byte `0x41` | BYPASS, NOERROR | BADSIG | | empty MAC | BYPASS, NOERROR | BADSIG | | bad key name | BYPASS, NOERROR | NOTAUTH/BADKEY | | no TSIG record | REJECTED, REFUSED | REJECTED, 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.

CVE-2026-35579 Affected Github.com/coredns/coredns Versions

1 component(s)
Fixed Versions:
1.14.3
Product / Package Ecosystem Affected Versions Fixed Version
github.com/coredns/coredns
Go
< 1.14.3
1.14.3

References

Frequently Asked Questions

What is CVE-2026-35579?
CVE-2026-35579 is a security vulnerability in Github.com/coredns/coredns involving CoreDNS has TSIG authentication bypass on gRPC and QUIC transports under CWE-287: Improper Authentication.
Which Github.com/coredns/coredns versions are affected?
Affected versions include releases prior to 1.14.3 across affected packages: github.com/coredns/coredns.
What version fixes CVE-2026-35579?
Upgrading to 1.14.3 (or the latest patched release for your respective branch) resolves the vulnerability.
Is github.com/coredns/coredns affected?
Yes, github.com/coredns/coredns is affected in releases prior to 1.14.3. Upgrade your dependency to 1.14.3 or later.
What is the CVSS score of CVE-2026-35579?
CVE-2026-35579 has a CVSS v3.1 base score of 7.5 (HIGH) with vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N.
What CWE is associated with CVE-2026-35579?
CVE-2026-35579 is classified under CWE-287: Improper Authentication (When an actor claims to have a given identity, the product does not prove or insufficiently proves that the claim is correct.).
How can I check Go dependencies for CVE-2026-35579?
Run the dependency tree command: 'inspect dependencies for github.com/coredns/coredns'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-vp29-5652-4fw9",
  "modified" : "2026-05-08T15:30:59Z",
  "published" : "2026-04-28T22:54:32Z",
  "aliases" : [ "CVE-2026-35579" ],
  "summary" : "CoreDNS has TSIG authentication bypass on gRPC and QUIC transports",
  "details" : "### Summary\n\nThe gRPC, QUIC, DoH, and DoH3 transports in CoreDNS incorrectly handle TSIG authentication.\n\nFor 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\".\n\nFor 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.\n\nAs 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.\n\n### Details\n\nIn `server_grpc.go` and `server_quic.go`, the TSIG handling checks whether the TSIG key name exists, but does not call `dns.TsigVerify()`.\n\nRelevant code before fix:\n\n```go\nif tsig := msg.IsTsig(); tsig != nil {\n    if s.tsigSecret == nil {\n        w.tsigStatus = dns.ErrSecret\n    } else if _, ok := s.tsigSecret[tsig.Hdr.Name]; !ok {\n        w.tsigStatus = dns.ErrSecret\n    }\n    // key found -> nothing happens -> tsigStatus stays nil -> \"verified\"\n}\n```\n\nThis means that for gRPC and QUIC, a request with a known TSIG key name but an invalid MAC is accepted as authenticated.\n\nPRs #7943 and #7947 partially addressed this area by adding key name checks for gRPC and QUIC, but did not add HMAC verification.\n\nThe DoH and DoH3 paths have an even weaker failure mode. In `https.go`, `DoHWriter.TsigStatus()` returned nil unconditionally:\n\n```go\nfunc (d *DoHWriter) TsigStatus() error {\n    return nil\n}\n```\n\nIn `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()`.\n\nThe same pattern exists in the DoH3 path in `server_https3.go`.\n\nThe effective DoH/DoH3 flow before the fix was:\n\n1. HTTP or HTTP/3 request arrives.\n2. DNS message is unpacked from the request.\n3. A `DoHWriter` is created.\n4. The message is passed to `ServeDNS()`.\n5. The tsig plugin checks `w.TsigStatus()`.\n6. `TsigStatus()` returns nil.\n7. nil is interpreted as successful TSIG verification.\n\nThis 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.\n\n### PoC\n\nSetup: 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 }`.\n\nListeners used the same TSIG configuration and key:\n\n- TCP on port 1053, using the normal `dns.Server` path where TSIG HMAC verification works correctly\n- gRPC on port 1443, using manual TSIG handling\n- DoH on port 8443\n- DoH3 with the same TSIG configuration\n\n#### gRPC / QUIC behavior\n\nA 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.\n\n| MAC used | gRPC | TCP |\n|----------|------|-----|\n| 32 zero bytes | BYPASS, 9 records returned | BADSIG |\n| 32 random bytes | BYPASS, 9 records returned | BADSIG |\n| HMAC computed with wrong secret | BYPASS, 9 records returned | BADSIG |\n| truncated to 16 bytes | BYPASS, 9 records returned | BADSIG |\n| single byte `0x41` | BYPASS, 9 records returned | BADSIG |\n| empty MAC | BYPASS, 9 records returned | BADSIG |\n| wrong key name + zero MAC | REJECTED, NOTAUTH/BADKEY | REJECTED, NOTAUTH/BADKEY |\n\n6 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.\n\nThe same class applied to QUIC.\n\n#### DoH / DoH3 behavior\n\nFor DoH, a test client sent DNS queries over HTTPS POST to `/dns-query` with forged TSIG records. These requests were also compared against TCP.\n\n| TSIG variant | DoH result | TCP result |\n|-------------|------------|------------|\n| 32 zero bytes | BYPASS, NOERROR | BADSIG |\n| 32 random bytes | BYPASS, NOERROR | BADSIG |\n| HMAC computed with wrong secret | BYPASS, NOERROR | BADSIG |\n| truncated to 16 bytes | BYPASS, NOERROR | BADSIG |\n| single byte `0x41` | BYPASS, NOERROR | BADSIG |\n| empty MAC | BYPASS, NOERROR | BADSIG |\n| bad key name | BYPASS, NOERROR | NOTAUTH/BADKEY |\n| no TSIG record | REJECTED, REFUSED | REJECTED, REFUSED |\n\n7 out of 8 cases bypassed authentication over DoH. Every request containing a TSIG record was accepted, including requests with an invalid key name.\n\nAn AXFR request over DoH with a forged TSIG record using a zero-byte MAC returned the full test zone.\n\nThe 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.\n\nTo 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.\n\n### Impact\n\nAn unauthenticated network attacker may bypass TSIG authentication on affected CoreDNS transports.\n\nDepending on configuration, this may allow an attacker to:\n\n- perform AXFR or IXFR zone transfers over affected transports\n- dump TSIG-protected zone data\n- submit dynamic DNS updates if enabled\n- bypass other TSIG-gated plugin behavior\n- authenticate over DoH or DoH3 without knowing a valid TSIG key name\n\nThe 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.\n\n### Affected transports\n\n- gRPC\n- QUIC\n- DoH\n- DoH3\n\n### Workarounds\n\nIf upgrading is not immediately possible:\n\n- Disable gRPC, QUIC, DoH, and DoH3 listeners where TSIG authentication is required.\n- Restrict network-level access to affected transport ports to trusted sources only.\n- Avoid exposing TSIG-protected functionality such as AXFR, IXFR, or dynamic updates over affected transports.\n\n### Fix\n\nAffected transports must verify TSIG before passing the DNS message into the plugin chain.\n\nFor requests containing a TSIG record, the transport should:\n\n1. check whether TSIG secrets are configured\n2. verify that the TSIG key name exists\n3. call `dns.TsigVerify()` against the original wire-format message\n4. store the resulting status in the response writer\n5. return that status from `TsigStatus()`\n\nA successful key name lookup alone is not sufficient. A nil TSIG status must only be returned after successful HMAC verification.",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N"
  }, {
    "type" : "CVSS_V4",
    "score" : "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"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "Go",
      "name" : "github.com/coredns/coredns"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "1.14.3"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/coredns/coredns/security/advisories/GHSA-vp29-5652-4fw9"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-35579"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/coredns/coredns"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/coredns/coredns/releases/tag/v1.14.3"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-287" ],
    "severity" : "HIGH",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-04-28T22:54:32Z",
    "nvd_published_at" : "2026-05-05T21:16:22Z"
  }
}