T09 · Insecure Skill Coding Practices
- Location
skillz-cli.ts:64- Finding
Unrestricted Remote Endpoints Can Trigger Wallet-Backed Payment Requests
- Content
View full analysis
Vulnerability Details
File Location:
skillz-cli.ts:64-79andskillz-cli.ts:99-119
Vulnerability Type: Unvalidated payment-enabled remote endpoint and potential server-side request forgery
Risk Level: HighVulnerable Code
typescript const skill: Skill = await skillRes.json(); if (skill.isActive === false) { console.error(`Skill "${slug}" is not active`); process.exit(1); } console.error(`Calling ${skill.name} @ ${skill.endpoint} ($${skill.price} USDC)`); // Set up payment client const account = privateKeyToAccount(PRIVATE_KEY); const client = new x402Client(); registerExactEvmScheme(client, { signer: account }); const paymentFetch = wrapFetchWithPayment(fetch, client); try { const response = await paymentFetch(skill.endpoint, {typescript async function direct(url: string, input: string) { if (!PRIVATE_KEY) { console.error('Error: SKILLZ_PRIVATE_KEY not set'); process.exit(1); } console.error(`Calling endpoint: ${url}`); // Set up payment client const account = privateKeyToAccount(PRIVATE_KEY); const client = new x402Client(); registerExactEvmScheme(client, { signer: account }); const paymentFetch = wrapFetchWithPayment(fetch, client); try { const response = await paymentFetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: input, });Technical Analysis
The
callcommand obtainsskill.endpointfrom the remotely configured marketplace API and passes it directly to a payment-enabled fetch operation. Thedirectcommand similarly accepts an arbitrary URL from the command line.Neither path validates:
- The URL protocol or destination hostname.
- Whether the resolved address belongs to a loopback, private, link-local, or cloud metadata range.
- The payment recipient, chain, token, or requested amount.
- Whether the x402 payment challenge matches the catalog's displayed
skill.price. - A per-call or cumulative spending li ...[truncated 2072 chars]
- Remediation
View remediation
Remediation Suggestions
- Require
https:for all remotely accessed payment endpoints and reject URLs containing embedded credentials. - Introduce an explicit allowlist of trusted marketplace and skill endpoint hostnames.
- Resolve destination hostnames before connecting and reject loopback, private, link-local, multicast, reserved, and cloud metadata address ranges. Repeat this validation after redirects and mitigate DNS rebinding.
- Disable automatic redirects or validate every redirect destination before following it.
- For x402 challenges, enforce the expected network, asset, recipient, and maximum amount before authorizing a signature.
- Compare the challenge amount against the catalog price and reject any mismatch.
- Add configurable per-transaction and cumulative spending limits.
- Display the final payment recipient, asset, network, and amount and require explicit user confirmation before payment.
- Restrict or remove the
directcommand where arbitrary endpoint access is not a strict functional requirement. - Use a dedicated wallet with minimal funds and narrowly scoped operational limits.
- Require
