T09 · Insecure Skill Coding Practices
- Location
docs/AGENT-INTEGRATION.md:135- Finding
Shell Command Injection in Documented CLI Integration
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill mostly matches its game-playing purpose, but it needs review because it can automatically spend or move real USDC and includes unsafe shell-based integration examples.
Install only with a dedicated low-balance wallet, keep the private key out of logs and repositories, set strict local spending limits outside the skill, review the API/RPC endpoints before use, and prefer the GameClient API over the documented execSync CLI examples.
docs/AGENT-INTEGRATION.md:135Shell Command Injection in Documented CLI Integration
lib/client.js:27Automatic x402 Payment Authorization Without Local Spending Constraints
The code does operate on the Clabcraw platform and participates in USDC-based matches, so it is related to the declared domain. However, the declared description is broad and implies a normal-purpose 1v1 game competitor, while the actual code is specifically a poker auto-play script designed for quick local/testing-style games. Its primary behavior is materially narrower and different: it only targets poker and deliberately switches to an all-in strategy after the first five hands to finish games fast. That undisclosed game-specific and quick-play behavior makes the description inaccurate.
The declared description says the skill competes in 1v1 games on the Clabcraw arena, but this code does not contain any game interaction or gameplay logic. Instead, it implements payment and signing utilities: it converts a private key into a viem account and creates a fetch wrapper that automatically handles x402 payment flows by signing USDC authorizations when a server responds with 402 Payment Required. That is a materially different primary purpose from playing Clabcraw matches. While payment support could be a supporting detail for a USDC-based arena, this chunk is purely payment infrastructure and cryptographic signing, not competition logic, so the description does not accurately represent this code chunk.
The code does support the declared core purpose of competing in Clabcraw 1v1 games for USDC: it joins games, retrieves game state, submits actions, and runs a game loop. However, it also includes materially additional financial and platform-management capabilities not reflected in the description, notably tipping the platform, checking claimable balances, and executing on-chain claim transactions through a wallet client. These are beyond merely competing in games and should be declared if this description is meant to accurately represent the skill’s behavior. Declared permissions are empty, yet the code uses a private key, makes signed requests, performs payment-enabled requests, and can submit blockchain transactions; while permission mismatch alone is not the main criterion, these behaviors reinforce that the implementation is broader than the stated purpose.
The declared purpose is a game-playing skill for the Clabcraw arena involving 1v1 competition for USDC. The provided code chunk does not implement gameplay, arena interaction, wallet/payment handling, or any trigger logic. Instead, it provides generic logging utilities. While logging can be a supporting implementation detail, this chunk alone does not reflect the declared purpose and is materially unrelated in primary behavior.
The declared description suggests an active skill that competes in Clabcraw 1v1 games for USDC. However, this code chunk only contains local data-transformation helpers: parsing card strings, normalizing valid actions, and converting a raw game-state response into a cleaner object. It does not initiate or join games, submit moves, handle wallets/USDC, call external services, or otherwise perform competition behavior. While this code could support such a skill as an internal helper, by itself it does not accurately represent the declared primary purpose.
The declared purpose describes gameplay functionality on the Clabcraw arena, likely involving participating in 1v1 USDC games. However, the supplied code chunk does not implement gameplay or arena interaction at all. It only reads local files and runs tests to ensure that contract address values are consistent between configuration sources. This is a materially different primary purpose from the declared description, so it should be flagged as a mismatch.
The description says the skill competes in 1v1 games on the Clabcraw arena for USDC. However, the provided code chunk is only a test suite for error classes and HTTP response mapping in lib/errors.js. It checks behavior for statuses like 400, 401, 402, 404, 422, 500, and 503, plus retry timing and specialized errors such as paused, insufficient funds, and invalid action. While this may support a larger Clabcraw client, this specific code does not perform gameplay, place wagers, interact with arena matches, or handle game turns beyond testing error objects. Therefore the actual behavior does not match the declared primary purpose.
This code chunk does not implement a game-playing skill. It only contains tests for helper functions (parseCard, normalizeState) that transform card and state data into normalized structures. There is no network access, no trigger handling, no betting or wallet logic, and no action-selection code to compete in 1v1 matches. While the tested schema relates to card-game state, that is only a supporting data-model concern and does not match the declared primary purpose of actively competing on Clabcraw for USDC.
The declared purpose suggests an operational skill that participates in 1v1 games on the Clabcraw arena involving USDC. However, the actual code chunk contains only tests for a poker strategy library. It exercises functions like handRank, estimateEquity, potOdds, shouldCall, suggestBetSize, countOuts, and findAction. There is no code showing connection to Clabcraw, no arena/gameplay integration, no blockchain or USDC handling, no triggers, and no logic specific to 1v1 competition on that platform. The primary purpose of the code is materially different from the declared description, so this is a clear mismatch.
Referenced artifact was not completely inspected
The best way to run this skill is using **GameClient** from `lib/game.js`. It handles all coordination automatically — joining, matching, state polling, and gam
Referenced artifact was not completely inspected
The best way to run this skill is using **GameClient** from `lib/game.js`. It handles all coordination automatically — joining, matching, state polling, and gam
Advising users to place a blockchain private key in a local .env file creates a straightforward credential-exposure path if the file is copied, logged, backed up, or accidentally committed. Because the credential directly controls funds, compromise can immediately lead to wallet takeover and financial loss.
Or store in a .env file (never commit to git):
# .env
CLABCRAW_WALLET_PRIVATE_KEY=0x...
The lockfile pins transitive dependency ws to version 8.18.3, and the supplied finding indicates known advisories affecting that exact version, including memory disclosure and memory-exhaustion denial of service. In a skill that interacts with blockchain/network services, WebSocket usage is plausible via viem, so a vulnerable ws package can expose the agent to remote attack surface if it connects to untrusted or attacker-influenced endpoints.
The skill declares capabilities that require environment access and outbound network use, including a wallet private key and API calls, but does not declare any tool scope or permissions boundary. In an agent platform, this increases the chance the skill runs with broader-than-necessary privileges and makes review, sandboxing, and user consent weaker.
The quick-start path says joining the queue pays an entry fee via x402, but it does not provide a prominent warning that real funds will be spent automatically when the command runs. In an agent setting, insufficient spending disclosure can lead to unintentional financial loss, especially if auto-play is launched with a funded wallet.
The wallet setup instructions print the private key to stdout, store it in a plaintext file, and then display the file contents with cat. Even though file permissions are tightened, these steps materially increase the chance of credential exposure through shell history, terminal logs, screenshots, backups, or agent execution logs, and compromise would enable theft of USDC and wallet control.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
mkdir -p ~/.clabcraw && chmod 700 ~/.clabcraw
node -e "
import { generatePrivateKey, privateKeyToAddress } from 'viem'
The instructions create a persistent directory under the user's home folder and store wallet material there for reuse across sessions. Persistent storage of a high-value private key expands the exposure window and increases the blast radius of any later host compromise, log leak, or backup leak.
mkdir -p ~/.clabcraw && chmod 700 ~/.clabcraw
node -e "
import { generatePrivateKey, privateKeyToAddress } from 'viem'
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
console.log('Private Key:', key)
" > ~/.clabcraw/wallet-key.txt
chmod 600 ~/.clabcraw/wallet-key.txt
cat ~/.clabcraw/wallet-key.txt
# Load it:
The guide instructs users to provide a wallet private key via environment variables without clearly flagging that this is a highly sensitive credential controlling on-chain funds. In agent and automation environments, environment variables are frequently exposed through logs, process inspection, crash reports, CI systems, or inherited subprocesses, increasing the risk of wallet compromise and theft.
The integration guide shows agents how to automatically join paid games, claim winnings, and send tips using real USDC, but it does not prominently warn that these actions spend or move real funds. In an agent context, examples are often copied directly into autonomous workflows, so this can lead to unintended financial transactions, repeated paid actions, or unauthorized value transfer if the agent is triggered incorrectly.
The documentation instructs users to run a queue-join command that pays a USDC entry fee and requires a wallet private key, but it does not provide an explicit warning that executing the command authorizes spending real funds. In an agent-skill context, this is especially risky because an autonomous system may invoke the command as part of normal operation, causing unintended financial loss or repeated paid joins without meaningful user consent.
The documentation describes a claim command that withdraws all claimable USDC on-chain using a wallet private key, but it lacks a clear caution that this initiates a blockchain transaction, consumes gas, and moves assets. In an agent environment, this can lead to unauthorized transfers, accidental claims to the wrong wallet or network configuration, and unnecessary gas expenditure if invoked automatically.
The example directly calls game.claim() and logs a transaction hash in a troubleshooting context without an explicit warning that this initiates a real on-chain withdrawal. In a skill centered on real-money USDC gameplay, readers may copy-paste recovery snippets into production agents and unintentionally trigger fund-moving transactions when they only intended to inspect balances or debug failures.
This queue-leave example automatically follows cancellation with game.claim() after checking for a positive balance, but does not clearly warn that the call performs a real on-chain withdrawal. Because the skill operates in a financial setting using USDC, such documentation can normalize automatic fund-moving behavior in agent code and increase the risk of unintended transactions, gas expenditure, or premature withdrawals.