{"record":{"id":"25b762b4bedaf5cd","repo":"astrid-runtime/astrid","slug":"os-csprng-unavailable-while-generating-default-key","errorCode":null,"errorMessage":"OS CSPRNG unavailable while generating default keypair name","messagePattern":"OS CSPRNG unavailable while generating default keypair name","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/keypair.rs","lineNumber":600,"sourceCode":"            name.len()\n        );\n    }\n    // Lowercase letters, digits, dash. Same posture as principal ids;\n    // also avoids path-separator / shell-meta surprises.\n    if !name\n        .chars()\n        .all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '-')\n    {\n        bail!(\"keypair name {name:?} contains invalid chars; only a-z, 0-9, '-' are allowed\");\n    }\n    Ok(())\n}\n\nfn default_name() -> String {\n    let mut bytes = [0u8; 4];\n    SysRng\n        .try_fill_bytes(&mut bytes)\n        .expect(\"OS CSPRNG unavailable while generating default keypair name\");\n    format!(\"key-{}\", hex::encode(bytes))\n}\n\nfn fingerprint_pubkey(hex_pub: &str) -> Result<String> {\n    PublicKeyFingerprint::from_ed25519_hex(hex_pub)\n        .map(PublicKeyFingerprint::into_inner)\n        .map_err(|e| anyhow::anyhow!(\"fingerprint Ed25519 public key: {e}\"))\n}\n\n/// Convert a 64-char hex ed25519 public key into the `ed25519:<base64>`\n/// wire form that `[distro.signing].pubkey`, `astrid distro seal`, and\n/// the distro trust store consume. Reuses `astrid-crypto`'s encoder so\n/// the base64 variant matches the verifier byte-for-byte.\nfn pubkey_hex_to_wire(pub_hex: &str) -> Result<String> {\n    let pk = astrid_crypto::PublicKey::from_hex(pub_hex.trim())\n        .map_err(|e| anyhow::anyhow!(\"decode public key hex: {e}\"))?;\n    Ok(format!(\"ed25519:{}\", pk.to_base64()))\n}","sourceCodeStart":582,"sourceCodeEnd":618,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/keypair.rs#L582-L618","documentation":"default_name generates a random key-<hex> name using the OS CSPRNG via getrandom (SysRng.try_fill_bytes). If the operating system randomness source is unavailable, the function panics with this expect message instead of returning a keypair name. The randomness is considered a hard requirement for key generation.","triggerScenarios":"Calling commands that need an auto-generated keypair name (e.g. astrid keypair new without --name) on a system where /dev/urandom or getrandom(2) fails — exhausted entropy blocking, seccomp/container policies blocking getrandom, or a broken /dev/urandom.","commonSituations":"Hardened containers/jails that seccomp-filter getrandom; early-boot environments before the RNG is seeded; chroots missing /dev/urandom; VMs with unusual entropy configuration.","solutions":["Fix the environment so getrandom works (restore /dev/urandom, relax seccomp rules blocking getrandom(2))","Pass an explicit keypair name so default_name is never invoked","Retry after the system RNG is available (e.g. after boot completes)","Report/upgrade if running on a platform whose RNG syscall is unsupported"],"exampleFix":"// before\nastrid keypair new\n// after\nastrid keypair new --name my-key","handlingStrategy":"fallback","validationCode":"// probe RNG availability before invoking keypair commands\nlet mut b = [0u8; 1];\ngetrandom::getrandom(&mut b).map_err(|_| \"OS CSPRNG unavailable\")?;","typeGuard":null,"tryCatchPattern":"// the library panics, so guard the entry point\nlet out = Command::new(\"astrid\").args([\"keypair\", \"new\"]).output()?;\nif !out.status.success()\n    && String::from_utf8_lossy(&out.stderr).contains(\"OS CSPRNG unavailable\") {\n    eprintln!(\"RNG unavailable; pass an explicit --name or fix entropy\");\n}","preventionTips":["Pass an explicit keypair name in automated/CI environments","Avoid running key generation in seccomp-restricted containers without getrandom","Monitor entropy/RNG health on minimal or early-boot systems"],"tags":["crypto","rng","panic","entropy"],"backgroundTag":"internal-invariant-violation","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}