T09 · Insecure Skill Coding Practices
Error
- Location
- plugin.ts:298
- Finding
- AI Prompt Injection in Structured SOL Transfer Tool<![CDATA[ ## Vulnerability Details **File Location**: `plugin.ts:298-299` **Vulnerability Type**: Natural-language command injection in a financial operation **Risk Level**: High ### Vulnerable Code ```ts const message = `transfer ${amount_sol} SOL to ${to}` const text = await consumeChatStream(message) ``` ### Technical Analysis The `transfer_sol` tool accepts structured `to` and `amount_sol` parameters, but it does not submit them to a dedicated typed transfer API. Instead, it concatenates both values into a natural-language command and sends that command to the general-purpose `/api/chat` AI endpoint. The `to` value is not locally validated as either a valid Solana base58 address or a trusted contact name. An attacker who can influence tool parameters can therefore include additional natural-language instructions in this field. The downstream AI may interpret those instructions as part of the command rather than as recipient data. The implementation also does not locally verify that `amount_sol` is finite, positive, or within the documented per-action limit. Although the project states that limits are enforced by the downstream Rust signer, this adapter does not preserve a strict typed boundary between untrusted parameters and AI instructions. ### Attack Path 1. An attacker supplies content that influences the host Agent or directly controls the arguments passed to `transfer_sol`. 2. The attacker places additional instructions in the `to` parameter, such as a recipient-like prefix followed by another wallet command. 3. The plugin interpolates the untrusted value into `transfer ${amount_sol} SOL to ${to}`. 4. `consumeChatStream()` submits the resulting text to the authenticated `/api/chat` endpoint. 5. The downstream AI interprets the entire string as natural-language instructions. 6. Depending on the downstream policy, operating mode, and signer safeguards, the AI may attempt an unintended transfer or another wallet operation. ### Impact Assessment ...[truncated 728 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Replace the natural-language transfer mechanism with a dedicated typed endpoint, for example: ```ts await sonaPost("/api/transfers", { recipient: validatedRecipient, amount_sol: validatedAmount, }, true) ``` 2. Validate `to` before sending it: - Require a syntactically valid Solana base58 public key; or - Resolve a contact name through a trusted contact API and use the resulting address. - Reject whitespace, control characters, sentence delimiters, and arbitrary instruction text. 3. Validate `amount_sol` locally: - Require `Number.isFinite(amount_sol)`. - Require an amount greater than zero. - Enforce the documented local maximum. - Convert SOL to lamports using a safe, deterministic representation. 4. Require a transaction preview containing the resolved address, lamport amount, fees, and network before authorization. 5. Keep final spend-limit enforcement in the signer as defense in depth. Adapter-side validation must not replace signer-side policy enforcement. 6. Add tests with malicious recipient strings to ensure that untrusted values can never become executable AI instructions. ]]>
