astrid-runtime/astrid · critical
OS CSPRNG unavailable while generating invite token
Error message
OS CSPRNG unavailable while generating invite token
What it means
Panic from `SysRng.try_fill_bytes(&mut bytes).expect("OS CSPRNG unavailable while generating invite token")` in `generate_token` (crates/astrid-kernel/src/invite/mod.rs:675). The library refuses to generate an invite token from anything but the OS cryptographically secure RNG (rand::rngs::SysRng); if the operating system's entropy source (/dev/urandom, getrandom) is unavailable, it panics rather than fall back to a weak source.
Solutions
- Restore OS entropy access: ensure /dev/urandom exists and getrandom(2) is permitted by seccomp/AppArmor/sandbox policy.
- If running in a container, add the device and adjust the syscall allowlist (e.g. docker run with proper /dev mounts).
- Retry at process start after entropy is initialized (wait for rngd / kernel crng ready).
- Replace expect with error propagation (try_fill_bytes returns Result) so callers can degrade gracefully instead of panicking.
Example fix
// before
SysRng.try_fill_bytes(&mut bytes).expect("OS CSPRNG unavailable while generating invite token");
// after
SysRng.try_fill_bytes(&mut bytes)
.map_err(|e| InviteError::RngUnavailable(e))?; Defensive patterns
Strategy: try-catch
Validate before calling
// preflight: verify OS CSPRNG works before generating tokens
use rand::{TryRng, rngs::SysRng};
let mut probe = [0u8; 1];
let rng_ok = SysRng.try_fill_bytes(&mut probe).is_ok(); Try / catch
// wrap token generation so panics don't take down the request
let token = std::panic::catch_unwind(generate_token)
.map_err(|_| InviteError::RngUnavailable)?; Prevention
- Smoke-test the RNG at service startup and fail fast with a clear message.
- Ensure containers allow getrandom(2) and expose /dev/urandom.
- Avoid generating tokens before kernel crng initialization on early-boot systems.
- Prefer a fallible generate_token API over expect in library code.
When it happens
Trigger: Calling `generate_token()` on a system where the OS CSPRNG fails: exhausted/fileless entropy setups, containers without /dev/urandom, seccomp/sandbox rules blocking getrandom(2), or extremely early boot before entropy initialization.
Common situations: Hardened containers with restricted syscalls, chroot/jail environments missing device nodes, custom Linux builds without getrandom, or VM snapshots resumed with RNG misconfiguration.
Related errors
- OS CSPRNG unavailable while generating invite suffix
- OS CSPRNG unavailable while generating default keypair name
- OS CSPRNG unavailable while generating gateway signing key
- alice
- astrid distro apply requires a signed Distro…
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/070ad5b7f42b6881.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-kernel/src/invite/mod.rs:675
struct PersistedFile {
#[serde(default)]
schema_version: u32,
#[serde(default)]
invite: Vec<Invite>,
}
/// Generate a typed token with a random URL-safe-base64 secret. Uses the OS CSPRNG.
///
/// # Panics
///
/// Panics if the OS CSPRNG is unavailable.
#[must_use]
pub fn generate_token() -> String {
use rand::{TryRng, rngs::SysRng};
let mut bytes = [0u8; TOKEN_RAW_LEN];
SysRng
.try_fill_bytes(&mut bytes)
.expect("OS CSPRNG unavailable while generating invite token");
format!(
"{TOKEN_PREFIX}{}",
base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(bytes)
)
}
/// Derive a token identifier for storage and lookup.
#[must_use]
pub fn hash_token(token: &str) -> String {
IdentifierHash::derive(TOKEN_HASH_CONTEXT, token.as_bytes()).to_prefixed_hex()
}
/// Constant-time hash comparison. Both inputs must be `blake3:<hex>`
/// identifiers. Returns `false` on any length mismatch
/// without leaking the position via short-circuit.
#[must_use]
pub fn ct_hash_eq(a: &str, b: &str) -> bool {
if a.len() != b.len() {View on GitHub (pinned to affd8760f4)