SECURITYCRITICALCVE-2026-9733

CVE-2026-9733: Mojolicious OAuth2 Weak PRNG Enables CSRF Session Hijacking

A critical flaw in the Mojolicious::Plugin::Web::Auth::OAuth2 Perl module uses a predictable SHA-1 state derived from epoch time and rand(), allowing...

Dylan H.

Security Team

June 23, 2026
4 min read
CVE-2026-9733: Mojolicious OAuth2 Weak PRNG Enables CSRF Session Hijacking

Critical severity

Rated critical. Prioritise patching — see the remediation guidance below.

Affected Products

  • Mojolicious::Plugin::Web::Auth::OAuth2 <= 0.17 (Perl/CPAN)

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

FieldValue
CVE IDCVE-2026-9733
CVSS 3.1 Score9.1 (CRITICAL)
Attack VectorNetwork
Attack ComplexityLow
Privileges RequiredNone
User InteractionNone
ScopeUnchanged
ImpactConfidentiality High, Integrity High
CWECWE-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

  1. Attacker initiates an OAuth flow against a target application, capturing the Date header.
  2. Using the known epoch window, attacker precomputes candidate state values.
  3. Attacker crafts a malicious OAuth callback URL containing a predicted state value.
  4. Victim's browser (or application) is directed to the malicious callback.
  5. 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::OAuth2 through version 0.17 without a custom state generator.

Remediation

Immediate Actions

  1. Apply the patch: Update to a version incorporating the CVE-2026-9733-r2.patch fix available via security.metacpan.org. The patch replaces the default state generator with a cryptographically secure random bytes source.

  2. 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);
    },
});
  1. Audit OAuth callback logs: Review recent OAuth completions for unexpected state values or anomalous timing patterns that may indicate exploitation.

  2. 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

DateEvent
2026-01Vulnerability reported via oss-security mailing list
2026-06-23NVD published, CVSS 9.1 assigned by CISA-ADP
PendingOfficial patched release on CPAN

References