Executive Summary
A critical cryptographic weakness has been identified in the Mojolicious::Plugin::Web::Auth::OAuth2 Perl module — all versions through 0.17. When no custom state generator is configured, the module defaults to generating the OAuth 2.0 state parameter using a SHA-1 hash of low-entropy inputs: the current epoch time (leaked via the HTTP Date header) and Perl's built-in rand() function. This predictable state value violates the OAuth 2.0 specification's CSRF protection requirements and allows unauthenticated remote attackers to perform session hijacking via CSRF.
CVE-2026-9733 carries a CVSS 3.1 score of 9.1 (CRITICAL).
Vulnerability Details
| Field | Value |
|---|---|
| CVE ID | CVE-2026-9733 |
| CVSS 3.1 Score | 9.1 (CRITICAL) |
| Attack Vector | Network |
| Attack Complexity | Low |
| Privileges Required | None |
| User Interaction | None |
| Scope | Unchanged |
| Impact | Confidentiality High, Integrity High |
| CWE | CWE-338 (Weak PRNG), CWE-340 (Predictable Identifiers) |
Affected Component
The vulnerable code resides in lib/Mojolicious/Plugin/Web/Auth/OAuth2.pm within the _state_generator routine. When an application registers the plugin without specifying a custom state generator, the default implementation constructs the state value as:
# Pseudocode representation of the vulnerable default
sub _state_generator {
my $epoch = time(); # Leaked via HTTP Date header
my $rand = rand(); # Low-entropy Perl built-in
return sha1_hex("$epoch$rand");
}An attacker who observes the Date response header can narrow the time() value to a small window. Combined with the weak seeding of Perl's rand(), the entire state space becomes computationally feasible to brute-force, enabling a forged OAuth callback that the module will accept as legitimate.
Attack Flow
- Attacker initiates an OAuth flow against a target application, capturing the
Dateheader. - Using the known epoch window, attacker precomputes candidate state values.
- Attacker crafts a malicious OAuth callback URL containing a predicted state value.
- Victim's browser (or application) is directed to the malicious callback.
- Module validates the forged state as legitimate — attacker gains control of the OAuth session.
This attack satisfies RFC 6749 §10.12 CSRF threat requirements: the state parameter must be unpredictable and unguessable.
Impact
- Session Hijacking: Attacker can complete the OAuth flow as the victim, obtaining their access token and authenticated session.
- Account Takeover: Any account linked via this OAuth plugin is potentially compromisable.
- No Authentication Required: The attack is fully unauthenticated — no existing account or session needed.
- Scope: All Perl/Mojolicious applications using
Mojolicious::Plugin::Web::Auth::OAuth2through version 0.17 without a custom state generator.
Remediation
Immediate Actions
-
Apply the patch: Update to a version incorporating the
CVE-2026-9733-r2.patchfix available viasecurity.metacpan.org. The patch replaces the default state generator with a cryptographically secure random bytes source. -
Specify a custom state generator: If updating immediately is not possible, override the default by explicitly configuring a CSPRNG-based generator in your plugin registration:
$app->plugin('Web::Auth::OAuth2', {
# ...
state_generator => sub {
require Bytes::Random::Secure;
return Bytes::Random::Secure::random_hex_string(32);
},
});-
Audit OAuth callback logs: Review recent OAuth completions for unexpected state values or anomalous timing patterns that may indicate exploitation.
-
Rotate OAuth tokens: For any application that may have been exposed, rotate OAuth client secrets and revoke outstanding access tokens.
Verification
After patching, verify that the state parameter is generated using Crypt::URandom, Bytes::Random::Secure, or an equivalent CSPRNG-backed source — not rand() or time().
Timeline
| Date | Event |
|---|---|
| 2026-01 | Vulnerability reported via oss-security mailing list |
| 2026-06-23 | NVD published, CVSS 9.1 assigned by CISA-ADP |
| Pending | Official patched release on CPAN |