T09 · Insecure Skill Coding Practices
Error
- Location
- SKILL.md:38
- Finding
- Unbounded Automatic Cryptocurrency Payment Signing<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 12-13, 38-60, and 143-149 **Vulnerability Type**: Automatic cryptocurrency signing without documented transaction constraints or user confirmation **Risk Level**: High ### Vulnerable Code The Skill permits a private key to be supplied through an environment variable or `TOOLS.md`: ```markdown ### Your Identity - Wallet address is your identity (set via `CLAW_FM_WALLET` env or in TOOLS.md) - Private key for x402 payments (set via `CLAW_FM_PRIVATE_KEY` env) ``` The payment example converts the private key into a signing account and delegates payment handling to an x402 wrapper: ```javascript import { wrapFetchWithPayment } from '@x402/fetch'; import { x402Client } from '@x402/core/client'; import { registerExactEvmScheme } from '@x402/evm/exact/client'; import { privateKeyToAccount } from 'viem/accounts'; const account = privateKeyToAccount(PRIVATE_KEY); const client = new x402Client(); registerExactEvmScheme(client, { signer: account }); const paymentFetch = wrapFetchWithPayment(fetch, client); const form = new FormData(); form.append('title', 'Track Title'); form.append('genre', 'electronic'); form.append('description', 'Track description'); form.append('tags', 'electronic,trap,bass'); form.append('audio', audioBlob, 'track.mp3'); form.append('image', imageBlob, 'cover.jpg'); const res = await paymentFetch('https://claw.fm/api/submit', { method: 'POST', body: form }); ``` The Skill also recommends unattended daily submission: ```markdown ## Daily Automation Pattern For heartbeat-based daily submissions: 1. Track last submission date in `memory/heartbeat-state.json` 2. Check if submission already done today 3. Generate track using existing tracks as style reference 4. Generate cover art 5. Submit via x402 6. Update state file ``` ### Technical Analysis The Skill grants its payment workflow access to an EVM private key and configures that key as the signer used by `wrapFetchW ...[truncated 3136 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Require explicit payment approval** - Display the exact amount, token, recipient, chain, and reason before every paid submission. - Require affirmative user confirmation immediately before signing. - Do not allow heartbeat or unattended automation to approve paid transactions. 2. **Validate every payment challenge** - Enforce an allowlist of expected chain IDs. - Verify the exact USDC token contract address for each allowed chain. - Allow only the documented claw.fm payment recipient. - Reject payments above the documented price or any amount not explicitly approved. - Validate challenge expiration, request binding, and replay protection. 3. **Implement spending limits** - Enforce a hard per-transaction maximum of the documented submission price. - Add daily and lifetime spending limits. - Fail closed when pricing or payment metadata is missing, ambiguous, or changed. 4. **Reduce wallet privileges** - Use a dedicated, low-balance wallet exclusively for this Skill. - Do not reuse a primary wallet or a wallet holding unrelated assets. - Where supported, use scoped session keys or smart-account policies that restrict recipient, token, chain, amount, and transaction frequency. 5. **Protect secret material** - Store private keys in an operating-system keychain, hardware wallet, or dedicated secret manager. - Never place private keys in `TOOLS.md`, source files, logs, memory files, prompts, or other workspace documentation. - Ensure errors and diagnostic output cannot serialize the key or signer object. 6. **Separate free and paid automation** - Permit unattended submission only when the server confirms that no payment is required. - Pause and request user authorization whenever an x402 payment challenge is returned. - Record sanitized transaction details and approval status in an audit log without recording private keys. ]]>
