BRUTE_FORCE_SUCCESS { tries: 26, guess: 'z', status: 200, tokenIssued: true }
An intercepted authorization code can be redeemed by brute-forcing low-entropy verifiers that the server should have rejected under RFC7636.
This weakens PKCE’s protection goal and allows token theft when clients generate short/predictable verifiers.
Summary
The token exchange path accepts RFC7636-invalid
code_verifiervalues (including one-character strings) forS256PKCE flows.Because short/weak verifiers are accepted and failed verifier attempts do not consume the authorization code, an attacker who intercepts an authorization code can brute-force
code_verifierguesses online until token issuance succeeds.Root cause
lib/pkce/pkce.js(getHashForCodeChallenge) only checks thatverifieris a non-empty string before hashing forS256; it does not enforce RFC7636 ABNF (43..128unreserved chars).lib/grant-types/authorization-code-grant-type.jscompareshash(code_verifier)to storedcodeChallengewithout validating verifier format/length.AuthorizationCodeGrantType.handle, authorization code revocation happens after verifier validation. Invalid guesses fail before revoke, so the same code can be retried repeatedly.Steps to Reproduce
Setup
codeChallengeMethod = "S256"codeChallenge = BASE64URL(SHA256("z"))(verifier is one character, RFC-invalid)Reproduction
code_verifiervalues:invalid_grant.a..z).code_verifier=z, token issuance succeeds and returns bearer tokens.Confirmed PoC output
Impact
An intercepted authorization code can be redeemed by brute-forcing low-entropy verifiers that the server should have rejected under RFC7636.
This weakens PKCE’s protection goal and allows token theft when clients generate short/predictable verifiers.
Recommended Fix
pkce.codeChallengeMatchesABNF(request.body.code_verifier)in authorization code token exchange before hashing/comparison.43..128unreserved).