CVE-2026-41213
@node-oauth/oauth2-server: PKCE code_verifier ABNF not enforced in token exchange allows brute-force redemption of intercepted authorization codes
@node-oauth/oauth2-server is a module for implementing an OAuth2 server in Node.js. 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.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- High
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- None
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
5.9
@node-oauth/oauth2-server: PKCE code_verifier ABNF not enforced in token exchange allows brute-force redemption of intercepted authorization codes
@node-oauth/oauth2-server is a module for implementing an OAuth2 server in Node.js. 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.
- Record
CVE-2026-41213- CVSS 3.1
- 5.9 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-307, CWE-1289
- Updated
- 2026-11-02
EUVDEUVD-2026-25272
5.9
@node-oauth/oauth2-server is a module for implementing an OAuth2 server in Node.js. 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.
- Record
EUVD-2026-25272- CVSS 3.1
- 5.9 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-jhm7-29pj-4xvf
5.9
@node-oauth/oauth2-server: PKCE code_verifier ABNF not enforced in token exchange allows brute-force redemption of intercepted authorization codes
Summary
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.
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.- In
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
- PKCE authorization code exists with:
codeChallengeMethod = "S256"codeChallenge = BASE64URL(SHA256("z"))(verifier is one character, RFC-invalid)
- Attacker has intercepted the authorization code value.
Reproduction
- Send repeated token requests with guessed
code_verifiervalues:
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>
- Observe invalid guesses return
invalid_grant. - Continue guessing (
a..z). - When
code_verifier=z, token issuance succeeds and returns bearer tokens.
Confirmed PoC output
BRUTE_FORCE_SUCCESS { tries: 26, guess: 'z', status: 200, tokenIssued: true }
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
- Enforce
pkce.codeChallengeMatchesABNF(request.body.code_verifier)in authorization code token exchange before hashing/comparison. - Reject verifier values outside RFC7636 charset/length (
43..128unreserved). - Invalidate authorization codes on failed verifier attempts (or add strict retry limits) to prevent online guessing.
- Record
GHSA-jhm7-29pj-4xvf- CVSS 3.1
- 5.9 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-307, CWE-1289
- Updated
- 2026-11-02
NVD
5.9
@node-oauth/oauth2-server is a module for implementing an OAuth2 server in Node.js. 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.
- Record
CVE-2026-41213- CVSS 3.1
- 5.9 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-307, CWE-1289
- Updated
- 2026-11-02
OSV
5.9
@node-oauth/oauth2-server: PKCE code_verifier ABNF not enforced in token exchange allows brute-force redemption of intercepted authorization codes
@node-oauth/oauth2-server is a module for implementing an OAuth2 server in Node.js. 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.
- Record
CVE-2026-41213- CVSS 3.1
- 5.9 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-1289, CWE-307
- Updated
- 2026-11-02
OSVGHSA-jhm7-29pj-4xvf
5.9
@node-oauth/oauth2-server: PKCE code_verifier ABNF not enforced in token exchange allows brute-force redemption of intercepted authorization codes
Summary
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.
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.- In
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
- PKCE authorization code exists with:
codeChallengeMethod = "S256"codeChallenge = BASE64URL(SHA256("z"))(verifier is one character, RFC-invalid)
- Attacker has intercepted the authorization code value.
Reproduction
- Send repeated token requests with guessed
code_verifiervalues:
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>
- Observe invalid guesses return
invalid_grant. - Continue guessing (
a..z). - When
code_verifier=z, token issuance succeeds and returns bearer tokens.
Confirmed PoC output
BRUTE_FORCE_SUCCESS { tries: 26, guess: 'z', status: 200, tokenIssued: true }
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
- Enforce
pkce.codeChallengeMatchesABNF(request.body.code_verifier)in authorization code token exchange before hashing/comparison. - Reject verifier values outside RFC7636 charset/length (
43..128unreserved). - Invalidate authorization codes on failed verifier attempts (or add strict retry limits) to prevent online guessing.
- Record
GHSA-jhm7-29pj-4xvf- CVSS 3.1
- 5.9 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-1289, CWE-307
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
@node-oauth/oauth2-servernpm |
through 5.2.1 | 5.3.0 |
@node-oauth/oauth2-servernpm |
before 5.3.0 | 5.3.0 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-41213 is a medium vulnerability (CVSS 5.9) in Node-oauth Node-oauth2-server, published April 16, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.26%, the 17th percentile. Fixed in @node-oauth/oauth2-server 5.3.0.