astrid-runtime/astrid · critical

OS CSPRNG unavailable while generating gateway signing key

Error message

OS CSPRNG unavailable while generating gateway signing key

What it means

`State::fresh()` generates a 32-byte gateway signing key using the OS CSPRNG (`SysRng.try_fill_bytes`). It panics with this message if the OS random source cannot fill the buffer, because an unpredictable key is mandatory for signing — proceeding would be insecure. This is a fail-fast panic, not a recoverable error.

Solutions

  1. Fix the host so the OS CSPRNG works (allow the `getrandom` syscall in the container/sandbox profile).
  2. Retry process startup once entropy is available (the condition is usually transient at boot).
  3. If the platform genuinely lacks a CSPRNG, switch the RNG provider to one backed by a hardware RNG and re-audit.
  4. Never replace this with a deterministic/fallback RNG — the panic is intentional.

Example fix

// before (blocks startup under seccomp)
let state = SignState::fresh();
// after: surface the entropy failure instead of panicking deep in construction
let secret = SysRng
    .try_fill_bytes(&mut buf)
    .map_err(|e| StartupError::EntropyUnavailable(e.to_string()))?;
let state = SignState::from_secret(secret);
Defensive patterns

Strategy: fallback

Validate before calling

// Rust: probe the OS RNG before constructing signing state
fn entropy_available() -> bool {
    let mut b = [0u8; 1];
    SysRng.try_fill_bytes(&mut b).is_ok()
}

Try / catch

// Rust: catch at startup boundary, not inside fresh()
match SignState::try_fresh() {
    Ok(state) => state,
    Err(e) => { log::error("CSPRNG unavailable: {e}"); std::process::exit(1); }
}

Prevention

When it happens

Trigger: Calling `SignState::fresh()` (at process startup or key generation) when `getrandom`/OS entropy fails: e.g. exhausted `/dev/urandom`, restricted seccomp/sandbox blocking `getrandom(2)`, or a broken RDRAND on some VMs.

Common situations: Running the gateway inside a container/sandbox that blocks the `getrandom` syscall, heavily contended entropy at early boot on embedded/VM hosts, or unusual hardened kernels restricting randomness syscalls.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/f3dcebda227d9656. Report an issue: GitHub.

Appendix: source

Thrown at crates/astrid-gateway/src/state.rs:56

    pub signer: SigningKey,
    /// Verifies incoming bearer tokens. Same key — kept separately
    /// so middleware can hold a cheap `Copy` of the public half.
    pub verifier: VerifyingKey,
}

impl SigningMaterial {
    /// Generate a fresh signing keypair from the OS CSPRNG. Used by
    /// tests and by the load path when the on-disk key is missing.
    ///
    /// # Panics
    ///
    /// Panics if the OS CSPRNG is unavailable.
    #[must_use]
    pub fn fresh() -> Self {
        let mut secret = [0u8; 32];
        SysRng
            .try_fill_bytes(&mut secret)
            .expect("OS CSPRNG unavailable while generating gateway signing key");
        let signer = SigningKey::from_bytes(&secret);
        let verifier = signer.verifying_key();
        Self { signer, verifier }
    }

    /// Load the persisted gateway signing key, generating it on
    /// first boot. Matches the kernel's `runtime.ed25519` load
    /// pattern: 0600 perms, atomic write-then-rename. Same path
    /// layout convention (`keys/` under `$ASTRID_HOME`).
    ///
    /// # Errors
    /// Returns an error if the keys directory can't be created,
    /// the on-disk key is corrupt (wrong length), or the file
    /// write fails.
    pub fn load_or_generate() -> anyhow::Result<Self> {
        use anyhow::Context as _;
        let home = astrid_core::dirs::AstridHome::resolve()
            .context("resolve $ASTRID_HOME for gateway signing key")?;

View on GitHub (pinned to affd8760f4)