Summary
age/Cargo.toml lists rand as a direct dependency, but the crate only uses OsRng and RngCore — both of which are defined in rand_core and merely re-exported by rand. The rand dep can be replaced with rand_core = { version = \"0.6\", features = [\"getrandom\"] } without any logic changes.
Evidence
Three files use rand:
age/src/keys.rs
use rand::{rngs::OsRng, RngCore};
age/src/protocol.rs
use rand::{rngs::OsRng, RngCore};
// used as:
OsRng.fill_bytes(&mut nonce);
age/src/native/x25519.rs
use rand::rngs::OsRng;
// used as:
StaticSecret::random_from_rng(rng)
EphemeralSecret::random_from_rng(rng)
None of these use anything from the rand frontend: no thread_rng, no random(), no distributions, no Rng trait. Every call site goes through OsRng or RngCore, both of which originate in rand_core. rand_core 0.6.4 confirms this directly:
pub use os::OsRng; // gated on feature = "getrandom"
Proposed fix
In age/Cargo.toml, replace:
with:
rand_core = { version = "0.6", features = ["getrandom"] }
(or add rand_core to the workspace deps and reference it similarly)
In the three source files, replace use rand::rngs::OsRng / use rand::RngCore with use rand_core::{OsRng, RngCore}.
Why this matters
rand 0.8 is currently affected by RUSTSEC-2026-0097 / GHSA-cq8v-f236-94qc (unsoundness with custom loggers calling rand::rng() during reseed; fixed in rand 0.9.3). Downstream projects that use age receive a Dependabot alert they cannot resolve themselves — it can only be cleared here.
The advisory is low severity and the trigger conditions (a custom log-crate logger that calls rand::rng()) are unlikely to apply to most age users. But the alert is noise that downstream maintainers have to triage and dismiss, and it goes away entirely by dropping the rand dep.
The broader convention in the Rust crypto ecosystem is to depend on rand_core for traits and leave the rand frontend choice to the application. This change brings age in line with that convention.
Summary
age/Cargo.tomllistsrandas a direct dependency, but the crate only usesOsRngandRngCore— both of which are defined inrand_coreand merely re-exported byrand. Theranddep can be replaced withrand_core = { version = \"0.6\", features = [\"getrandom\"] }without any logic changes.Evidence
Three files use
rand:age/src/keys.rsage/src/protocol.rsage/src/native/x25519.rsNone of these use anything from the
randfrontend: nothread_rng, norandom(), no distributions, noRngtrait. Every call site goes throughOsRngorRngCore, both of which originate inrand_core.rand_core 0.6.4confirms this directly:Proposed fix
In
age/Cargo.toml, replace:with:
(or add
rand_coreto the workspace deps and reference it similarly)In the three source files, replace
use rand::rngs::OsRng/use rand::RngCorewithuse rand_core::{OsRng, RngCore}.Why this matters
rand 0.8is currently affected by RUSTSEC-2026-0097 / GHSA-cq8v-f236-94qc (unsoundness with custom loggers callingrand::rng()during reseed; fixed inrand 0.9.3). Downstream projects that useagereceive a Dependabot alert they cannot resolve themselves — it can only be cleared here.The advisory is low severity and the trigger conditions (a custom
log-crate logger that callsrand::rng()) are unlikely to apply to mostageusers. But the alert is noise that downstream maintainers have to triage and dismiss, and it goes away entirely by dropping theranddep.The broader convention in the Rust crypto ecosystem is to depend on
rand_corefor traits and leave therandfrontend choice to the application. This change bringsagein line with that convention.