CVE-2026-41564 Overview
CVE-2026-41564 is an insecure random number generation vulnerability in CryptX versions before 0.088 for Perl. The Crypt::PK modules fail to reseed their PRNG (Pseudorandom Number Generator) state after process forking operations, leading to identical cryptographic output across multiple child processes.
The Crypt::PK::RSA, Crypt::PK::DSA, Crypt::PK::DH, Crypt::PK::ECC, Crypt::PK::Ed25519, and Crypt::PK::X25519 modules seed a per-object PRNG state in their constructors and reuse it without fork detection. When a Crypt::PK::* object is created before fork(), it shares byte-identical PRNG state with every child process. Any randomized cryptographic operation performed by these child processes can produce identical output, including key generation.
Critical Impact
Two ECDSA or DSA signatures from different forked processes using the same PRNG state are sufficient to recover the signing private key through nonce-reuse key recovery attacks. This is particularly dangerous in preforking server environments like Starman.
Affected Products
- CryptX versions before 0.088 for Perl
- Crypt::PK::RSA, Crypt::PK::DSA, Crypt::PK::DH, Crypt::PK::ECC, Crypt::PK::Ed25519, Crypt::PK::X25519 modules
- Preforking services such as Starman web server that inherit Crypt::PK::* objects from parent processes
Discovery Timeline
- 2026-04-23 - CVE-2026-41564 published to NVD
- 2026-04-23 - Last updated in NVD database
Technical Details for CVE-2026-41564
Vulnerability Analysis
This vulnerability stems from improper PRNG state management in the CryptX library's public-key cryptography modules. When a Perl application using CryptX creates a cryptographic object and subsequently calls fork(), the PRNG state is duplicated to all child processes without reseeding. Since the PRNG is deterministic given its state, all forked processes will generate identical "random" values when performing cryptographic operations.
The impact is most severe for signature schemes like ECDSA and DSA that rely on unique, unpredictable nonces for each signature. When two signatures are created with the same nonce but different messages, an attacker can mathematically recover the private key. This is a well-documented cryptographic attack known as nonce-reuse key recovery.
Preforking web servers like Starman are particularly vulnerable because they typically load application code (including cryptographic objects) in the parent process before forking worker processes to handle requests.
Root Cause
The root cause is the absence of fork detection in the Crypt::PK::* module structures. Each cryptographic object maintains a prng_state and pindex for its random number generation, but lacks a mechanism to detect when the process has forked. Without a last_pid field to track the process ID at PRNG initialization time, the library cannot detect when it's operating in a forked child process and needs to reseed.
Attack Vector
The attack exploits the network-accessible nature of preforking services:
- An attacker identifies a service using CryptX in a preforking architecture (e.g., Starman)
- The attacker triggers multiple requests that cause different worker processes to perform signing operations
- Due to shared PRNG state, workers generate signatures with identical nonces
- The attacker collects two or more signatures with the same nonce but different messages
- Using the nonce-reuse recovery formula, the attacker computes the private signing key
- With the recovered private key, the attacker can forge signatures or impersonate the service
// Security patch adding fork detection via last_pid field
typedef struct rsa_struct { /* used by Crypt::PK::RSA */
prng_state pstate;
int pindex;
+ IV last_pid;
rsa_key key;
} *Crypt__PK__RSA;
typedef struct dsa_struct { /* used by Crypt::PK::DSA */
prng_state pstate;
int pindex;
+ IV last_pid;
dsa_key key;
} *Crypt__PK__DSA;
typedef struct dh_struct { /* used by Crypt::PK::DH */
prng_state pstate;
int pindex;
+ IV last_pid;
dh_key key;
} *Crypt__PK__DH;
typedef struct ecc_struct { /* used by Crypt::PK::ECC */
prng_state pstate;
int pindex;
+ IV last_pid;
ecc_key key;
} *Crypt__PK__ECC;
Source: GitHub Commit Patch
The fix initializes last_pid in the constructor:
if (!RETVAL) croak("FATAL: Newz failed");
RETVAL->key.type = -1;
RETVAL->pindex = find_prng("chacha20");
+ RETVAL->last_pid = (IV)PerlProc_getpid();
if (RETVAL->pindex == -1) {
Safefree(RETVAL);
croak("FATAL: find_prng('chacha20') failed");
Source: GitHub Commit Patch
Detection Methods for CVE-2026-41564
Indicators of Compromise
- Detection of identical ECDSA or DSA signature nonces across different requests or worker processes
- Cryptographic signatures with recoverable private keys indicating nonce reuse
- Multiple SSL/TLS handshakes from the same server producing identical ephemeral keys
- Duplicate random values in DH or ECDH key exchanges from preforking services
Detection Strategies
- Audit Perl applications using CryptX modules for preforking patterns (Starman, Starlet, Twiggy with multiple workers)
- Monitor for Crypt::PK::* object instantiation in parent processes before fork() calls
- Implement signature nonce logging and anomaly detection for services using DSA/ECDSA
- Review dependency manifests for CryptX versions below 0.088
Monitoring Recommendations
- Enable logging of cryptographic operations in production environments to detect nonce collisions
- Implement automated dependency scanning to identify vulnerable CryptX versions in CI/CD pipelines
- Monitor security advisories for Perl cryptographic libraries via the OpenWall Security Mailing List
- Configure SentinelOne agents to detect anomalous cryptographic behavior patterns in monitored Perl processes
How to Mitigate CVE-2026-41564
Immediate Actions Required
- Upgrade CryptX to version 0.088 or later immediately
- Audit all Perl applications using Crypt::PK::* modules for preforking patterns
- Rotate any cryptographic keys that may have been generated or used in vulnerable preforking configurations
- Review DSA and ECDSA signatures generated by affected systems for potential nonce reuse
Patch Information
The vulnerability is fixed in CryptX version 0.088, which adds fork detection by tracking the process ID (last_pid) in each cryptographic object structure. When a cryptographic operation is performed, the library now compares the current PID with the stored PID and reseeds the PRNG if they differ.
Patch details are available in the GitHub Security Advisory and the fixed version can be obtained from MetaCPAN.
Workarounds
- Defer Crypt::PK::* object instantiation until after fork() completes in worker processes
- Explicitly reseed PRNG state in worker processes immediately after fork using system entropy
- Avoid using preforking server architectures with CryptX until upgraded to version 0.088
- Consider using alternative cryptographic libraries with proper fork safety until patching is complete
# Upgrade CryptX via CPAN
cpanm CryptX@0.088
# Verify installed version
perl -MCryptX -e 'print $CryptX::VERSION, "\n"'
# For applications using cpanfile, update dependency
echo 'requires "CryptX", ">= 0.088";' >> cpanfile
cpanm --installdeps .
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

