Back to skill

Security audit

Uniclaw Skill

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed prediction-market trading tool, but it handles wallet secrets and token withdrawals with weak scoping and limited user guardrails.

Install only if you are comfortable giving this skill access to your Unicity wallet for trading and withdrawals. Use a testnet or limited-balance wallet, avoid custom UNICLAW_SERVER values unless you trust the endpoint, verify withdrawal recipients manually, and prefer a version that removes raw private-key export, hardcoded credentials, and weak request signing.

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
lib/api.ts:15
Finding
Request signatures do not bind the HTTP method, path, or destination<![CDATA[ ## Vulnerability Details **File Location**: `lib/api.ts:15-28`, `lib/api.ts:45-55`, and `lib/api.ts:68-78` **Vulnerability Type**: Insufficient request-signature scope and cross-endpoint replay **Risk Level**: High ### Vulnerable Code ```ts export function signRequest(body: unknown, privateKeyHex: string): { body: string; headers: SignedHeaders } { const timestamp = Date.now(); const payload = JSON.stringify({ body, timestamp }); const messageHash = sha256(new TextEncoder().encode(payload)); const privateKeyBytes = hexToBytes(privateKeyHex); const signature = secp256k1.sign(messageHash, privateKeyBytes); const publicKey = bytesToHex(secp256k1.getPublicKey(privateKeyBytes, true)); return { body: JSON.stringify(body), headers: { 'x-signature': bytesToHex(signature), 'x-public-key': publicKey, 'x-timestamp': String(timestamp), 'content-type': 'application/json', }, }; } ``` ```ts export async function apiGet(path: string, privateKeyHex: string): Promise<any> { const signed = signRequest({}, privateKeyHex); const res = await fetch(`${config.serverUrl}${path}`, { method: 'GET', headers: signed.headers, }); const data = await res.json(); if (!res.ok) { throw new Error(data.error ?? `HTTP ${res.status}`); } return data; } ``` ```ts export async function apiDelete(path: string, privateKeyHex: string): Promise<any> { const signed = signRequest({}, privateKeyHex); const res = await fetch(`${config.serverUrl}${path}`, { method: 'DELETE', headers: signed.headers, }); const data = await res.json(); if (!res.ok) { throw new Error(data.error ?? `HTTP ${res.status}`); } return data; } ``` ### Technical Analysis The signed payload contains only the request body and timestamp: ```ts JSON.stringify({ body, timestamp }) ``` It does not include the HTTP method, normalized URL path, query parameters, destination origin, or a single-use nonce. Consequently, all GE ...[truncated 2473 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Sign a canonical request envelope containing at least: - A protocol or signature-scheme version. - The HTTPS origin or server identifier. - The uppercase HTTP method. - The normalized path and canonical query string. - A cryptographic hash of the exact transmitted body. - The timestamp. - A cryptographically random nonce. 2. For example, construct and sign a deterministic object equivalent to: ```ts { version: 1, origin, method, path, query, bodyHash, timestamp, nonce } ``` 3. Make the server verify every signed field against the received request before processing it. 4. Store used nonces server-side for the duration of the authentication window and reject duplicate nonces. 5. Enforce a narrow timestamp tolerance and reject stale or future-dated requests. 6. Require `https:` for production endpoints. If development HTTP support is necessary, restrict it to loopback addresses and require an explicit development mode. 7. Consider allowlisting the official API hostname by default and requiring a prominent warning or explicit opt-in for custom remote hosts. 8. Add tests proving that a signature generated for: - GET `/api/agent/balance` cannot authorize DELETE requests. - One path cannot authorize another path. - One origin cannot authorize requests to another origin. - A nonce cannot be reused. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
lib/wallet.ts:28
Finding
Credential-like oracle API key is hardcoded as a fallback<![CDATA[ ## Vulnerability Details **File Location**: `lib/wallet.ts:28-33` **Vulnerability Type**: Hardcoded secret or shared service credential **Risk Level**: Medium ### Vulnerable Code ```ts oracle: { trustBasePath, apiKey: process.env.UNICITY_API_KEY ?? 'sk_06365a9c44654841a366068bcfc68986', }, transport: { debug: true, }, ``` ### Technical Analysis The wallet provider configuration contains a plaintext `sk_`-prefixed API credential as the fallback when `UNICITY_API_KEY` is absent. Anyone with access to the Skill package can recover this value without executing the code. A credential distributed in client-side source cannot be treated as confidential or as a reliable client-authentication mechanism. If the key remains active, unrelated parties may use it outside the Skill. Even if it is intended as a public testnet key, the code does not identify it as non-secret, constrain its permissions, or prevent use in other configured network modes. The key is supplied to the Sphere SDK's oracle provider. The exact remote endpoint and permissions are implemented in the dependency and were not established from the reviewed first-party source, so the maximum backend privilege should not be overstated. Nevertheless, embedding an apparently secret bearer credential is an insecure credential-management practice. ### Attack Path 1. An attacker downloads or inspects the Skill package. 2. The attacker reads `lib/wallet.ts` and extracts the hardcoded API key. 3. The attacker identifies the oracle API used by the Sphere SDK or observes normal SDK traffic in a controlled environment. 4. The attacker submits requests directly using the extracted credential. 5. If the key is active and accepted, the requests consume the credential owner's permissions, quota, or rate limits. No access to the user's wallet, local files, or private key is necessary for this attack. ### Impact Assessment Potential impact includes unauthorized oracle API usage, quota or rate-limit exh ...[truncated 365 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Revoke and rotate the exposed key if it is active or has ever been treated as confidential. 2. Remove the fallback credential and fail safely when no key is configured: ```ts const apiKey = process.env.UNICITY_API_KEY; if (!apiKey) { throw new Error('UNICITY_API_KEY is required'); } ``` 3. Provision credentials through a secret manager, protected environment injection, or an authenticated backend rather than distributing them in the package. 4. Prefer short-lived, narrowly scoped tokens. Restrict them by permitted endpoint, network, rate, expiration, and—where practical—client identity. 5. If anonymous testnet access is intended, expose a deliberately public and heavily rate-limited endpoint rather than presenting a shared value as an API secret. 6. Ensure testnet credentials cannot access mainnet or administrative operations. 7. Add repository secret scanning and CI checks that reject committed API-key patterns. 8. Review service logs for unauthorized use of the exposed value and monitor newly issued credentials for abnormal traffic. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (71)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The skill is presented as a market-trading tool but also performs withdrawals and fund transfers, which are distinct high-risk asset-movement operations. Undeclared transfer capability is particularly dangerous in this context because users may not expect that invoking the skill could result in irreversible off-platform movement of tokens.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The skill is presented as a market-trading tool but also performs withdrawals and fund transfers, which are distinct high-risk asset-movement operations. Undeclared transfer capability is particularly dangerous in this context because users may not expect that invoking the skill could result in irreversible off-platform movement of tokens.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill is presented as a market-trading tool but also performs withdrawals and fund transfers, which are distinct high-risk asset-movement operations. Undeclared transfer capability is particularly dangerous in this context because users may not expect that invoking the skill could result in irreversible off-platform movement of tokens.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill is presented as a market-trading tool but also performs withdrawals and fund transfers, which are distinct high-risk asset-movement operations. Undeclared transfer capability is particularly dangerous in this context because users may not expect that invoking the skill could result in irreversible off-platform movement of tokens.

Ae1

High
Category
analysis-evasion
Content
npx tsx scripts/market.ts list
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
npx tsx scripts/market.ts list
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
npx tsx scripts/trade.ts buy --market <id> --side yes --price 0.35 --qty 10
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
npx tsx scripts/trade.ts buy --market <id> --side yes --price 0.35 --qty 10
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
npx tsx scripts/trade.ts buy --market <id> --side yes --price 0.35 --qty 10
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
npx tsx scripts/trade.ts buy --market <id> --side yes --price 0.35 --qty 10
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
npx tsx scripts/portfolio.ts balance
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
npx tsx scripts/portfolio.ts balance
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
This helper intentionally bypasses the SDK’s public wallet abstraction to extract and return raw private key material from an internal field. In a trading skill, exposing the private key is unnecessary for normal market operations and creates a direct path for theft, unauthorized signing, or exfiltration by any downstream code that calls this function.

Missing User Warnings

High
Confidence
98% confidence
Finding
A helper that returns the raw private key without any strong guardrails or user warning materially expands the attack surface around the wallet. In the context of a trading skill, this is more dangerous because the expected capability is transaction signing and position management, not secret export, so any caller gaining access can fully compromise the wallet and funds.

Credential Access

High
Category
Privilege Escalation
Content
"@libp2p/crypto": "^5.1.7",
        "@libp2p/interface": "^3.1.0",
        "@libp2p/kad-dht": "^16.1.0",
        "@libp2p/keychain": "^6.0.5",
        "@libp2p/logger": "^6.0.5",
        "@libp2p/utils": "^7.0.5",
        "interface-datastore": "^9.0.2",
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"@libp2p/crypto": "^5.1.7",
        "@libp2p/interface": "^3.1.0",
        "@libp2p/kad-dht": "^16.1.0",
        "@libp2p/keychain": "^6.0.5",
        "@libp2p/logger": "^6.0.5",
        "@libp2p/utils": "^7.0.5",
        "interface-datastore": "^9.0.2",
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"@libp2p/crypto": "^5.1.7",
        "@libp2p/interface": "^3.1.0",
        "@libp2p/kad-dht": "^16.1.0",
        "@libp2p/keychain": "^6.0.5",
        "@libp2p/logger": "^6.0.5",
        "@libp2p/utils": "^7.0.5",
        "interface-datastore": "^9.0.2",
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"@libp2p/crypto": "^5.1.7",
        "@libp2p/interface": "^3.1.0",
        "@libp2p/kad-dht": "^16.1.0",
        "@libp2p/keychain": "^6.0.5",
        "@libp2p/logger": "^6.0.5",
        "@libp2p/utils": "^7.0.5",
        "interface-datastore": "^9.0.2",
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"@libp2p/crypto": "^5.1.7",
        "@libp2p/interface": "^3.1.0",
        "@libp2p/kad-dht": "^16.1.0",
        "@libp2p/keychain": "^6.0.5",
        "@libp2p/logger": "^6.0.5",
        "@libp2p/utils": "^7.0.5",
        "interface-datastore": "^9.0.2",
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"@libp2p/crypto": "^5.1.7",
        "@libp2p/interface": "^3.1.0",
        "@libp2p/kad-dht": "^16.1.0",
        "@libp2p/keychain": "^6.0.5",
        "@libp2p/logger": "^6.0.5",
        "@libp2p/utils": "^7.0.5",
        "interface-datastore": "^9.0.2",
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"@libp2p/crypto": "^5.1.7",
        "@libp2p/interface": "^3.1.0",
        "@libp2p/kad-dht": "^16.1.0",
        "@libp2p/keychain": "^6.0.5",
        "@libp2p/logger": "^6.0.5",
        "@libp2p/utils": "^7.0.5",
        "interface-datastore": "^9.0.2",
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"@libp2p/crypto": "^5.1.7",
        "@libp2p/interface": "^3.1.0",
        "@libp2p/kad-dht": "^16.1.0",
        "@libp2p/keychain": "^6.0.5",
        "@libp2p/logger": "^6.0.5",
        "@libp2p/utils": "^7.0.5",
        "interface-datastore": "^9.0.2",
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Known Vulnerable Dependency: @libp2p/kad-dht==16.1.3 — 1 advisory(ies): CVE-2026-45783 (@libp2p/kad-dht: Unvalidated PUT_VALUE records allow unbounded disk exhaustion o)

High
Category
Supply Chain
Confidence
91% confidence
Finding
The lockfile includes '@libp2p/kad-dht' version 16.1.3, which is flagged with a disk-exhaustion DoS advisory. In a trading skill, untrusted network interaction through optional libp2p/helia dependencies can increase operational risk because resource exhaustion could disrupt market actions or make the agent unavailable.

Known Vulnerable Dependency: ws==7.5.10 — 1 advisory(ies): CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
88% confidence
Finding
The lockfile contains 'ws' 7.5.10, which is flagged for memory exhaustion DoS via fragmented frames. Even as a transitive optional dependency, if any included devtool, React Native, or networking path is exposed during build, testing, or runtime, an attacker could cause service instability or crashes.

Known Vulnerable Dependency: axios==1.13.5 — 16 advisory(ies): CVE-2026-44494 (axios Vulnerable to Full Man-in-the-Middle via Prototype Pollution Gadget in `co); CVE-2026-44495 (axios Vulnerable to Credential Theft and Response Hijacking via Prototype Pollut); CVE-2025-62718 (Axios has a NO_PROXY Hostname Normalization Bypass that Leads to SSRF) +13 more

High
Category
Supply Chain
Confidence
80% confidence
Finding
The lockfile includes 'axios' 1.13.5 with multiple advisories, including SSRF and prototype-pollution-related issues. In a network-connected trading skill, any vulnerable HTTP client increases risk because remote endpoints, proxy settings, or attacker-controlled inputs could influence outbound requests or response handling.

Static analysis

No suspicious patterns detected.