JWT verification uses .verify() not just .decode()
Why it matters
jwt.decode() in jsonwebtoken does not verify the signature — it base64-decodes the payload without checking the HMAC or RSA signature at all. An attacker can construct a JWT with any payload they want, including { role: 'admin', userId: '1' }, and your application will accept it as a valid authenticated identity. CWE-347 (Improper Verification of Cryptographic Signature) and OWASP A07 (Identification & Authentication Failures) both cite this exact pattern. Authentication built on jwt.decode() provides zero security — every token is trusted unconditionally.
Severity rationale
Critical because using `.decode()` instead of `.verify()` makes JWT-based authentication trivially bypassable — any attacker can forge a token with arbitrary claims and gain full authenticated access.
Remediation
Replace every jwt.decode(token) that feeds into user identity with jwt.verify(token, secret). The verify call will throw if the signature is invalid or the token is expired.
// Bad: trusts payload without signature check
import jwt from 'jsonwebtoken'
const payload = jwt.decode(token) // no signature verification!
req.user = payload
// Good: verify the signature before trusting the payload
import jwt from 'jsonwebtoken'
try {
const payload = jwt.verify(token, process.env.JWT_SECRET!)
req.user = payload
} catch (err) {
return Response.json({ error: 'Invalid or expired token' }, { status: 401 })
}
.decode() is only safe when inspecting the token header (e.g., extracting the kid claim to select the right key) BEFORE a subsequent .verify() call. It must never be the final word on identity.
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the Security Implementation Validation Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- cwe · CWE-347 — Improper Verification of Cryptographic Signature
- cwe · CWE-345 — Insufficient Verification of Data Authenticity
- owasp:2021 · A02 — Cryptographic Failures
- owasp:2021 · A07 — Identification and Authentication Failures
Taxons
History
- 2026-04-18·v1.0.0·Initial import from ai-slop-security-theater·automated
- 2026-04-20·v1.1.0·Add Phase 6.0 detect-rg snippet for jwt.decode usage detection·by cakleinman