Skip to content

feat: add bilateral receipt signing (pre-execution + post-execution)#1333

Merged
imran-siddique merged 2 commits intomicrosoft:mainfrom
arian-gogani:feat/bilateral-receipts
Apr 22, 2026
Merged

feat: add bilateral receipt signing (pre-execution + post-execution)#1333
imran-siddique merged 2 commits intomicrosoft:mainfrom
arian-gogani:feat/bilateral-receipts

Conversation

@arian-gogani
Copy link
Copy Markdown
Contributor

Extends receipts.py with bilateral receipt support per the design doc in #1302.

Three new functions:

  • sign_authorization() — signs pre-execution commitment (proves policy evaluated before action ran)
  • seal_result() — seals post-execution outcome (binds actual result to the authorization)
  • verify_bilateral_receipt() — verifies both signatures, falls back to verify_receipt() for standard envelopes

Backward compatible. Existing single-signature receipts verify unchanged. Bilateral fields are additive.

The result signature covers the binding of authorization_hash and result_hash together, proving:

  1. The authorization existed before execution
  2. The result was produced after execution
  3. Both were signed by the same key

11 tests pass locally covering: creation, chain linkage, sealing, tamper detection (payload and result), wrong key rejection, and deny receipts.

Relates to #1249.

@github-actions github-actions Bot added size/L Large PR (< 500 lines) documentation Improvements or additions to documentation labels Apr 22, 2026
@github-actions
Copy link
Copy Markdown

🤖 AI Agent: security-scanner — Security Review of `feat: add bilateral receipt signing (pre-execution + post-execution)`

Security Review of feat: add bilateral receipt signing (pre-execution + post-execution)

This PR introduces bilateral receipt signing for compliance verification, which is a critical feature for ensuring the integrity and verifiability of agent actions. Below is the security analysis of the changes:


1. Prompt Injection Defense Bypass

Assessment: 🔵 LOW
The changes in this PR do not directly handle user input or natural language processing, so prompt injection is not applicable here. The focus is on cryptographic signing and verification of receipts.


2. Policy Engine Circumvention

Assessment: 🟡 MEDIUM
Issue: The sign_authorization() function relies on the payload argument to generate the authorization_hash. If the payload is not properly validated or sanitized before signing, an attacker could potentially inject malicious data into the payload, which would then be signed and treated as valid. This could allow circumvention of policy enforcement if the payload is manipulated to misrepresent the policy or action details.
Fix: Add strict validation for the payload to ensure it adheres to the expected schema and does not contain unexpected or malicious fields. Consider using a JSON schema validator to enforce the structure and content of the payload.


3. Trust Chain Weaknesses

Assessment: 🟠 HIGH
Issue: The verify_bilateral_receipt() function does not validate the signerKeyId field in the signature section of the envelope. This could allow an attacker to use a compromised or unauthorized key to sign receipts, bypassing the trust chain.
Fix: Add a check to ensure that the signerKeyId in the receipt matches the expected key ID for the agent. This can be done by maintaining a trusted key registry or using a secure key management system to verify the key's authenticity.


4. Credential Exposure

Assessment: 🔵 LOW
No sensitive credentials or secrets are logged or exposed in the changes. The private key used for signing is passed as a Signer object, which is assumed to be securely managed outside the scope of this PR.


5. Sandbox Escape

Assessment: 🔵 LOW
The changes do not introduce any new code that interacts with the operating system or external processes, so sandbox escape is not a concern here.


6. Deserialization Attacks

Assessment: 🟡 MEDIUM
Issue: The _canonicalize() function is used to serialize the payload and result data for hashing and signing. If _canonicalize() relies on a vulnerable or improperly configured JSON library, it could be exploited for deserialization attacks.
Fix: Ensure that _canonicalize() uses a secure JSON serialization library that does not allow arbitrary code execution or unsafe object creation. If _canonicalize() is a custom implementation, review it for potential vulnerabilities.


7. Race Conditions

Assessment: 🟡 MEDIUM
Issue: The seal_result() function assumes that the authorization_hash in the envelope has not been tampered with between the sign_authorization() and seal_result() calls. If the envelope is modified in a concurrent environment, it could lead to a mismatch between the authorization and result signatures, potentially invalidating the receipt.
Fix: Add a mechanism to ensure the integrity of the envelope between the sign_authorization() and seal_result() steps. This could involve locking the envelope or using a secure storage mechanism to prevent unauthorized modifications.


8. Supply Chain Risks

Assessment: 🟡 MEDIUM
Issue: The PR does not explicitly mention any new dependencies, but it uses cryptographic functions (e.g., Ed25519PublicKey, hashlib, _b64url, _canonicalize). If these are third-party libraries or custom implementations, they should be reviewed for security vulnerabilities.
Fix: Ensure that all cryptographic libraries are up-to-date and have no known vulnerabilities. If _b64url and _canonicalize are custom functions, review their implementations for security issues.


