T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/wake-cli.py:94
- Finding
- Automatic x402 Payment Signing Without Local Transaction Constraints<![CDATA[ ## Vulnerability Details **File Location**: `scripts/wake-cli.py:94-103`, `scripts/wake-cli.py:152-167`, and `scripts/wake-cli.py:201-205` **Vulnerability Type**: Unrestricted automatic signing of server-proposed payment transactions **Risk Level**: High ### Vulnerable Code ```python async def cmd_verify(args: argparse.Namespace) -> int: """Run the verify flow: POST /verify, then poll until resolved.""" signer = load_signer(args.keypair) log(f"Signer address: {signer.address}") x402 = x402Client() register_exact_svm_client(x402, signer) async with x402HttpxClient(x402, base_url=args.base_url) as client: # Step 1: POST /api/v1/verify log(f"POST {args.base_url}/api/v1/verify") resp = await client.post( "/api/v1/verify", json={"phone": args.phone}, ) ``` ```python async def cmd_schedule(args: argparse.Namespace) -> int: """Run the schedule flow: POST /schedule.""" signer = load_signer(args.keypair) log(f"Signer address: {signer.address}") x402 = x402Client() register_exact_svm_client(x402, signer) body = { "phone": args.phone, "times": args.time, "voice": args.voice, } if args.hints: body["hints"] = args.hints async with x402HttpxClient(x402, base_url=args.base_url) as client: log(f"POST {args.base_url}/api/v1/schedule") resp = await client.post("/api/v1/schedule", json=body) ``` ```python parser.add_argument( "--base-url", default="https://wake.meup.ai", help="Base URL for the Wakeup API (default: https://wake.meup.ai)", ) ``` ### Technical Analysis The client registers a funded Solana keypair with the x402 client and then permits the HTTP client to handle payment negotiation automatically. No application-level control verifies the payment recipient, USDC mint, Solana network, transaction amount, or cumulative expenditure before a signature is produced. The documentatio ...[truncated 1879 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Enforce a strict allowlist of API origins. In production mode, require exactly `https://wake.meup.ai` and reject user-info components, non-HTTPS schemes, unexpected ports, redirects to different origins, and ambiguous hostnames. 2. Before signing, decode and validate every payment proposal: - Require the intended Solana network. - Require the expected USDC mint. - Require an allowlisted recipient account. - Enforce a maximum of $0.50 USDC for verification. - Enforce a maximum of $2.00 USDC per scheduled call. - Verify that the total charge matches the number of requested calls. 3. Add per-transaction, per-run, and cumulative spending limits. 4. Display the recipient, mint, network, amount, and operation to the user and require explicit confirmation before signing, particularly when a custom endpoint is used. 5. Reject transactions containing additional transfers, instructions, account authorities, or permissions not required for the documented payment. 6. Prefer a dedicated low-balance wallet with no unrelated assets and document this as a required security boundary rather than only a recommendation. 7. Add tests using malicious x402 responses to verify rejection of excessive amounts, substituted recipients, incorrect mints, incorrect networks, and unexpected instructions. ]]>
