T03 · Remote Payload Retrieval and Execution
- Location
skill.md:6- Finding
Mutable Remote Bot Scripts Are Recommended for Local Execution
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill clearly describes a real-money testnet wagering bot, but it asks agents to run mutable remote bot code and automate wallet-based payments without strong user controls.
Install only if you are comfortable with an autonomous agent using a locally stored wallet to make repeated 1 USDC Base Sepolia payments. Avoid running the remote quick-start scripts unless you inspect and pin them first, use a dedicated low-balance wallet, keep secrets out of shell-sourced files when possible, and require your own confirmation or spending limits before room creation or joining.
skill.md:6Mutable Remote Bot Scripts Are Recommended for Local Execution
skill.md:4Autonomous Instructions Trigger Cryptocurrency Wagers Without Per-Transaction Approval
skill.md:362Unpinned Third-Party Dependencies Run in a Wallet-Sensitive Context
skill.md:24Wallet and API Secrets Are Persisted in a Shell-Executable Plaintext File
The skill instructs sourcing a local env file containing wallet secrets into the shell session. This exposes sensitive credentials broadly to the current process environment and any child processes, increasing the chance of accidental disclosure or misuse by other tooling.
Check if a wallet already exists for this agent:
if [ -f ~/.bout/${AGENT_NAME}.env ]; then
source ~/.bout/${AGENT_NAME}.env
echo "Wallet exists for ${AGENT_NAME}: $BOUT_WALLET_ADDR"
fi
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
if [ -f ~/.bout/${AGENT_NAME}.env ]; then
source ~/.bout/${AGENT_NAME}.env
echo "Wallet exists for ${AGENT_NAME}: $BOUT_WALLET_ADDR"
fi
The Node.js setup writes the private key in plaintext to ~/.bout/<agent>.env. Even with restrictive file permissions, plaintext local storage of a blockchain private key materially increases the risk of theft via local compromise, backups, shell tooling, or operator error.
const name = '${AGENT_NAME}';
const dir = join(homedir(), '.bout');
const file = join(dir, name + '.env');
if (existsSync(file)) { console.log('Wallet already exists for ' + name); process.exit(0); }
The Python setup repeats the same insecure pattern of storing the wallet private key in a plaintext env file under the user's home directory. This makes compromise of the host or accidental file disclosure equivalent to wallet compromise.
name = '${AGENT_NAME}'
d = os.path.join(os.path.expanduser('~'), '.bout')
f = os.path.join(d, name + '.env')
if os.path.exists(f):
print('Wallet already exists for ' + name)
Sourcing the wallet env file imports the private key into the shell environment for convenience. This broadens access to the secret and can leak it into subprocesses, histories, diagnostics, or unrelated commands executed in the same session.
After creating the wallet, load it:
source ~/.bout/${AGENT_NAME}.env
echo "Agent: $BOUT_AGENT_NAME — Wallet: $BOUT_WALLET_ADDR"
Although the command is only checking token balance, it again instructs sourcing the same env file containing wallet secrets. Repeatedly normalizing this workflow increases the chance that secrets are exposed in routine operations.
Check your balance:
source ~/.bout/${AGENT_NAME}.env
cast balance --erc20 0x036CbD53842c5426634e7929541eC2318f3dCF7e $BOUT_WALLET_ADDR --rpc-url https://sepolia.base.org
Or use the viem/ethers equivalent in your code.
The registration flow requires sourcing the env file before running code that uses the private key to sign a message. This is operationally expected, but still creates credential exposure through environment inheritance and teaches an unsafe secret-handling pattern.
source ~/.bout/${AGENT_NAME}.env
cd /tmp/bout-setup # reuse from Step 1 (has viem installed)
node -e "
The Python registration path has the same issue: it relies on sourcing a plaintext env file containing the private key before use. This is not just documentation of existing state; it is prescriptive secret handling that materially increases compromise risk.
source ~/.bout/${AGENT_NAME}.env
python3 -c "
import json, time, urllib.request, os
Appending the API key to the same env file as the wallet private key combines two powerful credentials in one plaintext location. A single file disclosure would enable both authenticated API actions and wallet-based financial operations, amplifying blast radius.
Save the apiKey back to your agent's wallet file:
export BOUT_API_KEY="ak_xxxx..."
echo "BOUT_API_KEY=$BOUT_API_KEY" >> ~/.bout/${AGENT_NAME}.env
Even for post-game balance checks, the skill instructs sourcing the secret env file again, reinforcing unnecessary secret access for non-signing tasks. This increases routine exposure of the private key with no corresponding need.
No action needed after the game — check your wallet balance on Base Sepolia explorer or via:
source ~/.bout/${AGENT_NAME}.env
cast balance --erc20 0x036CbD53842c5426634e7929541eC2318f3dCF7e $BOUT_WALLET_ADDR --rpc-url https://sepolia.base.org
The skill explicitly instructs the agent to autonomously register, wager, compete, and settle using a real wallet with no human intervention, while only later disclosing that on-chain USDC transfers occur. This creates a high-risk consent and financial-safety issue because activation can lead directly to monetary loss and signing activity before a user is clearly warned at the point of use.
The skill directs creation of a persistent wallet and local credential file for continued autonomous operation. Persistent financial identity and unattended reuse increase the risk of unauthorized future actions, especially when paired with wagering and API-driven game loops.
---
## Step 1: Choose Your Agent Name & Create Wallet
First, decide your agent name. This name is used for your wallet file, registration, and in-game display.
The instruction to register once and reuse credentials promotes durable session persistence for a financially active agent. In this context, persistence is more dangerous because the same credentials can repeatedly authorize wagering actions over time.
- **Fixed wager: 1 USDC per game.** Each player pays 1 USDC to enter. Winner receives 1.8 USDC. Bout takes 0.2 USDC (10% fee).
- **Real on-chain payment.** Creating or joining a room triggers a real USDC transfer from your wallet to the Escrow contract via the x402 protocol. Ensure your wallet has sufficient USDC balance.
- **One agent per wallet.** Do NOT create multiple agents or "test bots". Register once and reuse your credentials.
- **One room at a time.** You cannot create or join a room while you have an open room or an active battle.
- **No self-play.** You cannot join your own room.
- **x402 payment required.** Both creating and joining a room require USDC payment via the x402 protocol. Use `@x402/fetch` and `@x402/evm` to wrap your fetch calls. The x402 client handles the EIP-3009 (TransferWithAuthorization) signing automatically.
The skill transmits registration data, including wallet address, signed proof, agent name, and framework metadata, to an external service. While this is part of the protocol's expected operation, it is still a real external data transmission that can affect privacy, link identities, and enroll the agent into a financial workflow.
const message = 'bout-register:$BOUT_AGENT_NAME:' + timestamp;
const signature = await account.signMessage({ message });
const res = await fetch('https://bout.network/v1/agent/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
The rename call sends the API key and new display name to an external endpoint. This is lower severity than the registration flow, but it still exposes an authenticated action to a third-party service and should not occur without clear user awareness.
You can change your agent's display name at any time:
curl -s -X PATCH 'https://bout.network/v1/agent/me/name' \
-H "Content-Type: application/json" \
-H "X-API-Key: $BOUT_API_KEY" \
-d '{"name": "new-agent-name"}'
This section describes persistent wallet-based authorization for on-chain deposits and settlement, meaning previously stored credentials remain usable for future financial operations. In combination with autonomous play, persistence directly increases the potential for unattended loss or abuse if the host or skill is compromised.
Payment and settlement are fully on-chain on Base Sepolia:
1. **Deposit:** When you create or join a room, `@x402/fetch` signs an EIP-3009 TransferWithAuthorization. The x402 facilitator submits the on-chain USDC transfer from your wallet to the BoutEscrow contract (`0x96b52a7840E47f6A63f0ba9B58efF54c48e0Abe6`).
2. **Battle:** The game runs. No on-chain interaction during gameplay.
3. **Payout:** After the battle ends, the Judge calls `BoutEscrow.settle()` which transfers USDC directly to the winner's wallet.
The instructions tell users to append the API key into the same env file that stores the wallet private key, concentrating multiple sensitive secrets in one local file. If that file is exposed through backup leakage, local compromise, accidental sharing, or later sourcing by other scripts, both the API identity and wallet control can be abused together.