Background
release-rust.yml's setup_zig step originally pinned mirror: https://ziglang.org/download, intending to keep the download source fixed and egress-allowlist-friendly. That's wrong: mlugg/setup-zig explicitly rejects ziglang.org as a mirror override (to protect the official site from being hammered by CI) — the pin never actually worked, and the bug went uncaught until purpleclay/release-note became the first real consumer of this workflow and hit it in production: https://github.com/purpleclay/release-note/actions/runs/30449529929/job/90568000749
The immediate fix (done): drop the mirror: override entirely and let the action use its default behavior — a randomized pick from the live community mirror list (https://ziglang.org/download/community-mirrors.txt), falling back to the official site only as a last resort. build's harden_runner stays on egress-policy: audit for now.
Goal
plan and provenance have small, fixed, us-controlled network surfaces (GitHub API, Sigstore endpoints) and are reasonable block-mode candidates today. build is harder: the zig mirror is randomized and externally maintained, so a safe allowlist isn't knowable up front.
Audit mode logs every egress destination without blocking. Over enough real releases, randomization should surface every mirror currently in rotation, at which point we'd have real data to build a complete allowlist from (mirror list + ziglang.org fallback + any Sigstore/toolchain endpoints already in use) and move build to egress-policy: block.
Open caveat, not just the mirror
cargo build/cargo zigbuild also has to resolve and fetch every dependency in whatever Rust project calls this workflow — crates.io at minimum, but potentially more depending on what a given project's build.rs scripts or dependencies reach out to (vendored C libs, git dependencies, etc.). That surface is controlled by the calling project, not by release-workflows, and will differ per consumer (gpg-import, yam, release-note, ...). Confirm whether a single generic allowlist can actually cover this before committing to block mode — it may turn out build needs a per-consumer allowlist input, or needs to stay on audit regardless of the zig mirror being solved.
Acceptance criteria
Background
release-rust.yml'ssetup_zigstep originally pinnedmirror: https://ziglang.org/download, intending to keep the download source fixed and egress-allowlist-friendly. That's wrong:mlugg/setup-zigexplicitly rejectsziglang.orgas a mirror override (to protect the official site from being hammered by CI) — the pin never actually worked, and the bug went uncaught untilpurpleclay/release-notebecame the first real consumer of this workflow and hit it in production: https://github.com/purpleclay/release-note/actions/runs/30449529929/job/90568000749The immediate fix (done): drop the
mirror:override entirely and let the action use its default behavior — a randomized pick from the live community mirror list (https://ziglang.org/download/community-mirrors.txt), falling back to the official site only as a last resort.build'sharden_runnerstays onegress-policy: auditfor now.Goal
planandprovenancehave small, fixed, us-controlled network surfaces (GitHub API, Sigstore endpoints) and are reasonableblock-mode candidates today.buildis harder: the zig mirror is randomized and externally maintained, so a safe allowlist isn't knowable up front.Audit mode logs every egress destination without blocking. Over enough real releases, randomization should surface every mirror currently in rotation, at which point we'd have real data to build a complete allowlist from (mirror list + ziglang.org fallback + any Sigstore/toolchain endpoints already in use) and move
buildtoegress-policy: block.Open caveat, not just the mirror
cargo build/cargo zigbuildalso has to resolve and fetch every dependency in whatever Rust project calls this workflow — crates.io at minimum, but potentially more depending on what a given project'sbuild.rsscripts or dependencies reach out to (vendored C libs, git dependencies, etc.). That surface is controlled by the calling project, not byrelease-workflows, and will differ per consumer (gpg-import,yam,release-note, ...). Confirm whether a single generic allowlist can actually cover this before committing toblockmode — it may turn outbuildneeds a per-consumer allowlist input, or needs to stay onauditregardless of the zig mirror being solved.Acceptance criteria
mirror:pinned to one mirror (or the full observed list added toallowed-endpoints) andbuild'sharden_runnermoved toegress-policy: blockbuilddocumented as staying onauditdeliberately (not as a gap)