| Package | Affected versions | Patched versions |
|---|---|---|
| node-oauth/oauth2-server | < 5.3.0 | 5.3.0 |
| @node-oauth/oauth2-server | < 5.3.0 | 5.3.0 |
The token exchange path accepts RFC7636-invalid code_verifier values (including one-character strings) for S256 PKCE 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_verifier guesses online until token issuance succeeds.
lib/pkce/pkce.js (getHashForCodeChallenge) only checks that verifier is a non-empty string before hashing for S256; it does not enforce RFC7636 ABNF (43..128 unreserved chars).lib/grant-types/authorization-code-grant-type.js compares hash(code_verifier) to stored codeChallenge without 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.codeChallengeMethod = "S256"codeChallenge = BASE64URL(SHA256("z")) (verifier is one character, RFC-invalid)code_verifier values:POST /token HTTP/1.1
Host: oauth.example
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&
client_id=client1&
client_secret=s3cret&
code=stolen-auth-code&
redirect_uri=https://client.example/callback&
code_verifier=<guess>
invalid_grant.a..z).code_verifier=z, token issuance succeeds and returns bearer tokens.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.
Running one of these products? Scan your site to see whether it exposes a vulnerable version.
Scan my site freepkce.codeChallengeMatchesABNF(request.body.code_verifier) in authorization code token exchange before hashing/comparison.43..128 unreserved).