fix: SKR debug gate per attestation type; ComputeID receipt claims from the signed payload - #243
Merged
Merged
Conversation
The debug gate and base conditions were derived from required_hw_platform[0]. With [intel-tdx, amd-sev-snp] no branch had a debuggable gate; with [amd-sev-snp, intel-tdx] the tdxvm branches got x-ms-sevsnpvm-is-debuggable and x-ms-sevsnpvm-hostdata, which MAA never issues on a tdxvm token, so they never matched. Each branch now gets its own gate: x-ms-sevsnpvm-is-debuggable on sevsnpvm, tdx_td_attributes_debug on tdxvm (MAA TDX EAT profile and the tdxvm sample token on the MAA token examples page). A TEE-specific measurement claim is refused for the other TEE's branch; a mapping from attestation type to claim is accepted instead. Documented TDX measurement claims are added with their widths, so the width check refuses them for a 64-hex WCM measurement. evidence_from_maa_claims checks the debug claim of the token's own type. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… CA-signed payload offline-verifier.js checked the CA signature over receipt_payload but never parsed it. Freshness used the unsigned receipt.expires_at, revocation the unsigned bundle.status, and the passport keys are self-embedded, so an edited expires_at, or an attacker bundle with its own keys and another passport's genuine receipt, passed with overall_pass true. passport_id, status, issued_at and expires_at now come only from the verified receipt_payload and must equal the bundle and the unsigned receipt copies; the signed key_id must name the supplied CA key. The current receipt signs no passport key, so issuer_trusted and overall_pass are false for every current ComputeID bundle, with the reason in verification_reasons.receipt_binding. Output field names are unchanged; receipt_binding, credential_fresh reasons and receipt_signed_fields are added. verify() takes an optional now, the CLI --now, and node:test tests cover the edited expiry, the attacker bundle and the fixture. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes GHSA-h8c4-mjgc-w25m and GHSA-8vvv-28gh-rr4v.
build_release_policyinintegrations/wcm-azure-skrwrites an Azure Key Vault secure key release policy from a Weight Custody Manifest. Withrequire_not_debuggable, the debuggable check was added only when the first entry ofrequired_hw_platformwasamd-sev-snp(wcm_azure_skr.py:238).["intel-tdx", "amd-sev-snp"]: neither thetdxvmnor thesevsnpvmbranch carries a debug condition, so Key Vault releases the key to a debug guest.["amd-sev-snp", "intel-tdx"]: thetdxvmbranches get SNP-only claims (x-ms-sevsnpvm-is-debuggable,x-ms-sevsnpvm-hostdata), never match, and fail closed.A debug guest lets the host read guest memory, so the released key is exposed to the host.
Fix: each
anyOfbranch is built from its own attestation type.sevsnpvmbranches requirex-ms-sevsnpvm-is-debuggable == false,tdxvmbranches requiretdx_td_attributes_debug == false(Microsoft Learn, TDX EAT profile). A TEE-specific measurement claim on the other TEE's branch is refused, and the TDX measurement claims are refused for a 64-hex WCM digest.evidence_from_maa_claimschecks the debug claim for the token's own type.Affected:
integrations/wcm-azure-skrfrom cf9c1c1 (2026-08-27) to 59c9019. Regenerate any release policy built from a manifest that listsintel-tdxfirst. CWE-693.offline-verifier.jsinintegrations/computeid-agentpassport-tracereturnsoverall_pass=truefor a bundle nobody issued. It verifies the CA signature oververification_receipt.receipt_payloadbut never parses that payload.verification_receipt.expires_at.status.Reproduction on 59c9019:
evidence/opaque-diligence-demo.jsongivesoverall_pass=false(expired). Changing onlyverification_receipt.expires_atto 2099 givesoverall_pass=true.passport_id=attacker-passport, capabilities["admin"]and a CA receipt copied from another passport givesoverall_pass=truewith every outcome true.Fix:
passport_id,status,issued_at,expires_atandkey_idare read only from the CA-signedreceipt_payloadand must equal the bundle and the unsigned copies. The signedkey_idmust name the supplied CA key. Passport keys count as trusted only when the signed payload carriespublic_keyandpq_public_keyequal to the bundle's.Current ComputeID receipts do not sign the passport keys, so every bundle now reports
issuer_trusted=falseuntil the receipt format adds them. That is intended.Affected:
integrations/computeid-agentpassport-tracefrom 2d8144e (2026-09-10) to 59c9019. CWE-345.Generated with Claude Code