5 min read

JWT verification with explicit algorithm pin — defense against alg-confusion

Verify JWTs with explicit algorithm + issuer + audience. Default verify functions accept multiple algorithms = alg-confusion attack surface.

Default JWT verify accepts multiple algorithms. Attacker substitutes 'none' or HS256 for an RS256-signed token + bypasses verification.

What it is

JWT alg-confusion: if your verify function accepts both RS256 and HS256, an attacker re-signs the token using the public key as an HS256 secret + your verify accepts it.

Vulnerable example

// vulnerable: accepts any algorithm
const payload = jwt.verify(token, publicKey);

Fixed example

// pin algorithm + issuer + audience
const payload = jwt.verify(token, publicKey, {
  algorithms: ["RS256"],          // pin algorithm
  issuer: "https://your-issuer.com",
  audience: "your-app-id",
  clockTolerance: 30,
});

How Securie catches it

Securie findinghigh
apps/web/auth.ts:87

JWT verification with explicit algorithm pin

Crypto_hygiene + AuthAuthz specialists catch jwt.verify without algorithms[] pin.

Suggested fix — ready as a PR
// pin algorithm + issuer + audience
const payload = jwt.verify(token, publicKey, {
  algorithms: ["RS256"],          // pin algorithm
  issuer: "https://your-issuer.com",
  audience: "your-app-id",
  clockTolerance: 30,
});
Catch this in my repo →Securie scans every PR · ships the fix as a one-click merge · free during early access

Checklist

  • algorithms[] explicitly set
  • issuer + audience verified
  • clockTolerance set
  • Signing key from secure source (not request)

FAQ

Why audience?

Audience identifies which service the token is FOR; pinning prevents tokens for other services being used here.

Related guides