ADR 063: Offline release signature verification and update trust policy¶
This page is generated from docs/decisions/*.yaml by task docs:export-adr-markdown. Do not edit manually.
- Number:
063 - Title:
Offline release signature verification and update trust policy - Category:
architecture - Status:
accepted - Provenance:
guided-ai - Source:
docs/decisions/063-offline-release-signature-verification.yaml
Decision¶
Make bb update verifiable without internet access, and make every setting that decides who may vouch for a new bb binary administrative policy only.
1. Offline Sigstore Trust Material:
- update_trusted_root: <path> in system configuration points at a Sigstore trusted_root.json
(produced by cosign trusted-root create, or the TUF target itself). When set, verification
loads trust material from that file instead of fetching it from
https://tuf-repo-cdn.sigstore.dev, and makes no network calls at all: signed certificate
timestamps, the Rekor inclusion promise, and observer timestamps are all checked against keys
carried inside the file. The organisation's existing public-good signatures verify unchanged;
no re-signing is required.
- update_tuf_url: <url> is the alternative for organisations that mirror the Sigstore TUF
repository itself. The TUF fetch uses the CLI's own HTTP client, so the configured CA bundle
and client certificates apply to it. The two settings are mutually exclusive.
- Signer Overrides for Re-Signed Artifacts:
-
update_signature_identityandupdate_signature_issuerreplace the certificate SAN and OIDC issuer bb pins by default (its GitHub Actions release workflow), for organisations that rebuild or re-sign mirrored artifacts against their own Fulcio instance. -
Unverified Updates as a Last Resort:
-
allow_unverified_update: trueskips Sigstore verification. SHA256 checksum verification stays mandatory, so corruption is still caught and tampering is not. Every run that uses it prints a warning to stderr, andsignature_skipped: trueappears in the JSON result. -
Policy-Only Sourcing:
-
None of the five settings above has an environment variable or flag form. They are read from the system configuration file (including its
policies:/policy:blocks) and, on Windows, fromHKLM\Software\Policies\bb.update_base_urlkeeps its flag and environment forms, because signature verification still gates whatever a mirror serves. -
Mirror Download Order:
- When a release mirror is configured, an asset URL that points off the mirror is fetched from
{baseURL}/{assetName}first, and only then from the URL in the manifest. A URL that already resolves onto the mirror is used as-is.
Agent Instructions¶
Never read update trust settings (update_trusted_root, update_tuf_url, update_signature_identity, update_signature_issuer, allow_unverified_update) from environment variables or command flags; they come from administrative policy only. Never skip SHA256 checksum verification, including when allow_unverified_update is set. When adding verification steps to bb update, keep failures to obtain trust material distinguishable from signatures that failed to verify.
Rationale¶
ADR-059 offers release mirrors for air-gapped enclaves, but verification still fetched its trust root from the Sigstore CDN on every run, so bb update could not complete without internet access however the mirror was configured. Pinning the trust root to a file removes that single remaining network dependency while keeping full cryptographic verification, and it is deployed through the same fleet management push that already delivers the corporate CA bundle.
The trust settings are policy-only because each of them changes which signer bb will accept for a binary it is about to execute. Honouring them from the environment would hand that decision to anyone who can set a variable in a user's shell, on the most privileged code path in the CLI. Where the bytes come from is a different question from who signed them, which is why update_base_url remains freely configurable.
Rejected Alternatives¶
Cache the fetched Sigstore trust root on disk and reuse it when offline: The TUF client refreshes expired metadata by design, so a cache is a timing-dependent convenience rather than a guarantee. An air-gapped host would work until the cached metadata expired and then fail, which is worse than not working at all because it fails long after the change that caused it.Allow BB_UPDATE_TRUSTED_ROOT as an environment variable for users without admin rights: A trusted root names the certificate authority allowed to vouch for the release signer, so an attacker-supplied file verifies an attacker-signed binary. Accepting one from the environment would make the entire verification chain bypassable by anyone who can set a variable.Support plain public-key signing (update_verify_key) alongside the identity overrides: Key-based bundles carry no certificate identity, no signed certificate timestamps and usually no transparency log entry, so accepting them means relaxing three independent verification requirements rather than redirecting one. Organisations running a private Fulcio and Rekor are covered by the trusted root and signer overrides; bare-key signing needs its own decision.