T09 · Insecure Skill Coding Practices
Warning
- Location
- SKILL.md:43
- Finding
- Replayable Wallet Registration Signature<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:43-51` **Vulnerability Type**: Replayable authentication proof **Risk Level**: Medium ### Vulnerable Code ```bash # Sign with cast (Foundry) — produces a hex signature cast wallet sign "I am registering as an omni.fun agent" # Or use any EIP-712 signer — the signature proves wallet ownership ``` ```bash curl -X POST https://api.omni.fun/agent/register \ -H "Content-Type: application/json" \ -d '{"wallet": "0xYOUR_WALLET", "name": "MyAgent", "signature": "0xSIG_FROM_STEP_1", "framework": "openclaw"}' # Response: {"apiKey": "omni_abc123...", "agentId": "..."} ``` ### Technical Analysis The documented registration procedure signs a fixed message that does not include a server-issued nonce, expiration time, intended recipient, chain ID, or explicit EIP-712 domain separation. Although the text refers to EIP-712, the demonstrated `cast wallet sign` command signs a static text message and does not show typed structured data. A signature over a fixed message remains valid indefinitely unless the server implements additional undocumented replay protection. An attacker who acquires the signature could resubmit it with the corresponding public wallet address. Because the registration endpoint returns an API key, successful replay may allow the attacker to register or impersonate the wallet identity. This assessment is limited to the documented workflow. The server implementation was not included in the project, so undocumented server-side nonce or duplicate-registration controls could not be verified. ### Attack Path 1. The wallet owner signs the fixed registration message. 2. An attacker obtains the signature through logs, clipboard history, command output, insecure storage, or interception at an untrusted client boundary. 3. The attacker sends the wallet address and captured signature to `POST /agent/register`. 4. If the service does not enforce a single-use challenge or reject duplicate regis ...[truncated 863 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Require the client to request a cryptographically random, single-use registration nonce from the server. 2. Use a fully specified EIP-712 typed-data structure containing: - The wallet address - The server-issued nonce - The intended registration action - The service domain and verifying contract or service identifier - The applicable chain ID - An issuance timestamp and short expiration time 3. Bind the challenge to the submitted agent metadata where appropriate. 4. Atomically invalidate the nonce after the first verification attempt or successful registration. 5. Reject expired, previously used, malformed, and cross-domain signatures. 6. Enforce clear duplicate-registration and API-key recovery policies. 7. Replace the static-message example with an exact typed-data signing example supported by the chosen signer. 8. Avoid printing or persistently storing registration signatures, even after nonce protection is added. ]]>
