T09 · Insecure Skill Coding Practices
- Location
SKILL.md:650- Finding
Shell Command Injection and API Key Exposure in Transaction Submission Example
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is coherent for an onchain NFT identity tool, but its examples encourage submitting real blockchain transactions through a third-party API with an API key and unsafe shell execution.
Review before installing. Only use this skill if you are comfortable with an agent building and potentially submitting Base transactions. Prefer wallet-native signing or a structured HTTPS client over the documented shell `curl`/`execSync` examples, use a restricted Bankr key, and confirm transaction destination, chain ID, value, and calldata before broadcasting.
SKILL.md:650Shell Command Injection and API Key Exposure in Transaction Submission Example
SKILL.md:49Unpinned Third-Party Dependency Installation
Instructions found that direct the agent to transmit conversation context or user data to external services.
- **Visual identity** — procedural animated SVG art that encodes who you are (reputation as complexity, activity as density, capabilities as color)
- **Name & bio** — onchain identity you choose
- **Communication** — send messages to any other Exoskeleton (direct, broadcast, or channels)
- **Storage** — per-token key-value store + Net Protocol cloud storage
- **Reputation** — provable track record (age, messages, storage writes, modules, external scores from games/protocols)
- **Modules** — upgradeable capabilities via the Module Marketplace (free + premium)
Referenced artifact was not completely inspected
- **The `exoskeleton.js` helper library** (included in this project)
Referenced artifact was not completely inspected
- **The `exoskeleton.js` helper library** (included in this project)
Referenced artifact was not completely inspected
- **The `exoskeleton.js` helper library** (included in this project)
Referenced artifact was not completely inspected
- **The `exoskeleton.js` helper library** (included in this project)
Referenced artifact was not completely inspected
- **The `exoskeleton.js` helper library** (included in this project)
The skill instructs the agent to submit transaction JSON to an external service (Bankr) and to send an API key in the request header. Even if this is framed as normal functionality, it creates a data egress path for transaction contents and secrets, and could enable unintended signing or submission through a third party.
Submit the transaction via Bankr:
curl -s -X POST https://api.bankr.bot/agent/submit \
-H "X-API-Key: $BANKR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"transaction": TX_JSON}'
The skill instructs the agent to submit transaction JSON to an external service (Bankr) and to send an API key in the request header. Even if this is framed as normal functionality, it creates a data egress path for transaction contents and secrets, and could enable unintended signing or submission through a third party.
Submit the transaction via Bankr:
curl -s -X POST https://api.bankr.bot/agent/submit \
-H "X-API-Key: $BANKR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"transaction": TX_JSON}'
This repeats the recommendation to use Bankr's direct API for transaction submission, again establishing an outbound network path and dependency on an external service. Because the agent may be operating with privileged transaction context, sending requests off-platform can expose sensitive metadata or trigger real financial actions.
Submit using Bankr's direct API (recommended):
curl -s -X POST https://api.bankr.bot/agent/submit \
-H "X-API-Key: $BANKR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"transaction": TX_JSON}'
This repeats the recommendation to use Bankr's direct API for transaction submission, again establishing an outbound network path and dependency on an external service. Because the agent may be operating with privileged transaction context, sending requests off-platform can expose sensitive metadata or trigger real financial actions.
Submit using Bankr's direct API (recommended):
curl -s -X POST https://api.bankr.bot/agent/submit \
-H "X-API-Key: $BANKR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"transaction": TX_JSON}'
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
**Storage:**
- `setData(uint256 tokenId, bytes32 key, bytes value)` — Store key-value data
- `getData(uint256 tokenId, bytes32 key) → bytes` — Read stored data
- `setNetProtocolOperator(uint256 tokenId, address operator)` — Set cloud storage pointer
**Reputation:**
The example uses execSync to construct and execute a curl command that includes the API key and serialized transaction data inline. This is more dangerous than a static curl snippet because it encourages shell execution with secrets in command strings, increasing the risk of credential leakage, command injection bugs, process-list exposure, and accidental submission of transactions.
function submitTx(tx) {
const result = JSON.parse(execSync(
`curl -s -X POST https://api.bankr.bot/agent/submit ` +
`-H "X-API-Key: ${process.env.BANKR_API_KEY}" ` +
`-H "Content-Type: application/json" ` +
`-d '${JSON.stringify({ transaction: tx })}'`
The example uses execSync to construct and execute a curl command that includes the API key and serialized transaction data inline. This is more dangerous than a static curl snippet because it encourages shell execution with secrets in command strings, increasing the risk of credential leakage, command injection bugs, process-list exposure, and accidental submission of transactions.
function submitTx(tx) {
const result = JSON.parse(execSync(
`curl -s -X POST https://api.bankr.bot/agent/submit ` +
`-H "X-API-Key: ${process.env.BANKR_API_KEY}" ` +
`-H "Content-Type: application/json" ` +
`-d '${JSON.stringify({ transaction: tx })}'`
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
* // Writing (returns transaction JSON for Bankr)
* const tx = exo.buildSetName(1, "Atlas");
* const tx = exo.buildSendMessage(1, 42, ethers.ZeroHash, 0, "hello!");
* // Submit `tx` via Bankr: curl -X POST https://api.bankr.bot/agent/submit ...
*
* CLI:
* node exoskeleton.js 1
No suspicious patterns detected.