Summary
Every provider generated the OAuth state parameter with Math.random(), and the X (Twitter) provider generated its PKCE code_verifier the same way. Math.random() is not a cryptographically secure pseudorandom number generator, so neither value is unpredictable.
Details
The state parameter is the anti-CSRF token of the authorization flow and must be unguessable (RFC 6749 Section 10.12), and RFC 7636 Section 7.1 requires the PKCE code_verifier to come from a cryptographically secure generator. Both were derived from Math.random(), which V8 implements as xorshift128+: its internal state is recoverable from a small number of observed outputs, after which every subsequent value follows deterministically. The generator is a single stream shared across requests on an instance, and each authorization request emits a fresh state in a redirect URL that whoever initiated it can read.
This issue affects all providers. Applications that supply their own state through the state option, available on googleAuth, msentraAuth and twitchAuth, do not reach the affected path for that value.
Impact
An attacker able to sample the generator's output may predict state values issued to other requests on the same instance, defeating the protection the parameter provides. This may lead to:
- Login CSRF, where the victim continues inside the attacker's account
- Forced account linking, where the attacker's identity is attached to the victim's account
Recovering the generator state and aligning it with a concurrent request is intricate, which limits practical exploitation. On the X provider the same weakness applies to the code_verifier, which is what otherwise binds a callback to the browser that started the flow.
Summary
Every provider generated the OAuth
stateparameter withMath.random(), and the X (Twitter) provider generated its PKCEcode_verifierthe same way.Math.random()is not a cryptographically secure pseudorandom number generator, so neither value is unpredictable.Details
The
stateparameter is the anti-CSRF token of the authorization flow and must be unguessable (RFC 6749 Section 10.12), and RFC 7636 Section 7.1 requires the PKCEcode_verifierto come from a cryptographically secure generator. Both were derived fromMath.random(), which V8 implements as xorshift128+: its internal state is recoverable from a small number of observed outputs, after which every subsequent value follows deterministically. The generator is a single stream shared across requests on an instance, and each authorization request emits a freshstatein a redirect URL that whoever initiated it can read.This issue affects all providers. Applications that supply their own
statethrough thestateoption, available ongoogleAuth,msentraAuthandtwitchAuth, do not reach the affected path for that value.Impact
An attacker able to sample the generator's output may predict
statevalues issued to other requests on the same instance, defeating the protection the parameter provides. This may lead to:Recovering the generator state and aligning it with a concurrent request is intricate, which limits practical exploitation. On the X provider the same weakness applies to the
code_verifier, which is what otherwise binds a callback to the browser that started the flow.