Additional Observations:

  1. Error Handling: The verify_bilateral_receipt() function does not log or handle exceptions in a way that provides meaningful feedback for debugging. This could make it harder to identify and fix issues during verification.
    Recommendation: Add detailed error messages and logging for failed signature verifications to aid in debugging without exposing sensitive information.

  2. Replay Attacks: There is no mention of mechanisms to prevent replay attacks, where a valid receipt could be reused maliciously.
    Recommendation: Consider adding a nonce or timestamp validation to ensure that each receipt is unique and cannot be reused.

  3. Documentation: The proposal document is well-written and provides a clear explanation of the feature. However, it would be helpful to include explicit security considerations and threat models to guide future development and audits.


Summary of Findings:

Category Severity Issue Fix
Prompt Injection Defense Bypass 🔵 LOW Not applicable. None
Policy Engine Circumvention 🟡 MEDIUM Lack of strict validation for payload. Add schema validation for payload.
Trust Chain Weaknesses 🟠 HIGH signerKeyId is not validated. Validate signerKeyId against a trusted key registry or KMS.
Credential Exposure 🔵 LOW No credentials exposed. None
Sandbox Escape 🔵 LOW Not applicable. None
Deserialization Attacks 🟡 MEDIUM Potential risks in _canonicalize() implementation. Ensure secure JSON serialization and review _canonicalize() for vulnerabilities.
Race Conditions 🟡 MEDIUM Potential tampering of authorization_hash between signing and sealing. Use locking or secure storage to protect the envelope between steps.
Supply Chain Risks 🟡 MEDIUM Cryptographic libraries and custom functions not explicitly reviewed. Ensure all libraries are up-to-date and review custom functions for security vulnerabilities.
Replay Attacks 🟡 MEDIUM No mechanism to prevent replay attacks. Add nonce or timestamp validation to ensure receipt uniqueness.

Final Recommendation:

The PR introduces a critical feature for compliance and verifiability, but there are several medium and high-severity issues that need to be addressed before merging. Specifically:

  1. Add schema validation for payload in sign_authorization().
  2. Validate signerKeyId against a trusted key registry or KMS.
  3. Review _canonicalize() and _b64url for security vulnerabilities.
  4. Implement mechanisms to prevent replay attacks.
  5. Add error handling and logging for failed verifications.

Once these issues are resolved, the PR can be considered for merging.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI Agent: code-reviewer

Review Summary

This PR introduces a significant enhancement to the receipts.py module by adding support for bilateral receipt signing, which includes pre-execution authorization (sign_authorization) and post-execution result sealing (seal_result). Additionally, it provides a verification mechanism (verify_bilateral_receipt) to validate both the authorization and result signatures. The implementation appears to be backward compatible, as it does not modify the existing single-signature receipt verification logic.

The changes are well-documented, with a detailed proposal included in the PR. The new functionality is critical for ensuring compliance with regulations like the EU AI Act and SOC 2, as it provides independently verifiable compliance evidence.


🔴 CRITICAL

  1. Replay Attack Vulnerability in Authorization Signature:

    • The sign_authorization function does not include a unique nonce or identifier in the payload before signing. This could allow an attacker to reuse a valid authorization signature in a different context, leading to a potential security bypass.
    • Recommendation: Include a unique, cryptographically secure nonce in the payload before signing. This ensures that each authorization signature is unique and cannot be reused in a replay attack.
  2. Lack of Expiry for Authorization Receipts:

    • The sign_authorization function does not enforce an expiration time for the authorization. This could allow an attacker to use an old authorization receipt to execute actions long after it was issued.
    • Recommendation: Add an expires_at field to the authorization payload and validate it during the verify_bilateral_receipt process.
  3. Insufficient Validation of Input Data:

    • The sign_authorization, seal_result, and verify_bilateral_receipt functions do not validate the structure or types of the input data (e.g., payload, result_data, envelope). This could lead to unexpected behavior or security vulnerabilities if malformed data is passed.
    • Recommendation: Use Pydantic models to validate the input data for these functions. This will ensure type safety and prevent potential issues from malformed inputs.
  4. Canonicalization Process Not Validated:

    • The _canonicalize function is used to generate canonical JSON for signing, but there is no validation to ensure that the canonicalization process is consistent and secure.
    • Recommendation: Add tests to verify that the _canonicalize function produces consistent and correct output for various edge cases, including nested JSON structures, special characters, and large payloads.

