Why AI tools produce this: AI coding tools produce this regularly, typically when prompted for a shortcut or a quick fix.
Why this matters
This is the "algorithm confusion" attack: an attacker can sign forged tokens with the public key and your code will happily verify them with HMAC-SHA256 treating the PEM string as the shared secret.
Always pin the algorithm to the asymmetric one you actually use (e.g. algorithms: ['RS256']) and pass the public key only when verifying asymmetric tokens.
RFC 7518 §3.1: the "alg" header must be matched to the key type.
VULNERABLE
vulnerable.ts
import jwt from 'jsonwebtoken';const RSA_PUBLIC = `-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxxxxxxxxxxxxxxxxxxxx-----END PUBLIC KEY-----`;// ruleid: auth.jwt.algorithm-confusionexport function badVerify(token: string) { return jwt.verify(token, RSA_PUBLIC, { algorithms: ['HS256'] });}// ruleid: auth.jwt.algorithm-confusion -- mixing HS with an RSA public keyexport function badVerifyMixed(token: string, publicKey: string) { return jwt.verify(token, publicKey, { algorithms: ['HS256', 'RS256'] });}
SAFE
safe.ts
import jwt from 'jsonwebtoken';const RSA_PUBLIC = process.env.JWT_PUBLIC_KEY!;const HMAC_SECRET = process.env.JWT_HMAC_SECRET!;// ok: auth.jwt.algorithm-confusion -- RS256 matches the asymmetric keyexport function goodVerifyAsymmetric(token: string) { return jwt.verify(token, RSA_PUBLIC, { algorithms: ['RS256'] });}// ok: auth.jwt.algorithm-confusion -- HS256 with a real shared secret, not a PEMexport function goodVerifySymmetric(token: string) { return jwt.verify(token, HMAC_SECRET, { algorithms: ['HS256'] });}
Suppressing this rule
If a finding is a genuine false positive, scope the suppression to the exact line and leave a reason, never disable the rule project-wide. Disable directives are line-scoped by design.