T09 · Insecure Skill Coding Practices
Error
- Location
- SKILL.md:31
- Finding
- Unverified Remote Vault Address Used for Signed Mainnet Financial Transactions## Vulnerability Details **File Location**: `SKILL.md`, lines 31 and 115–160 **Vulnerability Type**: Untrusted remote address resolution and unsafe private-key handling **Risk Level**: High ### Vulnerable Code ```sh VAULT_ADDRESS=$(curl -s "https://api.terminal.markets/api/v1/vault?ownerAddress=$(cast wallet address --private-key $DX_TERMINAL_PRIVATE_KEY)" | jq -r .vaultAddress) ``` The remotely returned address is subsequently used as the destination for signed Base mainnet transactions: ```sh cast send "$VAULT_ADDRESS" "updateSettings((uint256,uint256,uint8,uint8,uint8,uint8,uint8))" "(5000,200,3,3,3,3,3)" --private-key "$DX_TERMINAL_PRIVATE_KEY" --rpc-url "https://mainnet.base.org" ``` ```sh cast send "$VAULT_ADDRESS" "addStrategy(string,uint64,uint8)" "Rotate into strongest relative volume while keeping 20% idle ETH for opportunities." "$(( $(date +%s) + 86400 ))" "2" --private-key "$DX_TERMINAL_PRIVATE_KEY" --rpc-url "https://mainnet.base.org" ``` ```sh cast send "$VAULT_ADDRESS" "disableStrategy(uint256)" "1" --private-key "$DX_TERMINAL_PRIVATE_KEY" --rpc-url "https://mainnet.base.org" ``` ```sh cast send "$VAULT_ADDRESS" "depositETH()" --value 0.05ether --private-key "$DX_TERMINAL_PRIVATE_KEY" --rpc-url "https://mainnet.base.org" ``` ```sh cast send "$VAULT_ADDRESS" "withdrawETH(uint256)" "50000000000000000" --private-key "$DX_TERMINAL_PRIVATE_KEY" --rpc-url "https://mainnet.base.org" ``` ### Technical Analysis The destination stored in `VAULT_ADDRESS` is obtained directly from `api.terminal.markets` and then trusted for every state-changing transaction. The documented workflow does not: - Validate that the response is a syntactically valid Ethereum address. - Independently derive the expected vault address. - Verify the address through an authenticated on-chain registry. - Confirm that the returned contract is owned by or associated with the expected wallet. - Check the deployed contract bytecode or implementation. - Confirm the Base chain ID ...[truncated 2543 chars]
- Remediation
- ## Remediation Suggestions 1. **Verify the vault through an authoritative on-chain source** - Resolve the vault using a documented registry or factory contract on Base. - Confirm that the registry associates the vault with the address derived from the user’s wallet. - If deterministic deployment is used, independently calculate the expected vault address. 2. **Validate the remote API response** - Reject empty, null, malformed, zero, or non-checksummed addresses. - Treat the API result as an untrusted hint rather than the source of authority. - Fail closed when the API and on-chain registry disagree. 3. **Verify the target contract** - Confirm the Base chain ID before signing. - Require deployed bytecode at the destination. - Compare the runtime bytecode or implementation against an approved contract version. - Verify proxy implementations and upgrade administrators where proxy contracts are used. 4. **Add transaction safety controls** - Simulate each transaction before broadcasting it. - Display the chain, destination, decoded function, parameters, ETH value, gas estimate, and simulation result. - Require explicit user confirmation for settings changes, strategy changes, deposits, and withdrawals. - Apply configurable transaction-value and slippage limits. 5. **Use a secure signer** - Do not pass raw private keys through command-line arguments. - Use a hardware wallet, encrypted keystore, operating-system keychain, or isolated signing service. - Ensure the signer presents transaction details for approval. - Disable shell tracing and avoid recording commands containing secrets. 6. **Improve failure handling** - Use strict shell behavior and make `curl` fail on HTTP errors. - Validate JSON parsing before assigning `VAULT_ADDRESS`. - Abort transaction execution whenever address verification, contract verification, or simulation fails.
