Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-11625

CVE-2026-11625: Perl Bytes::Random::Secure Vulnerability

CVE-2026-11625 is an information disclosure vulnerability in Bytes::Random::Secure for Perl where shared PRNG state across forked processes produces predictable secrets in multiprocess applications. This article covers the technical details, affected versions through 0.29, impact analysis, and mitigation strategies.

Published:

CVE-2026-11625 Overview

CVE-2026-11625 affects the Perl module Bytes::Random::Secure in versions through 0.29. The module shares internal pseudo-random number generator (PRNG) state across forked processes, producing identical random streams in child processes. When an object is initialised before fork(), or when the functional interface is used, secrets generated in multiprocess applications become predictable across processes. The flaw is classified under CWE-335: Incorrect Usage of Seeds in Pseudo-Random Number Generator. Applications using this module to generate tokens, session identifiers, passwords, or cryptographic material in pre-forking servers are directly affected.

Critical Impact

Secrets, tokens, and keys generated by forked Perl processes are predictable and reproducible across workers, undermining confidentiality guarantees for authentication and cryptographic material.

Affected Products

  • Bytes::Random::Secure Perl module, all versions up to and including 0.29
  • Perl applications importing the functional interface (random_bytes, random_bytes_hex, random_bytes_base64, random_string_from)
  • Pre-forking Perl web servers and worker pools that instantiate the module before calling fork()

Discovery Timeline

  • 2026-06-26 - CVE-2026-11625 published to the National Vulnerability Database
  • 2026-07-01 - Last updated in NVD database

Technical Details for CVE-2026-11625

Vulnerability Analysis

Bytes::Random::Secure wraps Math::Random::ISAAC to provide cryptographically strong random bytes. The module initialises an ISAAC PRNG instance and reuses it for subsequent calls. When a parent process seeds this PRNG and then calls fork(), each child inherits an exact copy of the PRNG internal state. Every child that calls random_bytes() produces the same output sequence as its siblings.

The functional interface aggravates the flaw. It lazily instantiates a package-global PRNG on first use, so any early call in the parent locks in shared state before workers are spawned. Applications that rely on the module to generate session cookies, CSRF tokens, password reset codes, or symmetric keys will emit colliding secrets from concurrent workers.

The issue does not weaken the underlying algorithm. It weakens the seeding lifecycle by failing to reseed after fork().

Root Cause

The module does not detect process boundaries. It lacks a pid-tracking mechanism that reseeds the PRNG when the current process identifier differs from the identifier recorded at initialisation. This is the canonical PRNG-across-fork failure mode described by CWE-335.

Attack Vector

An attacker who can request secrets from a multiprocess Perl service can observe repeated or predictable values across workers. By enumerating tokens from concurrent sessions, the attacker can predict values issued to other users, forge session identifiers, or precompute password reset links. Exploitation requires no authentication and no user interaction. The vulnerability is exposed through normal network requests to any endpoint that returns or uses PRNG output.

The upstream fix reseeds the ISAAC instance when a process-identifier mismatch is detected. Technical details are available in the GitHub issue report, the pull request implementing the fix, and the MetaCPAN patch for CVE-2026-11625.

Detection Methods for CVE-2026-11625

Indicators of Compromise

  • Duplicate session identifiers, CSRF tokens, or API keys issued to distinct users within a short time window
  • Repeated random_bytes output observed across concurrent worker processes when logging PRNG-derived values
  • Presence of Bytes::Random::Secure version <= 0.29 in cpanfile, Makefile.PL, or the installed @INC tree

Detection Strategies

  • Inventory Perl dependencies with cpanm --showdeps . or corelist and flag any Bytes::Random::Secure release at or below 0.29
  • Add regression tests that fork, generate random bytes in each child, and assert the outputs differ
  • Instrument application logs to record hashes of newly issued tokens and alert on collisions across worker PIDs

Monitoring Recommendations

  • Correlate authentication events by token hash across worker PIDs in the SIEM to surface duplicate secrets
  • Track deployments of Perl services and pin module versions in software composition analysis (SCA) reports
  • Monitor CPAN and distribution security channels for patched releases superseding 0.29

How to Mitigate CVE-2026-11625

Immediate Actions Required

  • Upgrade Bytes::Random::Secure to a version that incorporates the MetaCPAN patch for CVE-2026-11625
  • Invalidate secrets generated by affected workers, including active sessions, API tokens, and outstanding password reset codes
  • Audit all call sites of random_bytes, random_bytes_hex, random_bytes_base64, and random_string_from in pre-forking applications

Patch Information

The maintainer merged the fix in Bytes-Random-Secure pull request #4. The corresponding source patch is published as CVE-2026-11625-r1.patch. Apply the patch by upgrading through cpanm Bytes::Random::Secure once a release above 0.29 is available, or by applying the patch directly to vendored copies.

Workarounds

  • Instantiate a new Bytes::Random::Secure object inside each child after fork() rather than in the parent
  • Avoid the functional interface in pre-forking servers, and reseed explicitly on child startup handlers such as Starman's psgix.harakiri or mod_perl child init hooks
  • Replace calls with a fork-safe alternative such as Crypt::URandom that reads directly from /dev/urandom for each invocation
bash
# Example: reseed inside each worker on child init (Starman/Plack)
# In your PSGI app or worker startup hook:
use Bytes::Random::Secure;

sub on_child_init {
    # Discard any inherited state and create a fresh instance per PID
    $::PRNG = Bytes::Random::Secure->new(
        Bits        => 256,
        NonBlocking => 0,
    );
}

# Verify: fork two children and confirm outputs differ
perl -MBytes::Random::Secure=random_bytes_hex -e '
    for (1..2) {
        if (fork() == 0) {
            print "pid=$$ ", random_bytes_hex(16), "\n";
            exit;
        }
    }
    wait for 1..2;
'

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.