Skip to content

[TD-03 follow-up] getrandom 3-way split is structural — driven by aes-gcm 0.10, ahash, and iroh 0.98 #481

@intendednull

Description

@intendednull

Follow-up to #252.

Summary

A /resolving-issues implementer attempt on commit 49855e2 re-ran the audit and found the situation is architectural, not "obvious." The 3 active versions of getrandom (today, not 4 — the audit's 0.4 ×2 was build-script vs target separation) are each pinned by a transitive crate we don't own. A workspace-level getrandom pin alone won't unify them.

Current state (49855e2)

$ cargo tree --target wasm32-unknown-unknown | grep -oE "getrandom v[0-9]+\.[0-9]+\.[0-9]+" | sort -u
getrandom v0.2.17
getrandom v0.3.4
getrandom v0.4.2

Same 3 versions on native.

Who pins each version

Version Pinned by Why we can't unify it
0.2.17 aes-gcm 0.10 and chacha20poly1305 0.10 (via rand_core 0.6getrandom 0.2); also rand 0.8 (used by willow-crypto, willow-agent) Latest stable cryptosuite is 0.10. Bumping to 0.11 would bring rand_core 0.9 / getrandom 0.3 — but aes-gcm 0.11 / chacha20poly1305 0.11 are still RC (0.11.0-rc.3). Won't ship pre-stable RCs.
0.3.4 ahash (transitive via hashbrown / dashmapiroh-relay, leptos, rusqlite); also rand 0.9 (used by willow-identity) ahash pin is upstream; we don't depend on it directly. Bumping iroh / leptos / rusqlite is out of scope.
0.4.2 iroh 0.98 ecosystem (iroh, iroh-base, iroh-gossip, iroh-relay, noq-proto), rand 0.10 (transitive via iroh + rmcp), uuid 1.x (proc-macro side via leptos_macro) Bumping iroh major has its own breaking-change scope. Out of TD-03 scope.

Why the workspace-level pin in #252 doesn't fix this

cargo resolves each major version range independently. Adding getrandom = { version = "0.3", features = ["wasm_js"] } to [workspace.dependencies] would only constrain crates that depend on getrandom = "0.3" semver-compatible — not crates locked to 0.2 (aes-gcm 0.10) or 0.4 (iroh 0.98).

The existing per-crate shim in willow-identity, willow-crypto, willow-messaging (the getrandom_02 = { package = "getrandom", version = "0.2", features = ["js"] } + getrandom_03 = { ..., version = "0.3", features = ["wasm_js"] } pair) is already the correct WASM-safe pattern: it forces js/wasm_js features on whichever transitive copy gets pulled in, regardless of which major version. Removing it would break WASM builds.

What "fixing" this actually requires

Three separate, coordinated upstream events:

  1. aes-gcm 0.11 / chacha20poly1305 0.11 reach stable. Then bump willow-crypto's cryptosuite. (Status: at 0.11.0-rc.3 as of 2026-04-28.)
  2. iroh ≥ ? drops getrandom 0.4 in favor of 0.3 (or unifies internally to 0.4 after the ecosystem catches up). Out of our control.
  3. ahash upstream stabilizes on a single getrandom major. Out of our control.

Until those land, the three-version split is structural.

What we could do, cosmetically (low value)

  • Move the getrandom_02 = { ... } / getrandom_03 = { ... } shim from three per-crate Cargo.tomls to [workspace.dependencies], with each crate doing getrandom_02 = { workspace = true }. Saves ~6 duplicated lines, doesn't change the audit-finding's transitive count. Gold-plating.
  • Bump willow-crypto from rand 0.8rand 0.9 to drop our direct dep on getrandom 0.2. The 0.2 version still gets pulled by aes-gcm 0.10 / chacha20poly1305 0.10 transitively, so the audit count doesn't change. Pure churn.

Neither is worth its own PR.

Recommendation

Refs #252.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions