paragonie/random_compat · critical · Exception
Environment misconfiguration: /dev/urandom cannot be read.
Error message
Environment misconfiguration: /dev/urandom cannot be read.
What it means
random_compat's /dev/urandom backend only opens /dev/urandom when running on a Unix-like OS (DIRECTORY_SEPARATOR === '/'). If is_readable('/dev/urandom') returns false, the library throws because it cannot access the system CSPRNG and must not fall back to weak randomness. This indicates a broken or hostile environment rather than bad arguments.
Solutions
- Ensure /dev/urandom exists and is readable by the PHP user; in containers mount dev (e.g. add /dev/urandom device or run with proper device cgroup).
- Check and fix open_basedir restrictions: add /dev/urandom to open_basedir in php.ini.
- Fix filesystem permissions on /dev/urandom (typically 0666 root:root) or the chroot so the device node is present.
- Upgrade PHP to >= 7.0 for native random_bytes() and verify random_compat still selects a working backend (check which file was loaded).
Example fix
// before (fails in restricted env)
$token = random_bytes(32);
// after
if (!is_readable('/dev/urandom')) {
error_log('CSPRNG unavailable: /dev/urandom not readable; check open_basedir/chroot/container /dev mount');
}
$token = random_bytes(32); Defensive patterns
Strategy: try-catch
Validate before calling
if (DIRECTORY_SEPARATOR === '/' && !is_readable('/dev/urandom')) {
throw new RuntimeException("Environment misconfiguration: /dev/urandom unavailable");
} Try / catch
try {
$bytes = random_bytes(32);
} catch (Exception $e) {
if (strpos($e->getMessage(), '/dev/urandom') !== false) {
// fix env (mount /dev, open_basedir, permissions) — do not use weak RNG
throw new RuntimeException('CSPRNG environment misconfiguration', 0, $e);
}
throw $e;
} Prevention
- Ensure containers/chroots expose /dev/urandom (mount devtmpfs or add the device node).
- Keep /dev/urandom out of open_basedir restrictions or explicitly allow it.
- Verify is_readable('/dev/urandom') as a health check at application boot.
- Run PHP >= 7.0 with a properly provisioned OS so native random_bytes() works.
When it happens
Trigger: Calling random_bytes() on a Unix-like system where /dev/urandom does not exist, is not readable by the PHP process (permissions, chroot/jail without /dev, hardened open_basedir), or the filesystem lacks the device node (some containers/minimal images).
Common situations: Docker/alpine or minimal chroot images without /dev mounted or without the urandom device; hosting environments using open_basedir restricting access to /dev; running PHP as a user without read permission on /dev/urandom; misconfigured chroot for PHP-FPM.
Related errors
- Could not gather sufficient random data
- There is no suitable CSPRNG installed on your system
- COM does not exist
- Could not gather sufficient random data
- Could not gather sufficient random data
AI-assisted analysis of paragonie/random_compat@b5d188cc9d (2026-09-13).
Data as JSON: /api/errors/6a5e8a8819444e68.
Report an issue: GitHub.
Appendix: source
Thrown at lib/random_bytes_dev_urandom.php:69
static $fp = null;
/**
* This block should only be run once
*/
if (empty($fp)) {
/**
* We don't want to ever read C:\dev\random, only /dev/urandom on
* Unix-like operating systems. While we guard against this
* condition in random.php, it doesn't hurt to be defensive in depth
* here.
*
* To that end, we only try to open /dev/urandom if we're on a Unix-
* like operating system (which means the directory separator is set
* to "/" not "\".
*/
if (DIRECTORY_SEPARATOR === '/') {
if (!is_readable('/dev/urandom')) {
throw new Exception(
'Environment misconfiguration: ' .
'/dev/urandom cannot be read.'
);
}
/**
* We use /dev/urandom if it is a char device.
* We never fall back to /dev/random
*/
/** @var resource|bool $fp */
$fp = fopen('/dev/urandom', 'rb');
if (is_resource($fp)) {
/** @var array<string, int> $st */
$st = fstat($fp);
if (($st['mode'] & 0170000) !== 020000) {
fclose($fp);
$fp = false;
}
}View on GitHub (pinned to b5d188cc9d)