Broken Authentication

Broken Authentication in Go (Gin) - Remediation [Aug 2026] [CVE-2026-35579]

[Updated Aug 2026] Updated CVE-2026-35579

Overview

CVE-2026-35579 describes a CoreDNS vulnerability where TSIG-based authentication could be bypassed: the server would treat requests as authenticated if the TSIG key name existed in the configuration, or in the DoH/DoH3 variants would always return a nil TSIG status without inspecting the MAC. This allowed an unauthenticated attacker to bypass TSIG-protected operations such as zone transfers or dynamic DNS updates. The issue was fixed in CoreDNS 1.14.3. As a workaround, operators were advised to disable or isolate TSIG-reliant transports (gRPC, QUIC, DoH, DoH3) or restrict access to those ports. In the Go ecosystem, including Go services built with Gin, a similar broken-authentication pattern can occur when a service uses a presence-based check (e.g., a configured key name exists) and then fails to verify the cryptographic signature or token, effectively granting access without proper verification. This guide ties the real-world CVE to Go (Gin) patterns and shows concrete remediation steps and code fixes.

Affected Versions

CoreDNS < 1.14.3 (1.14.0-1.14.2 affected); DoH/DoH3 variants also addressed in the CVE, with fix in 1.14.3

Code Fix Example

Go (Gin) API Security Remediation
package main

import (
  "crypto/hmac"
  "crypto/sha256"
  "encoding/hex"
  "net/http"
  "os"
  "github.com/gin-gonic/gin"
)

// Simple in-memory key store for demonstration. In production, use a secure vault.
var keyStore = map[string]string{
  "v1-service": "sharedsecret1",
}

func main() {
  mode := os.Getenv("MODE") // MODE=VULN to run vulnerable version, else FIXED
  r := gin.Default()
  if mode == "VULN" {
    r.Use(vulnerableAuthMiddleware)
  } else {
    r.Use(fixedAuthMiddleware)
  }

  r.GET("/secure", func(c *gin.Context) {
    if v, ok := c.Get("authenticated"); ok && v.(bool) {
      c.JSON(http.StatusOK, gin.H{"status": "ok"})
      return
    }
    c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
  })

  r.Run()
}

// Vulnerable pattern: authenticates based solely on the presence of a configured key,
// without validating the accompanying MAC/signature.
func vulnerableAuthMiddleware(c *gin.Context) {
  keyName := c.GetHeader("X-Auth-Key")
  mac := c.GetHeader("X-Auth-MAC")
  if keyName == "" || mac == "" {
    c.AbortWithStatus(http.StatusUnauthorized)
    return
  }
  if _, ok := keyStore[keyName]; ok {
    // BUG: Do not verify MAC; treat as authenticated if keyName exists
    c.Set("authenticated", true)
    c.Next()
    return
  }
  c.AbortWithStatus(http.StatusUnauthorized)
}

// Fixed pattern: verify the MAC against the expected HMAC with per-key secret.
func fixedAuthMiddleware(c *gin.Context) {
  keyName := c.GetHeader("X-Auth-Key")
  macHeader := c.GetHeader("X-Auth-MAC")
  if keyName == "" || macHeader == "" {
    c.AbortWithStatus(http.StatusUnauthorized)
    return
  }
  secret, ok := keyStore[keyName]
  if !ok {
    c.AbortWithStatus(http.StatusUnauthorized)
    return
  }
  expected := computeHMAC(c.Request.Method+":"+c.Request.URL.Path, secret)
  if !hmac.Equal([]byte(macHeader), []byte(expected)) {
    c.AbortWithStatus(http.StatusUnauthorized)
    return
  }
  c.Set("authenticated", true)
  c.Next()
}

func computeHMAC(message, secret string) string {
  mac := hmac.New(sha256.New, []byte(secret))
  mac.Write([]byte(message))
  return hex.EncodeToString(mac.Sum(nil))
}

CVE References

Choose which optional cookies to allow. You can change this any time.