T09 · Insecure Skill Coding Practices
- Location
scripts/evm-verify-tx.sh:74- Finding
JavaScript Injection Through Unvalidated Chain ID in Transaction Verification
- Content
View full analysis
&2; exit 1; } EXPLORER="$(node -e "const c=require('$SCRIPT_DIR/lib/rpc-config.js'); const m=c.getChainMeta('$CHAIN_ID'); process.stdout.write(m?m.explorer+'/tx/':'')")" ``` ### Technical Analysis The `--chain-id` argument is not validated before `CHAIN_ID` is interpolated into JavaScript source supplied to `node -e`. Because the value is placed inside a JavaScript single-quoted string, an attacker can close the string and append arbitrary JavaScript. Shell quoting does not prevent this vulnerability: variable expansion occurs inside the double-quoted shell argument, and the resulting text is then parsed as JavaScript by Node.js. Injected JavaScript can invoke modules such as `child_process` and execute operating-system commands with the privileges of the Skill process. ### Attack Path 1. An attacker influences the `--chain-id` value passed to `evm-verify-tx.sh`. 2. The attacker supplies a payload that terminates the JavaScript string, such as a value structurally equivalent to: ```text ');require("child_process").execSync("attacker-command");(' ``` 3. The shell interpolates the payload into the `node -e` source. 4. Node.js parses and executes the injected statement before transaction verification begins. 5. The attacker-controlled command runs under the account operating the Agent or Skill. ### Impact Assessment Successful exploitation provides arbitrary code execution with the privileges of the Skill process. ...[truncated 348 chars]- Remediation
View remediation
&2 exit 1 fi ``` 2. Never interpolate user-controlled data into JavaScript source. Pass it through `process.argv`: ```bash RPC="$(node -e ' const c = require(process.argv[1]); const rpc = c.getRpc(process.argv[2]); if (!rpc) process.exit(1); process.stdout.write(rpc); ' "$SCRIPT_DIR/lib/rpc-config.js" "$CHAIN_ID")" ``` 3. Move substantial JavaScript into a static `.js` file to eliminate dynamic source construction. 4. Restrict chain IDs to an explicit supported-chain allowlist where arbitrary networks are unnecessary. 5. Run the Skill under a minimally privileged account with restricted filesystem and network access. ]]>
