Skip to content

fix(skill): bind x402 payments to approved terms and harden helpers - #56

Open
yashovardhan wants to merge 2 commits into
mainfrom
claude/greptile-fixes
Open

yashovardhan wants to merge 2 commits into
mainfrom
claude/greptile-fixes

Conversation

@yashovardhan

@yashovardhan yashovardhan commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

Motivation and Context

Greptile reviewed the vendored copy of this skill in davila7/claude-code-templates#1032, gave it a confidence score of 0/5, and flagged four P1 and two P2 issues. All six are real defects in this repo's skill, so this PR fixes them here. The biggest one is that pay --confirm could sign terms other than the ones the user approved.

Jira Link

N/A

Description

Behavior change: pay and mcp-sign now require --approved <approvalId>.

Finding Fix
P1: payment approval can go stale. pay fetched a fresh 402 and signed it without comparing it to what the user approved inspect/mcp-inspect print an approvalId for each option. It is a SHA-256 fingerprint of the scheme, network, asset, payTo, amount, and transfer method. pay/mcp-sign require --approved and refuse to sign if the offer they're about to sign has a different fingerprint. The fresh fetch stays, so the short payment window is still respected.
P1: MFA notices break JSON parsing. The first { to last } slice merged an AWAITING_MFA NDJSON line with the result mm output is decoded one object at a time with raw_decode. _notice objects are skipped, and the result object is returned. If the output holds only notices, the last one is returned so the approval state is surfaced.
P1: amount_to_hex.py silently truncated extra decimal places The script rejects amounts it can't represent exactly, instead of dropping digits. It also rejects negative, non-numeric, and non-finite amounts, and decimals outside 0 to 255. It computes at high precision, so large amounts are never rounded.
P1: password examples put secrets in command arguments auth.md shows mm wallet password set/change/remove in their prompting form, and the flag rows say never to pass the value inline. I also found the same problem in the BYOK export MM_MNEMONIC="…"/MM_PASSWORD examples in auth.md and onboarding.md, which would put a seed phrase in shell history. Those now use read -rs, which works in bash and zsh.
P2: unsupported CAIP-2 chains looked payable eip155:<id> must appear in mm chains list, the same rule as for named networks.
P2: a missing receipt still reported settled A 200 with no decodable receipt reports "status": "paid_unverified", with a note not to pay again and to check transaction history.

A second commit adds the Agent Skills compatibility field to SKILL.md. It declares that the skill needs the mm CLI and Python 3, and which parts use the network.

SKILL.md, references/x402.md, workflows/x402-pay.md, workflows/x402-mcp.md, and references/transaction.md document the new flag, the mismatch error, and the new status. The skill is bumped to 7.7.2, with a CHANGELOG entry.

How has this been tested?

I ran end-to-end tests against a local x402 server on loopback. The script allows plain HTTP only on loopback. For mm, I used a stub that prints a Node warning before chains list, and an AWAITING_MFA NDJSON notice before the sign-typed-data result.

Case Result
pay --confirm without --approved Refused, nothing signed
Approved offer unchanged, with an MFA notice before the signature settled with the transaction hash
Server raises the amount after inspect Refused: "terms differ from the approved ones"
Server changes payTo after inspect Refused
200 without a receipt paid_unverified, transaction: null, with a note
Offer on unsupported eip155:999999 chainId: null, not eligible, pay refuses
mcp-sign without, with matching, and with changed --approved Refused, then signed, then refused

amount_to_hex.py gives the same output as before for the documented examples (1.5 18, 100 6, 0.001 8). It errors on 0.1234567 6, -1 6, abc 6, inf 6, 1 -1, and 1 x. 123456789012345678901234.5 18 matches exact integer arithmetic.

Also run:

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

pay/mcp-sign calls without --approved now fail closed. The skill's docs and workflows are updated in the same PR, so agents that follow the skill aren't affected.

Checklist

  • My code follows the code style of this project. (run lint)
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

The repo has no test suite, so the harness above was run by hand.

🤖 Generated with Claude Code

Address the review of davila7/claude-code-templates#1032:

- x402: inspect/mcp-inspect print an approvalId per option. pay and
  mcp-sign require --approved and refuse to sign if the fresh offer's
  scheme, network, asset, payTo, or amount differ from the approved ones.
- x402: report "paid_unverified" instead of "settled" when a 200 has
  no decodable receipt.
- x402: require CAIP-2 chains to appear in `mm chains list`.
- x402: parse mm JSON output object by object and skip `_notice` lines,
  so an AWAITING_MFA notice before the result no longer crashes signing.
- amount_to_hex.py: reject excess precision instead of truncating, plus
  negative, non-numeric, and non-finite input.
- Docs: stop showing passwords or mnemonics inline. Use the prompting
  commands and `read -rs` for MM_MNEMONIC and MM_PASSWORD.

Bump the skill to 7.7.2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@yashovardhan
yashovardhan requested review from a team as code owners September 30, 2026 18:43
yashovardhan added a commit to yashovardhan/claude-code-templates that referenced this pull request Sep 30, 2026
Pull in MetaMask/agent-skills#56, which addresses the review on this
PR: x402 payments are bound to the approved terms with --approved,
receipt-less 200s report paid_unverified, CAIP-2 chains are checked
against mm, MFA notices no longer break JSON parsing, amount_to_hex.py
rejects excess precision, and secret examples use prompts or read -rs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add the Agent Skills compatibility field: the skill needs the mm CLI and
Python 3, mm talks to MetaMask services and chains, x402_pay.py only
contacts the URL or MCP challenge the user asks to pay, and
amount_to_hex.py is offline. Skill scanners such as awesome-llm-apps'
skill_scanner treat undeclared network use as a warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant