{"record":{"id":"b35ea153b1dbabc3","repo":"aaif-goose/goose","slug":"no-identity-in-certificate","errorCode":null,"errorMessage":"No identity in certificate","messagePattern":"No identity in certificate","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/goose-cli/src/commands/update.rs","lineNumber":176,"sourceCode":"// Verify a single attestation bundle against the artifact digest and workflow.\nfn verify_bundle(\n    bundle_json: &serde_json::Value,\n    artifact_digest: Sha256Hash,\n    policy: &VerificationPolicy,\n    trusted_root: &TrustedRoot,\n    workflow: &str,\n) -> Result<()> {\n    let bundle_str = serde_json::to_string(bundle_json)?;\n    let bundle = Bundle::from_json(&bundle_str)\n        .map_err(|e| anyhow::anyhow!(\"Failed to parse bundle: {e}\"))?;\n\n    let result = sigstore_verify::verify(artifact_digest, &bundle, policy, trusted_root)\n        .map_err(|e| anyhow::anyhow!(\"{e}\"))?;\n\n    let identity = result\n        .identity\n        .as_deref()\n        .ok_or_else(|| anyhow::anyhow!(\"No identity in certificate\"))?;\n\n    let expected = format!(\"/.github/workflows/{workflow}\");\n    if !identity.contains(&expected) {\n        bail!(\"Workflow mismatch: expected {workflow}, got {identity}\");\n    }\n\n    Ok(())\n}\n\n/// Returns `Ok(())` when the downloaded archive has verified provenance.\nasync fn verify_provenance(archive_data: &[u8], tag: &str) -> Result<()> {\n    let digest = sha256_hex(archive_data);\n    println!(\"Archive SHA-256: {digest}\");\n\n    let workflow = match tag {\n        \"canary\" => \"canary.yml\",\n        _ => \"release.yml\",\n    };","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/crates/goose-cli/src/commands/update.rs#L158-L194","documentation":"After sigstore_verify::verify succeeds, goose extracts the signer identity from the verified certificate to check it against the expected GitHub Actions workflow. This error means the certificate verified but carried no identity (missing SAN extension) — a malformed provenance certificate from the release pipeline rather than a local environment problem.","triggerScenarios":"A release whose attestation certificate was issued without the identity extension; verification libraries accepting a bundle whose cert lacks the SAN goose expects.","commonSituations":"Upstream release pipeline changes (signing step misconfigured); rare/regional CA issuance quirks; almost never caused by user config.","solutions":["Retry after the next release — the provenance generation is at fault, not your machine","Keep goose itself updated (pinned trusted roots and checks evolve)","Report the release tag to goose maintainers with the error text"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match verify_bundle(&bundle_json, digest, &policy, &trusted_root, workflow) {\n    Err(e) if e.to_string() == \"No identity in certificate\" => {\n        // release-side defect: report tag, do not install\n        anyhow::bail!(\"release provenance lacks signer identity; report to maintainers\");\n    }\n    other => other,\n}","preventionTips":["Treat identity-less certificates as a release defect: report, don't retry-install","Track which goose versions pinned which trusted roots; upgrade before updating across major releases"],"tags":["sigstore","security","supply-chain","certificate"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}