Skip to content

[Bug]: Merchant sample verifies checkout using embedded JWT without independent checkout-hash context #331

Description

@mh-yu

What happened?

Description

AP2 closed Checkout Mandates contain a merchant-signed checkout_jwt and a checkout_hash that binds the mandate to that checkout.

The Python SDK's CheckoutMandateChain.verify() accepts expected_checkout_hash as optional. If it is omitted, the SDK evaluates checkout constraints against the supplied checkout_jwt but does not check the closed mandate's checkout_hash against an independently expected checkout hash.

The Python Merchant MCP sample passes checkout_jwt=chain.closed_mandate.checkout_jwt but does not pass expected_checkout_hash. It then decodes that embedded JWT payload and continues checkout processing.

Impact

A merchant verifier can validate checkout constraints against checkout data carried inside the closed mandate, rather than binding the mandate to an independently created merchant checkout session.

This weakens the protection against manipulated or unrelated checkout data being used to complete an order.

Steps to Reproduce

  1. Review code/sdk/schemas/ap2/checkout_mandate.json:20-28. checkout_jwt is the merchant-signed checkout payload, and checkout_hash uniquely identifies that JWT.

  2. Review code/sdk/python/ap2/sdk/checkout_mandate_chain.py:44-100. expected_checkout_hash is optional and checkout_hash is checked only when that value is provided.

  3. Review code/sdk/python/ap2/sdk/checkout_mandate_chain.py:112-125. The SDK extracts checkout data by decoding the JWT payload.

  4. Review code/samples/python/src/roles/merchant_agent_mcp/server.py:872-883. The Merchant sample verifies the checkout mandate using checkout_jwt from the closed mandate, without passing expected_checkout_hash.

  5. Review code/samples/python/src/roles/merchant_agent_mcp/server.py:900-944. The sample decodes the embedded checkout JWT payload and continues checkout processing from that data.

Relevant log output

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions