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

JWT Algorithm Confusion (alg:none & RS→HS)

security CWE-327 OWASP A2:2021 CVSS 9.1 PHP 5.0+ Intermediate

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

Added 15 Mar 2026
Edited 22 Mar 2026
Views 27
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 1 ping S 0 pings M 1 ping T 1 ping W 0 pings T 1 ping F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 2 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S
No pings yesterday
Amazonbot 9 Perplexity 5 Unknown AI 3 Google 2 SEMrush 2 Majestic 1 Ahrefs 1
crawler 21 crawler_json 1 pre-tracking 1
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

✓ schema.org compliant