Repository navigation
fix(verifier): do not reject attestations when our pinned TSA chain is stale - #3396
Conversation
…s stale Upstream timestamp authorities rotate their responder certificates without notice. When that happens the pinned certChain no longer matches the signer of the RFC3161 response, and every attestation push fails even though the signature verified against a trusted certificate. Distinguish a timestamp failure caused by our own trust configuration from one caused by the attestation: verifyTimestamp now identifies the response's PKCS#7 signer up front and reports ErrTSASignerNotTrusted, naming the authority and the leaf it expected, when no configured authority signed it. SaveAttestation accepts such attestations with a warning instead of discarding the evidence; verification is recomputed on every read, so the result self-heals once the pinned chain catches up. Failures attributable to the attestation stay fatal. Assisted-by: Claude Code Signed-off-by: Jose I. Paris <jiparis@chainloop.dev> Chainloop-Trace-Sessions: 38ffe2d2-dec5-4c9f-9a68-abf837907af8
AI Session Checks — 🟡 79% · ✅ 0 failing
|
| Status | Attribution | File | Lines |
|---|---|---|---|
| created | ai | pkg/attestation/verifier/timestamp_test.go |
+302 / -0 |
| deleted | ai | app/cli/pkg/action/attestation_verify_test.go |
+75 / -75 |
| modified | ai | pkg/attestation/verifier/timestamp.go |
+91 / -2 |
| modified | ai | app/cli/pkg/action/attestation_verify.go |
+19 / -19 |
| modified | ai | app/controlplane/pkg/biz/workflowrun.go |
+20 / -2 |
| modified | ai | go.mod |
+2 / -2 |
Policies (4)
| Status | Policy | Material | Messages |
|---|---|---|---|
| ✅ Passed | ai-config-ai-agents-allowed |
ai-coding-session-38ffe2 |
- |
| ✅ Passed | ai-config-no-dangerous-commands |
ai-coding-session-38ffe2 |
- |
| ✅ Passed | ai-config-no-secrets |
ai-coding-session-38ffe2 |
- |
| ✅ Passed | ai-config-mcp-servers-allowed |
ai-coding-session-38ffe2 |
- |
Security Checks — ✅ 7 passing
✅ secret-scan
| Status | Policy | Messages |
|---|---|---|
| ✅ Passed | secrets-detection |
- |
✅ sast-scan
| Status | Policy | Messages |
|---|---|---|
| ✅ Passed | owasp-top10-2025 |
- |
| ✅ Passed | sast |
- |
| ✅ Passed | cwe-top25 |
- |
| ✅ Passed | cwe-top26-40-cusp |
- |
PR info
| Status | Policy | Messages |
|---|---|---|
| ✅ Passed | pr-description-required |
- |
| ✅ Passed | pr-user-story-linked |
- |
⏭️ 3 scans not applied
| Scan | Reason |
|---|---|
vulnerability-scan |
ran, but its output is not attested yet |
github-actions-scan |
no workflow files changed |
iac-scan |
no IaC files changed |
Powered by Chainloop and Chainloop Trace
There was a problem hiding this comment.
No issues found across 4 files
Heads up: you’re close to your included review allowance. Set a flex budget so reviews don’t pause.
Re-trigger cubic
…s timestamp `wf run describe` aborted with "bundle verification failed" whenever the control plane served no timestamp authority for a bundle carrying a timestamp, hiding the run entirely. The gap is in the trust material the control plane publishes, not in the attestation, so report the attestation as unverified and carry on. Failures attributable to the attestation still abort. Assisted-by: Claude Code Signed-off-by: Jose I. Paris <jiparis@chainloop.dev> Chainloop-Trace-Sessions: 38ffe2d2-dec5-4c9f-9a68-abf837907af8
…erify its timestamp" This reverts commit b0f0b0a. Failing the describe when the control plane cannot verify a timestamp is the intended behaviour on the read path. Assisted-by: Claude Code Signed-off-by: Jose I. Paris <jiparis@chainloop.dev> Chainloop-Trace-Sessions: 38ffe2d2-dec5-4c9f-9a68-abf837907af8
This PR prevents attestation push from failing when a TSA rotates their signing certificate. Instead of failing, a warning in sent to logs. Pushed attestations remain un-verifiable until CA certificate chain is rotated in the control plane config.
Verifier
verifyTimestampnow identifies the response's PKCS#7 signer (issuer + serial) before delegating to the underlying verifier, and only considers the configured authorities that actually signed it. When none did, it returns the newErrTSASignerNotTrusted, naming the authority tried and the leaf it expected, so the chain to rotate is identifiable from the message. A newIsTrustConfigErrorclassifies that andErrNoTSARootsConfiguredas verifier-side. Failures attributable to the attestation — bad signature, a timestamp that does not cover it, validity-window violations — are unaffected and keep their existing sentinels.Control plane
VerificationResultcarriesTrustConfigFault.SaveAttestationkeeps rejecting attestation-fault failures, but on a trust-config fault it logs a warning and persists the bundle. Verification is still reported as failed with its reason on read, and self-heals on the next read once the pinned chain is rotated.The read path is unchanged: a run whose timestamp cannot be verified is still reported as failed verification.
No proto or API change.
Assisted-by: Claude Code