Exploit Analysis: The JWT Algorithm 'none' Attack (And the Guard)
A technical analysis of the most dangerous auth misconfiguration. How to engineering static analysis guards to eliminate 'none' exploits.

A single line of configuration can forge a JWT. Here is the technical analysis of the 'none' algorithm attack, and the automated static analysis guard that eliminates this architectural risk.
JWT authentication is everywhere. It's also one of the most misconfigured security mechanisms.
One line of code can compromise everything.
The Vulnerable Code
// โ This looks fine...
const decoded = jwt.verify(token, secret, {
algorithms: ['HS256', 'none'], // ๐ The vulnerability
});
The Attack
// 1. Attacker takes a valid JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTYiLCJyb2xlIjoidXNlciJ9.
signature_here
// 2. Modifies the header to use "none" algorithm:
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.
eyJzdWIiOiIxMjM0NTYiLCJyb2xlIjoiYWRtaW4ifQ.
// No signature needed!
// 3. Server accepts it because "none" is in algorithms list
// Attacker is now admin
Real CVEs
| CVE | Library | Impact |
|---|---|---|
| CVE-2015-2951 | jwt-simple | Algorithm confusion |
| CVE-2016-10555 | jose2go | None algorithm bypass |
| CVE-2018-0114 | node-jose | Key confusion |
The Fix
// โ
Explicitly whitelist algorithms
const decoded = jwt.verify(token, secret, {
algorithms: ['HS256'], // Only what you use!
});
All JWT Vulnerabilities
1. Algorithm None
// โ Dangerous
jwt.verify(token, secret, { algorithms: ['none'] });
// โ
Safe
jwt.verify(token, secret, { algorithms: ['HS256'] });
2. Algorithm Confusion
// โ Dangerous: RS256 token verified with symmetric secret
jwt.verify(token, publicKey);
// โ
Safe: Explicit algorithm
jwt.verify(token, publicKey, { algorithms: ['RS256'] });
3. Weak Secret
// โ Dangerous: Brute-forceable
jwt.sign(payload, 'password123');
// โ
Safe: Strong secret
jwt.sign(payload, process.env.JWT_SECRET); // 256+ bits
4. Missing Expiration
// โ Dangerous: Token valid forever
jwt.sign({ userId: 123 }, secret);
// โ
Safe: Short expiration
jwt.sign({ userId: 123 }, secret, { expiresIn: '1h' });
5. Sensitive Payload
// โ Dangerous: Password in token (tokens can be decoded!)
jwt.sign({ userId: 123, password: 'secret' }, key);
// โ
Safe: Only IDs
jwt.sign({ userId: 123 }, key);
ESLint Coverage
// eslint.config.js
import jwtPlugin from 'eslint-plugin-jwt';
export default [jwtPlugin.configs.recommended];
13 JWT Rules
| Rule | CWE | What it catches |
|---|---|---|
no-algorithm-none | CWE-347 | Algorithm "none" allowed |
no-algorithm-confusion | CWE-327 | RS/HS confusion attacks |
no-weak-secret | CWE-326 | Brute-forceable secrets |
no-hardcoded-secret | CWE-798 | Secrets in code |
no-sensitive-payload | CWE-312 | PII in tokens |
require-expiration | CWE-613 | Missing exp claim |
require-algorithm-whitelist | CWE-327 | No explicit algorithms |
require-issuer-validation | CWE-345 | Missing iss check |
require-audience-validation | CWE-345 | Missing aud check |
no-decode-without-verify | CWE-347 | jwt.decode() misuse |
require-issued-at | CWE-613 | Missing iat claim |
require-max-age | CWE-613 | No maxAge in verify |
no-timestamp-manipulation | CWE-345 | Clock skew exploits |
Error Messages
src/auth.ts
15:3 error ๐ CWE-347 CVSS:9.8 | JWT algorithm 'none' is allowed
Risk: Attackers can forge tokens without a signature
Fix: Remove 'none' from algorithms: ['HS256']
Quick Install
::dev-to-cta{url="https://npmjs.com/package/eslint-plugin-jwt in 60 seconds. 13 rules. Full JWT security. Zero false positives.**
๐ฆ npm: eslint-plugin-jwt ๐ Rule: no-algorithm-none
The Interlace ESLint Ecosystem Interlace is a high-fidelity suite of static code analyzers designed to automate security, performance, and reliability for the modern Node.js stack. With over 330 rules across 18 specialized plugins, it provides 100% coverage for OWASP Top 10, LLM Security, and Database Hardening.
Explore the full Documentation
ยฉ 2026 Ofri Peretz. All rights reserved.
Build Securely. I'm Ofri Peretz, a Security Engineering Leader and the architect of the Interlace Ecosystem. I build static analysis standards that automate security and performance for Node.js fleets at scale.