Back to skill

Security audit

Okx 402 Payment

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent payment helper, but it gives agents unsafe signing workflows that could expose a private key or authorize payment terms the user did not clearly approve.

Review this skill carefully before installing. It should only be used with payment endpoints you trust, and users should verify the exact token, amount, recipient, network, and selected scheme before signing. Avoid the local private-key fallback unless necessary, and do not let an agent paste untrusted 402 headers or JSON into a shell command string.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
protocols/x402.md:121
Finding

Shell Command Injection Through Untrusted x402 Payment Requirements

Content
View full analysis
' ``` The same unsafe argument construction is documented for local signing: ```bash onchainos payment eip3009-sign \ --accepts '' ``` ### Technical Analysis The `decoded.accepts` array comes from an untrusted HTTP 402 response. For x402 v2, it is decoded from the merchant-controlled `PAYMENT-REQUIRED` header; for v1, it comes from the response body. The playbook instructs the Agent to serialize this untrusted object and interpolate it inside a single-quoted shell argument. JSON strings may legally contain apostrophes. If an Agent or command tool executes the documented command through a shell, an attacker-controlled apostrophe can terminate the quoted argument. Shell operators embedded after it can then be interpreted as commands. JSON serialization does not provide shell escaping. Base64 decoding the original response also does not establish trust or integrity. ### Attack Path 1. A user asks the Agent to access an attacker-controlled or compromised payment-gated endpoint. 2. The endpoint returns HTTP 402 with a crafted `PAYMENT-REQUIRED` header or x402 JSON body. 3. An element of `accepts` contains an apostrophe followed by shell syntax in a merchant-controlled string field. 4. The Agent displays payment information and the user confirms the payment. 5. The Agent constructs the documented `onchainos payment x402-pay --accepts '...'` command. 6. If the command is passed through a shell, the crafted apostrophe closes the argumen ...[truncated 618 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
protocols/mpp.md:112
Finding

Shell Command Injection Through Raw MPP Challenge Headers

Content
View full analysis
' \ [--from '<0xPayer>'] ``` Additional affected command patterns include: ```bash onchainos payment mpp-session-voucher \ --challenge '' \ --channel-id '' \ --cumulative-amount '' \ --escrow '' \ --chain-id '' \ [--from ''] ``` ```bash onchainos payment mpp-session-close \ --challenge '' \ --channel-id '' \ --cumulative-amount '' \ --escrow '' \ --chain-id '' \ [--from ''] ``` ### Technical Analysis The playbook passes the complete `WWW-Authenticate` response-header value to the CLI through a single-quoted shell argument. The header is controlled by the payment server and is therefore untrusted. A malicious header can contain an apostrophe that terminates the quoted `--challenge` value, followed by shell operators and commands. If the Agent uses a shell to execute the example, the shell interprets the injected content rather than passing it as inert header data. The issue affects one-shot charges and MPP session operations, including opening, issuing vouchers, topping up, and closing a channel. ### Attack Path 1. The Agent requests a resource from a malicious or compromised MPP server. 2. The server responds with HTTP 402 and a crafted `WWW-Authenticate: Payment ...` header. 3. The header includes an apostrophe and shell command syntax in a challenge attribute. 4. The user ...[truncated 774 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
protocols/x402.md:60
Finding

User May Confirm Different x402 Terms Than the CLI Ultimately Signs

Content
View full analysis
`"aggr_deferred"` > first entry). ``` ```markdown Present the following information to the user: > This resource requires x402 payment: > - **Network**: `` (``) > - **Token**: `` (``) > - **Amount**: `` (from `option.amount` for v2, or `option.maxAmountRequired` for v1; convert from minimal units using token decimals) > - **Pay to**: `` > > Proceed with payment? (yes / no) ``` ```bash onchainos payment x402-pay \ --accepts '' ``` ### Technical Analysis The playbook displays only the first element of `decoded.accepts` to the user. However, it passes the entire array to the CLI and explicitly delegates selection to that CLI according to its own scheme preference. Nothing in the documented flow requires every entry to have identical network, asset, recipient, amount, or timeout. Consequently, the option signed by the CLI can differ from the option that the user reviewed and approved. This is a transaction-integrity problem: confirmation is not cryptographically or procedurally bound to the exact payment terms used for signing. ### Attack Path 1. A malicious payment server supplies multiple entries in `decoded.accepts`. 2. The first entry contains benign terms, such as a small amount and expected recipient. 3. A later entry uses the CLI's preferred scheme but contains a larger amount, diffe ...[truncated 833 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
protocols/x402.md:108
Finding

Agent Is Instructed to Read a Plaintext Private-Key File Unnecessarily

Content
View full analysis
"No private key configured. Please save it to `~/.onchainos/.env`: add a line `EVM_PRIVATE_KEY=0x`, then let me know." ``` The CLI reference separately states: ```markdown Sign an EIP-3009 `TransferWithAuthorization` locally using a hex private key (from `EVM_PRIVATE_KEY` env var or `~/.onchainos/.env`). ``` ### Technical Analysis The stated purpose of reading `~/.onchainos/.env` is only to determine whether `EVM_PRIVATE_KEY` exists. The same document says the `onchainos payment eip3009-sign` CLI automatically reads the environment variable or file. Direct Agent access is therefore unnecessary for the declared signing workflow. Reading the entire `.env` file can place the private key—and potentially unrelated credentials stored in the same file—into Agent context, tool logs, traces, or error messages. This exceeds least privilege because signing requires use of the key by the local signer, not disclosure of the key to the language-model layer. The fallback also recommends storing a long-lived EVM private key in a plaintext file. Although the playbook mentions `chmod 600`, plaintext storage still expands exposure compared with an operating-system key store, hardware-backed signer, or isolated signing service. No reviewed instruction explicitly sends the raw private key over the network. ...[truncated 1091 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (9)

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · protocols/x402.md (reported line 465)May include surrounding context.

