microsoft / microsoft/agent-governance-toolkit

verifiable-compliance-receipts: does the signer key need to be independent of the acting agent?

Open
#3,805 31 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

needs-review:HIGH
Dominant language
Python
Stars
6.3k
Forks
1.1k
Avg merge
5d 11h
Merged PRs (30d)
142

Description

Read `docs/proposals/verifiable-compliance-receipts.md` (the AGT/Nobulex/AgentLedger interop format also referenced in LangChain RFC #35691, AutoGen #7609, CrewAI #5541) and the reference implementation in `agent-governance-python/agentmesh-integrations/mcp-receipt-governed/mcp_receipt_governed/receipt.py`, checked both against each other before opening this.

**The gap:** the proposal's own text says "Both signatures use the same Ed25519 key (signerKeyId), so a verifier confirms they came from the same agent process." The reference `sign_receipt()` takes an arbitrary `private_key_hex` — architecturally it's agnostic to who holds that key — but nothing in the proposal, the schema, or the example specifies that the signer must be a party structurally independent of the agent whose action is being evaluated. `verify_receipt_chain()`'s `trusted_keys` allowlist checks the signer is *one of a declared set*, not that the declared set excludes the agent's own operating key.

**Why this matters concretely, not hypothetically:** every stated verification check (signature validity, chain integrity, policy binding) can pass in full for a receipt chain that is entirely self-signed — the agent's own process evaluates its own policy, signs the "authorization," executes, signs the "result." That's real tamper-evidence (nobody can silently edit the chain after the fact) but it isn't independent verification — it proves internal consistency, not that anyone other than the acting agent ever looked at the decision. For EU AI Act Art. 12 / SOC 2 use (the proposal's own stated targets), an auditor reading "signature valid, chain intact, policy hash matches" could reasonably read that as "this was checked," when the honest claim is closer to "this agent process didn't (visibly) lie to itself."

We ran into the identical distinction on a related thread (crewAI#4877, `expect_intended_verifier`) — the fix there closes what's now called assurance-level (1), *intent-bound* (the record declares which verifier was intended), but not level (2), *presenter-bound* (proof the actual signer is who it claims, independent of the party under evaluation). This proposal is at level (1) today: `covenantHash`/`authorizationSignature` prove a policy *was declared* to have been evaluated, not that the evaluator was anyone other than the subject.

**Concrete question, not an assertion about the design being wrong:** is signer-independence intentionally left as a deployment choice (some operators want self-attestation, some want a real external mediator, and the schema shouldn't force one), or is it worth a schema-level marker — e.g. a required field distinguishing `self_attested` vs `external_signer`, or a MUST that `signerKeyId` differ from any key the acting agent's own runtime can access — so a verifier doesn't have to go find out of-band which case they're looking at? Checked LangChain RFC #35691 for prior discussion of this specific point — it isn't there (that thread's AgentMint receipts are also silent on who holds the key), so this looks like a genuinely open question across the whole interop cluster, not just here.

Happy to share our own worked version of this distinction if useful — `/review`'s signed verdict is issued and signed with a key the party under evaluation never has access to, specifically so `/verify-proof` doesn't have to trust the presenter, only the published key. Not proposing you adopt that mechanism, just flagging that the "who holds the key" question is the one place self-signed and independently-witnessed schemes actually diverge, and this proposal doesn't yet say which one it is.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read docs/proposals/verifiable-compliance-receipts.md alongside agent-governance-python/agentmesh-integrations/mcp-receipt-governed/mcp_receipt_governed/receipt.py. Start by tracing signerKeyId, sign_receipt(), verify_receipt_chain(), and trusted_keys to compare what independence the proposal and implementation establish. Done should be an explicit design decision about self-attestation versus external signing, reflected in the proposal, schema, or examples if a distinction is required.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cryptography, documentation, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.