{"record":{"id":"0dd5c7b94b4e0c4e","repo":"zeroclaw-labs/zeroclaw","slug":"system-rng-failed","errorCode":null,"errorMessage":"system RNG failed","messagePattern":"system RNG failed","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-runtime/src/agent/tool_receipts.rs","lineNumber":32,"sourceCode":"#[derive(Clone)]\npub struct ReceiptGenerator {\n    key: Vec<u8>,\n}\n\nimpl Default for ReceiptGenerator {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\nimpl ReceiptGenerator {\n    /// Create a new generator with a random 256-bit ephemeral key.\n    pub fn new() -> Self {\n        use ring::rand::{SecureRandom, SystemRandom};\n        let mut key = vec![0u8; 32];\n        SystemRandom::new()\n            .fill(&mut key)\n            .expect(\"system RNG failed\");\n        Self { key }\n    }\n\n    #[cfg(test)]\n    pub fn with_key(key: Vec<u8>) -> Self {\n        Self { key }\n    }\n\n    /// Generate a receipt for a tool execution.\n    /// The receipt encodes: tool_name | args_hash | result_hash | timestamp\n    /// into an HMAC-SHA256 digest, formatted as `zc-receipt-{timestamp}-{hash}`.\n    pub fn generate(\n        &self,\n        tool_name: &str,\n        args: &serde_json::Value,\n        result: &str,\n        timestamp: u64,\n    ) -> String {","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-runtime/src/agent/tool_receipts.rs#L14-L50","documentation":"ReceiptKeyGenerator::new() creates a random 256-bit HMAC key using ring's SystemRandom. fill() virtually never fails; when it does, the operating system's entropy source is unavailable (no /dev/urandom, getrandom(2) blocked by a sandbox policy). The library treats working system entropy as a hard requirement and panics.","triggerScenarios":"Calling ReceiptKeyGenerator::new() in an environment where the OS randomness source is inaccessible: containers with a seccomp/AppArmor profile denying getrandom, a chroot without /dev/urandom mounted, or exotic platforms early in boot before the kernel entropy pool is ready.","commonSituations":"Minimal distroless/alpine containers with restrictive runtime profiles; gVisor/Firecracker sandboxes with narrowed syscall surfaces; test harnesses running inside locked-down CI executors.","solutions":["Ensure /dev/urandom exists and is readable inside the container or chroot (install/mount it, or use a fuller base image).","Adjust the container security profile (seccomp, AppArmor, gVisor config) to allow getrandom(2) / reads of /dev/urandom.","For deterministic tests, use ReceiptKeyGenerator::with_key(...) instead of new() so no system RNG is needed."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Probe the OS entropy source before starting in locked-down environments:\nlet mut probe = [0u8; 1];\ngetrandom::getrandom(&mut probe)\n    .map_err(|e| anyhow::anyhow!(\"system RNG unavailable: {e}; check /dev/urandom and seccomp policy\"))?;\nlet generator = ReceiptKeyGenerator::new();","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Verify /dev/urandom is mounted and readable in minimal containers or chroots.","Allow getrandom(2) in seccomp/AppArmor/gVisor profiles for the agent process.","Use ReceiptKeyGenerator::with_key() in deterministic tests to sidestep the system RNG."],"tags":["rust","crypto","rng","environment","docker","sandbox"],"backgroundTag":"system-entropy-unavailable","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}