🟡 WARNING

  1. Potential Breaking Change in verify_bilateral_receipt:

    • The verify_bilateral_receipt function falls back to verify_receipt() for non-bilateral envelopes. While this ensures backward compatibility, any changes to the verify_receipt() function in the future could inadvertently affect the behavior of verify_bilateral_receipt.
    • Recommendation: Clearly document this dependency in the code and consider adding tests to ensure that changes to verify_receipt() do not break verify_bilateral_receipt.
  2. Backward Compatibility Assumptions:

    • The PR assumes that the addition of new fields (e.g., bilateral, result) to the receipt structure will not break existing consumers of the receipts.py module. While this is likely true, it should be explicitly tested.
    • Recommendation: Add tests to ensure that existing functionality (e.g., single-signature receipt verification) continues to work as expected with the new fields present.

💡 SUGGESTIONS

  1. Improve Error Messages:

    • The error messages in seal_result (e.g., "Cannot seal a non-bilateral receipt") could be more descriptive to aid debugging.
    • Recommendation: Include additional context in error messages, such as the current state of the envelope or the expected state.
  2. Thread Safety:

    • The sign_authorization and seal_result functions rely on the Signer object, which includes a private_key. If the Signer object is shared across threads, this could lead to race conditions or other concurrency issues.
    • Recommendation: Document whether the Signer object is thread-safe. If it is not, consider adding locks or requiring that each thread use its own Signer instance.
  3. Extend Test Coverage:

    • While the PR mentions that 11 tests pass locally, it is unclear whether edge cases (e.g., malformed envelopes, invalid signatures, missing fields) are thoroughly tested.
    • Recommendation: Add tests for edge cases, including:
      • Missing or malformed authorization and result sections.
      • Invalid or tampered signatures.
      • Receipts with unexpected or additional fields.
  4. Performance Considerations:

    • The verify_bilateral_receipt function performs multiple cryptographic operations (e.g., signature verification, hash computation). For high-throughput scenarios, this could become a bottleneck.
    • Recommendation: Benchmark the performance of the verification process and consider optimizations if necessary. For example, caching intermediate results or parallelizing verification steps.
  5. Documentation Improvements:

    • The proposal document is comprehensive, but the code itself could benefit from more inline comments explaining the rationale behind key design decisions (e.g., why certain fields are included in the receipt).
    • Recommendation: Add comments to the code to explain the purpose of each field in the receipt and the reasoning behind the design choices.

Summary of Actionable Feedback

🔴 CRITICAL

  1. Add a cryptographically secure nonce to the payload in sign_authorization to prevent replay attacks.
  2. Include an expires_at field in the authorization payload and validate it during verification.
  3. Use Pydantic models to validate input data for sign_authorization, seal_result, and verify_bilateral_receipt.
  4. Add tests to validate the _canonicalize function for edge cases.

🟡 WARNING

  1. Document the dependency of verify_bilateral_receipt on verify_receipt() and add tests to ensure future changes do not break compatibility.
  2. Add tests to confirm that existing single-signature receipt functionality remains unaffected by the new fields.

💡 SUGGESTION

  1. Improve error messages in seal_result for better debugging.
  2. Document or ensure thread safety of the Signer object.
  3. Extend test coverage to include edge cases and malformed inputs.
  4. Benchmark and optimize the performance of verify_bilateral_receipt if necessary.
  5. Add inline comments to explain the rationale behind key design decisions in the code.

Let me know if you need further clarification or assistance!

@arian-gogani
Copy link
Copy Markdown
Contributor Author

@microsoft-github-policy-service agree

@imran-siddique imran-siddique merged commit 1bb9a9b into microsoft:main Apr 22, 2026
10 of 11 checks passed
kenneives added a commit to agentgraph-co/agentgraph that referenced this pull request Apr 29, 2026
…rifier

Two harness updates from Apr 28-29 GitHub activity:

- Nobulex (@arian-gogani) merged @nobulex/crypto into Microsoft Agent
  Governance Toolkit (microsoft/agent-governance-toolkit#1333, OpenSSF
  passing badge). Material elevation — bilateral-receipt primitive is
  now Microsoft-shipped, not vendor-isolated.

- msaleme (Michael Saleme) volunteered to add their x402 conformance
  harness as 6th independent verifier (A2A #1672 comment 2026-04-29).
  Targeting v4.5 with claim_type-tagged output. The 41 existing x402
  tests map onto continuity-layer evidence_basis.evidence_type.
  payment_execution lane.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
arian-gogani added a commit to arian-gogani/agent-governance-toolkit that referenced this pull request May 2, 2026
Creates ADOPTERS.md as referenced in the README. Nobulex's bilateral receipt primitive was merged into AGT via PRs microsoft#1302 and microsoft#1333 (216 LOC, 11 tests). 8 independent implementations have byte-match validated the JCS/RFC 8785 canonicalization substrate. AAIF Growth-stage proposal filed with TC sponsorship from the CTEF maintainer.
imran-siddique pushed a commit to imran-siddique/agent-governance-toolkit that referenced this pull request May 4, 2026
…icrosoft#1333)

* Create verifiable-compliance-receipts.md

* add bilateral receipt signing (pre-execution + post-execution)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/L Large PR (< 500 lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants