Back to skill

Security audit

Sona Agentic Wallet

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed local Solana wallet-control adapter, but it needs Review because it gives an agent high-impact fund-moving and autonomous-mode authority without strong confirmation boundaries.

Install only if you understand that an OpenClaw agent with SONA_TOKEN can move funds, approve queued wallet actions, send arbitrary commands to the wallet agent, and switch SONA into autonomous mode. Use devnet or low-value wallets, keep policy limits tight, and avoid exposing the token to agents or contexts you do not fully trust.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

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. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
plugin.ts:233
Finding
Static Agent-Supplied Acknowledgment Can Enable Autonomous Wallet Mode<![CDATA[ ## Vulnerability Details **File Location**: `plugin.ts:233-243` **Vulnerability Type**: Ineffective authorization and confirmation control **Risk Level**: High ### Vulnerable Code ```ts const { mode, acknowledgment } = params as { mode: string acknowledgment?: string } const body: Record<string, string> = { mode } if (mode === "god") { if (acknowledgment !== "I UNDERSTAND") { return ok( 'God mode requires acknowledgment="I UNDERSTAND". ' + "This enables full autonomous execution within Constitutional Law limits." ) } body.acknowledgment = "I UNDERSTAND" } const res = await sonaPost("/api/mode", body, true) as any ``` ### Technical Analysis Switching to “god” mode enables full autonomous execution within the downstream system’s stated limits. The only plugin-side confirmation is the fixed phrase `I UNDERSTAND`. This phrase is disclosed in the tool schema and can be generated automatically by the same AI Agent that chooses to invoke the tool. It therefore does not prove that the wallet owner provided fresh, informed consent. The acknowledgment and the privileged mode-change request travel through the same Agent-controlled channel and use the same preconfigured session token. This is an ineffective confirmation boundary for a high-impact privilege transition. Prompt injection, compromised conversation context, or erroneous Agent planning could satisfy the check without direct human participation. ### Attack Path 1. Malicious or misleading content influences the host Agent’s planning. 2. The content persuades the Agent to invoke `set_mode` with `mode: "god"`. 3. The Agent obtains the required fixed acknowledgment from the public tool schema or the tool’s own error response. 4. The Agent calls the tool again with `acknowledgment: "I UNDERSTAND"`. 5. The plugin sends the authenticated request to `/api/mode`. 6. If the local SONA API accepts the request, the wallet enters autonomous execution mode. 7. Subsequent maliciou ...[truncated 900 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require out-of-band owner approval through the trusted SONA dashboard, hardware wallet, or another channel inaccessible to the Agent. 2. Use a short-lived, single-use challenge: - The Agent requests a mode change. - The owner reviews its consequences in a trusted interface. - The backend issues a cryptographically random, narrowly scoped approval token. - The token expires quickly and can only authorize the specific transition. 3. Require reauthentication or hardware-backed confirmation before enabling autonomous mode. 4. Do not expose a reusable confirmation secret or fixed phrase in the tool schema, documentation, or error response. 5. Separate capabilities: - Use a read-only token for status and policy tools. - Use a restricted transaction token for ordinary operations. - Require a distinct elevated credential for changing execution mode. 6. Record an immutable audit event and notify the owner whenever autonomous mode is requested, enabled, or disabled. 7. Consider preventing the OpenClaw tool from enabling “god” mode entirely. The tool could allow transitions only to less privileged modes, while elevation must occur directly through the trusted owner interface. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (9)

External Transmission

Medium
Category
Data Exfiltration
Content
### 2. Get a session token

```bash
TOKEN=$(curl -s -X POST http://localhost:3000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"you","password":"yourpass"}' | jq -r '.token')
```
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill exposes sensitive capabilities through environment access and network interaction, but it does not declare any explicit tool scope such as permissions or allowed-tools. That weakens least-privilege guarantees and makes it harder for users or hosting platforms to understand and constrain what the skill can access before installation.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
This skill can perform real wallet transfers, swaps, staking, approvals, and autonomous state changes, yet the description does not present a prominent warning that these actions can move funds. In a wallet automation context, missing user-facing risk disclosure increases the chance of accidental authorization or misuse of a high-impact financial skill.

External Transmission

Medium
Category
Data Exfiltration
Content
### 2. Get a session token

```bash
curl -s -c cookies.txt -X POST http://localhost:3000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"your_user","password":"your_pass"}' | jq -r '.token'
```
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
// ── Helpers ───────────────────────────────────────────────────────────────────

function headers(withAuth = false): Record<string, string> {
  const h: Record<string, string> = { "Content-Type": "application/json" }
  if (withAuth && TOKEN) h["Cookie"] = `sona_session=${encodeURIComponent(TOKEN)}`
  return h
Confidence
75% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
// ── Helpers ───────────────────────────────────────────────────────────────────

function headers(withAuth = false): Record<string, string> {
  const h: Record<string, string> = { "Content-Type": "application/json" }
  if (withAuth && TOKEN) h["Cookie"] = `sona_session=${encodeURIComponent(TOKEN)}`
  return h
Confidence
75% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
// ── Helpers ───────────────────────────────────────────────────────────────────

function headers(withAuth = false): Record<string, string> {
  const h: Record<string, string> = { "Content-Type": "application/json" }
  if (withAuth && TOKEN) h["Cookie"] = `sona_session=${encodeURIComponent(TOKEN)}`
  return h
Confidence
75% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The approve_action tool performs a state-changing authorization step immediately when invoked, without any additional user-facing confirmation or friction in this plugin layer. In the context of a wallet/agent-control skill, approving queued actions can directly enable downstream fund movements or other autonomous operations, so prompt injection or accidental invocation by a higher-level agent could cause unintended execution.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The chat tool forwards arbitrary natural-language input to an autonomous wallet agent that may reason, plan, and execute actions, yet the tool interface does not enforce any confirmation, scoping, or strong warning at execution time. Because this skill explicitly exposes transfers, swaps, rule-setting, and mode changes, a compromised or prompt-injected upstream agent could issue free-form commands that trigger real financial actions.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
plugin.ts:30