Auth ⚑ Critical severity

JWT None Algorithm Bypass

JWT library accepts "none" algorithm — attacker forges tokens with no signature and admin claims.

JWT libraries that don’t pin algorithms accept tokens with any `alg` header — including `"none"`. Since `"none"` means no signature, an attacker can forge any payload (including `admin: true`) and the server accepts it. Many libraries also fail to reject unknown algorithms or case variants like `nOnE`, `NoNe`, `NONE`.

❌ Vulnerable
// VULNERABLE — no algorithm restriction
const decoded = jwt.verify(token, secret);
// Attacker forges: { alg: "none", typ: "JWT", payload: { sub: "admin", role: "admin" } }
✓ Fixed
// FIXED — strict algorithm allowlist + reject none
const decoded = jwt.verify(token, secret, {
  algorithms: ['RS256', 'ES256', 'HS256'], // never include 'none'
});
// Also add: if (decoded.header.alg?.toLowerCase() === 'none') throw new Error();
CVE-2024-48916 (Ceph RadosGW JWT auth bypass via none algorithm), CVE-2024-54150 (another JWT algorithm confusion in libjwt), CVE-2026-23993 (HarbourJwt accepts any unrecognized algorithm including "none", "foo", "zzz"). Node.js jsonwebtoken library was vulnerable prior to 4.2.2. The classic JS example: `eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiIxMjM0NTYiLCJyb2xlIjoiYWRtaW4ifQ.` — remove the signature part, add admin role.
PullLight looks for `jwt.verify()` calls without `algorithms` in the options, and flags when a JWT header `alg` field is inspected without case-normalization. It flags token forgery patterns and algorithms arrays missing explicit exclusion of `"none"`.
See it in action — paste a diff into /analyze
Try a vulnerable example: pool.query(`SELECT * FROM users WHERE id = ${req.params.id}`)
Analyze a diff →