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 — no algorithm restriction
const decoded = jwt.verify(token, secret);
// Attacker forges: { alg: "none", typ: "JWT", payload: { sub: "admin", role: "admin" } }
// 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();
pool.query(`SELECT * FROM users WHERE id = ${req.params.id}`)