md
- **Expired authorization**: If the server rejects the payment as expired, retry with a fresh signature
- **Network error**: Retry once, then prompt user to try again later

## Amount Display Rules

- `amount` (v2) / `maxAmountRequired` (v1) is always in minimal units (e.g., `1000000` for 1 USDG)
- When displaying to the user, convert to UI units: divide by `10^decimal`

Whitespace Padding

Medium
Category
Prompt Injection
Confidence
70% confidence
Finding

Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Content

Scanner excerpt · protocols/x402.md (reported line 203)May include surrounding context.

md
After a successful payment and response, suggest:

| Just completed          | Suggest                                                                                     |
|-------------------------|---------------------------------------------------------------------------------------------|
| Successful replay       | 1. Check balance impact → `okx-agentic-wallet` 2. Make another request to the same resource |
| 402 on replay (expired) | Retry from Step 3 with a fresh signature                                                    |

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · protocols/x402.md (reported line 214)May include surrounding context.

Workflow A: Pay for a 402-Gated API Resource (most common)

User: "Fetch https://api.example.com/data — it requires x402 payment"

text
1. Send GET https://api.example.com/data                              → HTTP 402

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · protocols/x402.md (reported line 217)May include surrounding context.

Workflow A: Pay for a 402-Gated API Resource (most common)

User: "Fetch https://api.example.com/data — it requires x402 payment"

text
1. Send GET https://api.example.com/data                              → HTTP 402

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · protocols/x402.md (reported line 320)May include surrounding context.

Workflow A: Pay for a 402-Gated API Resource (most common)

User: "Fetch https://api.example.com/data — it requires x402 payment"

text
1. Send GET https://api.example.com/data                              → HTTP 402

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · protocols/x402.md (reported line 339)May include surrounding context.

Workflow A: Pay for a 402-Gated API Resource (most common)

User: "Fetch https://api.example.com/data — it requires x402 payment"

text
1. Send GET https://api.example.com/data                              → HTTP 402

Whitespace Padding

Medium
Category
Prompt Injection
Confidence
70% confidence
Finding

Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Content

Scanner excerpt · protocols/x402.md (reported line 298)May include surrounding context.

--accepts ''

text

| Param             | Required | Default | Description                                                                                                             |
|-------------------|----------|---------|-------------------------------------------------------------------------------------------------------------------------|
| `EVM_PRIVATE_KEY` | Yes      | -       | Hex-encoded secp256k1 private key; read from env var, falls back to `~/.onchainos/.env`                                 |
| `--accepts`       | Yes      | -       | JSON `accepts` array from the 402 payload (same as `x402-pay`); `extra.name`/`extra.version` provide the EIP-712 domain |

External Transmission

Medium
Category
Data Exfiltration
Confidence
82% confidence
Finding

The playbook instructs replaying the request using decoded.resource metadata from the untrusted 402 payload without explicitly requiring verification that it matches the original requested URL/origin. A malicious server could present a crafted payment challenge that causes the agent to send an authorization header to an unintended endpoint, leaking a reusable payment proof or redirecting paid access.

Content

Scanner excerpt · protocols/x402.md (reported line 395)May include surrounding context.

md
}
headerValue = btoa(JSON.stringify(paymentPayload))

GET https://api.example.com/data
PAYMENT-SIGNATURE: <headerValue>

→ HTTP 200  { "result": "..." }

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · protocols/x402.md (reported line 403)May include surrounding context.

md
## Local Signing Fallback (No Wallet)

> **⚠️ Security Notice**: This fallback uses your local private key for signing — the key stays on your machine but is **not** protected by TEE. Only use this path if you cannot log in to the wallet, and ensure your private key is stored securely (e.g., `~/.onchainos/.env` with `chmod 600`). The recommended path is always TEE signing via `onchainos payment x402-pay`.

If the user chose "Local private key" in Step 2, use the native `onchainos payment eip3009-sign` command to sign locally.

Static analysis

No suspicious patterns detected.