Common JWT Vulnerabilities
Understanding common vulnerabilities in JWT implementations is crucial for building secure applications. For comprehensive vulnerability scanning and management, consider using tools like Tenable or Bitdefender.
1. Algorithm "none" Vulnerability
CRITICAL
If a server accepts tokens with the "none" algorithm, attackers can modify tokens without a valid signature.
// Vulnerable token
{
"alg": "none",
"typ": "JWT"
}
// Attacker can modify payload without signature
// Server accepts it because algorithm is "none"Fix: Always explicitly specify allowed algorithms during verification.
2. Algorithm Confusion Attack
HIGH
If a server expects RS256 but accepts HS256, an attacker can forge tokens using the public key as a secret.
// Server expects RS256 (asymmetric)
// But accepts HS256 (symmetric) if not validated
// Attacker:
// 1. Gets public key (often exposed in JWKS endpoint)
// 2. Changes algorithm to HS256
// 3. Signs token with public key as secret
// 4. Server verifies with public key as secret - SUCCESS!Fix: Always verify the algorithm matches what you expect.
3. Weak Secret Key
HIGH
Using weak or default secrets makes tokens vulnerable to brute force attacks.
// Weak secrets
secret = "secret"
secret = "password"
secret = "123456"
// Attacker can brute force these easilyFix: Use strong, randomly generated secrets (at least 32 characters).
4. No Expiration
MEDIUM
Tokens without expiration never expire, allowing indefinite access if compromised.
Fix: Always set expiration times. Use refresh tokens for long-term access.
5. Sensitive Data in Payload
HIGH
JWTs are base64 encoded, not encrypted. Anyone can decode and read the payload.
// NEVER do this
{
"sub": "user123",
"password": "plaintext_password", // ❌
"credit_card": "1234-5678-9012", // ❌
"ssn": "123-45-6789" // ❌
}
// Only include non-sensitive data
{
"sub": "user123",
"name": "John Doe",
"role": "admin"
}6. Key ID (kid) Header Injection
MEDIUM
If the "kid" header is not properly validated, attackers can point to malicious keys.
Fix: Validate "kid" against a whitelist of trusted keys.
7. JWT Header Injection (kid, jku, x5u)
CRITICAL
Header parameters like "kid" (Key ID), "jku" (JWK Set URL), and "x5u" (X.509 URL) can be manipulated to point to attacker-controlled keys.
// Vulnerable header
{
"alg": "RS256",
"kid": "../../../etc/passwd", // Path traversal
"jku": "https://attacker.com/keys.json", // External key source
"x5u": "https://evil.com/cert.pem" // Malicious certificate
}
// Attack scenarios:
// 1. kid injection: Point to a predictable or weak key
// 2. jku spoofing: Redirect to attacker's JWKS endpoint
// 3. x5u manipulation: Use attacker's certificateFix: Whitelist allowed kid values, validate jku URLs against trusted domains, and verify certificate chains.
8. JWKS Spoofing Attack
CRITICAL
If the server fetches keys from a JWKS endpoint specified in the token, attackers can redirect to their own endpoint.
// Attacker creates token with malicious jku
{
"alg": "RS256",
"jku": "https://attacker.com/.well-known/jwks.json"
}
// Attacker hosts their own JWKS endpoint with their private key
// Server fetches the key and verifies the token - SUCCESS!
// Prevention:
// - Only allow JWKS from trusted domains
// - Use CORS and certificate pinning
// - Cache JWKS responsesFix: Whitelist trusted JWKS endpoints, implement certificate pinning, and cache JWKS responses.
9. Key Confusion (RS256 → HS256)
CRITICAL
If a server expects RS256 (asymmetric) but accepts HS256 (symmetric), an attacker can use the public key as a secret to forge tokens.
// Server expects RS256, but doesn't validate algorithm
// Attacker:
// 1. Obtains public key (often from /.well-known/jwks.json)
// 2. Changes algorithm from RS256 to HS256
// 3. Signs token with public key as HMAC secret
// 4. Server verifies with public key as secret - accepts!
// Vulnerable verification:
jwt.verify(token, publicKey); // ❌ Doesn't check algorithm
// Secure verification:
jwt.verify(token, publicKey, { algorithms: ['RS256'] }); // ✅Fix: Always explicitly specify allowed algorithms in verification. Never accept HS256 when expecting RS256.
10. Claim Injection & JWT Replay
HIGH
If claims are not properly validated, attackers can inject malicious claims or replay old tokens.
// Claim injection
{
"sub": "user123",
"role": "admin", // Injected claim
"isAdmin": true, // Privilege escalation
"permissions": ["*"] // Overly permissive
}
// Replay attack:
// 1. Attacker captures a valid token
// 2. Token is expired but server doesn't check
// 3. Attacker replays the token indefinitely
// Prevention:
// - Validate all claims
// - Check jti (JWT ID) for replay prevention
// - Use short expiration times
// - Implement token blacklistingFix: Validate all claims, use jti for replay prevention, implement token blacklisting, and check expiration.
11. Subdomain Takeover via JWKS
HIGH
If a subdomain used for JWKS is not properly secured, attackers can take it over and serve malicious keys.
// Scenario:
// 1. Token references jku: "https://keys.example.com/.well-known/jwks.json"
// 2. Subdomain "keys.example.com" is not properly secured
// 3. Attacker takes over subdomain (expired DNS, misconfigured hosting)
// 4. Attacker hosts their own JWKS with their private key
// 5. Server accepts tokens signed with attacker's key
// Prevention:
// - Secure all subdomains
// - Use certificate pinning
// - Monitor subdomain status
// - Whitelist specific JWKS endpointsFix: Secure all subdomains, implement certificate pinning, and whitelist trusted JWKS endpoints.
12. Timing Attacks on Signature Verification
MEDIUM
If signature verification uses string comparison instead of constant-time comparison, attackers can use timing differences to extract secrets.
// Vulnerable (timing attack possible):
if (signature === expectedSignature) { // ❌
return true;
}
// Secure (constant-time comparison):
if (crypto.timingSafeEqual(signature, expectedSignature)) { // ✅
return true;
}
// Attack:
// Attacker measures response time for different signatures
// Timing differences reveal information about the secretFix: Use constant-time comparison functions (e.g., crypto.timingSafeEqual) for signature verification.
13. XSS and Token Theft
CRITICAL
Storing tokens in localStorage makes them vulnerable to XSS attacks.
Fix: Use HttpOnly cookies instead of localStorage.
Tenable - Vulnerability Management (10% Discount)
10% OFFGet 10% off Tenable vulnerability scanning and management solutions. Identify and remediate security vulnerabilities in your infrastructure.
Affiliate Link
Tenable One - Unified Exposure Management Platform
PlatformThe world's leading AI-powered exposure management platform. Gain visibility across your entire attack surface, prioritize risks, and close exposure gaps across cloud, vulnerability, AI, OT/IoT, and identity domains.
Affiliate Link