Safeguard
Application Security•

ASVS 5.0 V9.1.2: Allowlist Token Algorithms, Never Allow None

ASVS V9.1.2 (Level 1): only allowlisted algorithms may create or verify tokens, with no None algorithm. Stop alg confusion with fixed settings and tests.

Safeguard Security Team
3 min read

ASVS 5.0 V9.1.2 requires that only algorithms on an allowlist can be used to create and verify self-contained tokens in a given context. The list names the permitted algorithms, ideally all symmetric or all asymmetric, and must not include none. If you need both kinds, extra controls must prevent key confusion. It is a Level 1 requirement.

Why it matters

A JWT header carries an alg field, and the attacker controls it. If the verifier believes the header, two classic attacks open up.

  • The none attack: the token says no signature is needed, and a naive library agrees.
  • Algorithm confusion: your server expects RS256 and verifies with an RSA public key. The attacker sets alg to HS256 and signs using your public key as the HMAC secret. Public keys are public, so the forged token verifies.

How to implement it

The server decides the algorithm. The token never does.

await jwtVerify(token, key, {
  algorithms: ["ES256"],   // one entry, set in code or config
  issuer: ISSUER,
  audience: AUDIENCE,
});
jwt.decode(token, public_key, algorithms=["ES256"], audience=AUD, issuer=ISS)

Practical rules:

  1. Pick one algorithm per issuer and context. Asymmetric (RS256, ES256, EdDSA) is the better default when many services verify, because verifiers hold no signing secret.
  2. Keep the list in configuration with a test that fails if none appears.
  3. Bind each key to its algorithm. In a JWKS, use the key's alg and use fields, and have your code refuse a key that does not match.
  4. If you truly must accept both symmetric and asymmetric tokens, use separate verifiers with separate keys, chosen by issuer, never by the token header.
  5. Never pass a public key into a function that accepts an HMAC secret.

How to test it

  1. Resign a valid token with alg: none and an empty signature. Expect 401.
  2. Take your public key, use it as an HS256 secret, and sign a forged token with alg: HS256. Expect 401.
  3. Use an algorithm that is secure but not on your list (for example RS512 when you allow RS256). Expect 401.
  4. Add a unit test that reads the configured list and asserts it contains no none and no mix of families.

Common mistakes

  • Calling verify without an algorithms argument and trusting library defaults.
  • Letting a config flag add HS256 "for local development" to production.
  • Reusing one key variable for both RSA public keys and HMAC secrets.
  • Using different libraries in different services with different defaults.

Quick check

Who should decide which algorithm verifies a token?

The verifying service, through a fixed allowlist. The token header is attacker controlled input.

Why do public keys matter in the HS256 attack?

If the verifier uses a public key as an HMAC secret, anyone who knows that public key can forge valid tokens.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.