JWT Algorithm Confusion (alg:none & RS→HS)
Also Known As
JWT none algorithm
alg:none attack
JWT signature bypass
TL;DR
Forging JWTs by exploiting libraries that accept alg:none or by switching an RS256 public key into HMAC-SHA256 signing.
Explanation
Two classic JWT attacks exploit algorithm flexibility. The alg:none attack: some libraries accept a token with {'alg':'none'} and no signature, treating it as valid — an attacker can forge any payload. The algorithm confusion attack: an RS256 token (asymmetric — signed with private key, verified with public key) is downgraded to HS256 (symmetric HMAC). If the library reuses the public key as the HMAC secret, an attacker who knows the public key can sign arbitrary tokens. Defences: always specify the expected algorithm explicitly in the verify call; never accept algorithm from the token header; use a dedicated JWT library (firebase/php-jwt, lcobucci/jwt) that enforces algorithm allowlisting; reject tokens with alg:none unconditionally.
Common Misconception
✗ Any JWT library handles the alg:none attack automatically. Older and poorly maintained libraries still accept tokens with "alg":"none" unless explicitly configured to reject them — always specify an allowlist of accepted algorithms.
Why It Matters
The 'none' algorithm tells the server the token is unsigned, and some libraries accept it — an attacker can forge any token with any claims without knowing the secret.
Common Mistakes
- Using a JWT library that accepts whatever algorithm is specified in the token header without validating against an allowlist.
- Not explicitly specifying the expected algorithm when verifying — letting the token dictate its own verification.
- Mixing HS256 and RS256 — sending an HS256 token to a server expecting RS256 can cause the public key to be used as the HMAC secret.
- Trusting the decoded payload before verifying the signature — some libraries return data even on verification failure.
Code Examples
✗ Vulnerable
JWT::decode($token, $key); // accepts whatever alg the token claims
✓ Fixed
JWT::decode($token, new Key($key, 'RS256')); // algorithm pinned explicitly
References
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
15 Mar 2026
Edited
22 Mar 2026
Views
27
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 1
No pings yesterday
Amazonbot 9
Perplexity 5
Unknown AI 3
Google 2
SEMrush 2
Majestic 1
Ahrefs 1
Also referenced
How they use it
crawler 21
crawler_json 1
pre-tracking 1
Related categories
⚡
DEV INTEL
Tools & Severity
🔴 Critical
⚙ Fix effort: Low
⚡ Quick Fix
Always specify an allowlist of permitted algorithms when verifying JWTs — never accept 'none' as a valid algorithm; use a well-maintained library like firebase/php-jwt
📦 Applies To
PHP 5.0+
web
api
🔗 Prerequisites
🔍 Detection Hints
JWT verification without specifying allowed algorithms; accepting alg header from token without validation; custom JWT decode without algorithm check
Auto-detectable:
✓ Yes
semgrep
psalm
⚠ Related Problems
🤖 AI Agent
Confidence: High
False Positives: Low
✓ Auto-fixable
Fix: Low
Context: Line
Tests: Update
CWE-347
CWE-327