aaif-goose/goose · critical
{e}
Error message
{e} What it means
Passthrough of the failure from sigstore_verify::verify: the bundle parsed fine but cryptographic verification failed — artifact digest mismatch, certificate chain not rooted in the pinned trusted root, expired certificates, or policy rejection. In verify_provenance this per-bundle error is captured and ultimately surfaces inside the final 'Sigstore verification failed' message.
Source
Thrown at crates/goose-cli/src/commands/update.rs:171
}
req.send().await.context("Failed to fetch attestations")
}
// Verify a single attestation bundle against the artifact digest and workflow.
fn verify_bundle(
bundle_json: &serde_json::Value,
artifact_digest: Sha256Hash,
policy: &VerificationPolicy,
trusted_root: &TrustedRoot,
workflow: &str,
) -> Result<()> {
let bundle_str = serde_json::to_string(bundle_json)?;
let bundle = Bundle::from_json(&bundle_str)
.map_err(|e| anyhow::anyhow!("Failed to parse bundle: {e}"))?;
let result = sigstore_verify::verify(artifact_digest, &bundle, policy, trusted_root)
.map_err(|e| anyhow::anyhow!("{e}"))?;
let identity = result
.identity
.as_deref()
.ok_or_else(|| anyhow::anyhow!("No identity in certificate"))?;
let expected = format!("/.github/workflows/{workflow}");
if !identity.contains(&expected) {
bail!("Workflow mismatch: expected {workflow}, got {identity}");
}
Ok(())
}
/// Returns `Ok(())` when the downloaded archive has verified provenance.
async fn verify_provenance(archive_data: &[u8], tag: &str) -> Result<()> {
let digest = sha256_hex(archive_data);
println!("Archive SHA-256: {digest}");View on GitHub (pinned to 3810898a74)
Solutions
- Treat as a hard stop — never bypass or downgrade the verification
- Delete any cached download and re-run `goose update` from a trusted network
- Verify the artifact manually with slsa-verifier against the official GitHub release to confirm
- If manual verification also fails, report possible tampering to the goose maintainers
Defensive patterns
Strategy: try-catch
Try / catch
match sigstore_verify::verify(digest, &bundle, &policy, &trusted_root) {
Ok(result) => { /* continue with identity check */ }
Err(e) => {
// fail closed: log and abort; never proceed with an unverified artifact
anyhow::bail!("provenance verification failed: {e}");
}
} Prevention
- Never catch-and-continue on verification errors — abort the update entirely
- Verify suspicious artifacts independently with slsa-verifier before reporting
- Check the system clock; wildly wrong time can fail otherwise-valid certificates
When it happens
Trigger: Archive bytes do not match the digest signed in the attestation (corrupted or tampered download); attestation signed by a key/cert outside goose's trusted root; replayed bundle from a different release; expired Fulcio cert at verification time.
Common situations: MITM'd or mirrored downloads; cached/partial downloads resumed incorrectly; release published with unsigned or mis-signed provenance; system clock badly wrong.
Related errors
- Sigstore verification failed: {} Aborting update due to sec
- Failed to parse bundle: {e}
- No identity in certificate
- goose serve TLS certificate fingerprint did not match readin
- GOOSE_SERVER__SECRET_KEY must be set to start `goose serve`;
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/516625c4159c34c5.
Report an issue: GitHub.