← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

JWT Vulnerabilities

security CWE-287 OWASP A2:2021 CVSS 8.8 PHP 7.0+ Intermediate

Also Known As

JWT attack JSON Web Token weakness

TL;DR

Misimplemented JSON Web Token handling allows attackers to forge tokens, bypass authentication, or escalate privileges.

Explanation

Common JWT vulnerabilities include: accepting the 'none' algorithm (no signature required), algorithm confusion attacks (RS256 public key used as HS256 secret), weak secrets susceptible to offline brute-force, missing expiry validation, and insecure storage of tokens in localStorage. Always validate the algorithm explicitly, reject 'none', use strong secrets or asymmetric keys, verify exp/nbf claims, and store tokens in HttpOnly cookies rather than JavaScript-accessible storage.

How It's Exploited

An attacker takes a valid JWT, changes the algorithm header to 'none', and strips the signature. A vulnerable library that doesn't reject the 'none' algorithm will accept the tampered token as valid, allowing the attacker to forge arbitrary claims.

Diagram

flowchart TD
    subgraph alg none attack
        J1[Header: alg=none] --> J2[Signature stripped]
        J2 --> J3[Server accepts<br/>unsigned token!]
    end
    subgraph Algorithm confusion
        J4[RS256 token] --> J5[Attacker changes<br/>alg=HS256]
        J5 --> J6[Signs with<br/>public key as HMAC secret]
        J6 --> J7[Server verifies<br/>with same public key]
    end
    subgraph Fix
        F1[Whitelist allowed algorithms<br/>never accept none<br/>validate exp, iss, aud]
    end
    style J3 fill:#f85149,color:#fff
    style J7 fill:#f85149,color:#fff
    style F1 fill:#238636,color:#fff

Watch Out

Never use the token's own header to determine which algorithm to use for verification — always enforce the expected algorithm in your server-side code.

Common Misconception

A valid JWT signature proves the token is trustworthy. The signature only proves the token was not tampered with after signing — it says nothing about the claims inside. Always validate exp, iss, aud, and sub server-side after verifying the signature.

Why It Matters

JWTs are widely misimplemented — algorithm confusion, weak secrets, and unverified claims have each caused complete authentication bypass in real applications.

Common Mistakes

  • Not explicitly specifying the allowed algorithm when verifying — accepting whatever alg the token declares.
  • Using a short or guessable HMAC secret — HS256 with a weak secret is crackable offline.
  • Not validating exp, nbf, and iss claims after signature verification.
  • Storing sensitive data in the payload without encrypting it — the payload is only base64-encoded, not secret.

Code Examples

✗ Vulnerable
// Trusting the algorithm from the token header:
$decoded = JWT::decode($token, $secret); // No algorithm allowlist specified
// Attacker sends alg=none token — some libraries accept it
✓ Fixed
// Whitelist algorithm — reject none and algorithm confusion:
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

// Always specify algorithm explicitly:
$decoded = JWT::decode(
    $token,
    new Key($publicKey, 'RS256') // Only RS256 accepted — rejects HS256, none
);

// Validate all critical claims:
if ($decoded->iss !== 'https://auth.example.com') {
    throw new Exception('Invalid issuer');
}
if ($decoded->aud !== 'api.example.com') {
    throw new Exception('Invalid audience');
}
if ($decoded->exp < time()) {
    throw new Exception('Token expired');
}

Added 15 Mar 2026
Edited 22 Mar 2026
Views 61
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings W 0 pings T 0 pings F 1 ping S 1 ping S 1 ping M 1 ping T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 2 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 1 ping S 0 pings S 0 pings M 1 ping T 0 pings W 0 pings T
No pings yet today
No pings yesterday
Perplexity 37 Amazonbot 6 Google 4 Unknown AI 2 Ahrefs 2 Majestic 1 Meta AI 1 ChatGPT 1
crawler 53 pre-tracking 1
DEV INTEL Tools & Severity
🔴 Critical ⚙ Fix effort: Medium
⚡ Quick Fix
Explicitly specify the allowed algorithm when decoding: never trust the 'alg' header from the token itself; use a dedicated library like firebase/php-jwt
📦 Applies To
PHP 7.0+ web api
🔗 Prerequisites
🔍 Detection Hints
JWT decode accepting algorithm from token header; no algorithm whitelist; base64_decode without signature verification
Auto-detectable: ✓ Yes semgrep psalm
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Medium ✗ Manual fix Fix: Medium Context: File Tests: Update
CWE-347 CWE-345

✓ schema.org compliant