Back to skill

Security audit

4Claw Mint

Security checks for vulnerabilities and agentic risk

Overview

This skill performs the advertised token minting flow, but it uses raw wallet keys and remote signing in ways that can expose users to unauthorized or misdirected blockchain transactions.

Review carefully before installing or running. Do not paste a funded wallet private key into the documented command. Treat the signer URL as security-critical, prefer HTTPS and a pinned expected contract address, and do not operate the signer service publicly without authentication, durable rate limits, and body-size limits.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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
Findings (4)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/server.js:33
Finding
Unauthenticated Mint Authorization Service<![CDATA[ ## Vulnerability Details **File Location**: `scripts/server.js:33-80` **Vulnerability Type**: Missing authentication and ineffective authorization controls **Risk Level**: High ### Vulnerable Code ```js async function handleMintRequest(req, res) { try { const { wallet_address } = await parseBody(req); if (!wallet_address || !ethers.isAddress(wallet_address)) { return respond(res, 400, { error: "Invalid wallet_address" }); } const addr = wallet_address.toLowerCase(); const now = Math.floor(Date.now() / 1000); // Check cooldown (server-side, contract also enforces) if (lastMintTime[addr] && now - lastMintTime[addr] < MINT_COOLDOWN) { const remaining = MINT_COOLDOWN - (now - lastMintTime[addr]); return respond(res, 429, { error: "Cooldown not elapsed", retry_after_seconds: remaining }); } // Generate nonce and deadline const nonce = "0x" + crypto.randomBytes(32).toString("hex"); const deadline = now + SIGNATURE_TTL; // Sign: keccak256(abi.encodePacked(minter, nonce, deadline, chainId, contract)) const messageHash = ethers.solidityPackedKeccak256( ["address", "bytes32", "uint256", "uint256", "address"], [wallet_address, nonce, deadline, CHAIN_ID, CONTRACT_ADDRESS] ); const signature = await signer.signMessage(ethers.getBytes(messageHash)); // Update cooldown lastMintTime[addr] = now; return respond(res, 200, { success: true, nonce, deadline, signature, contract: CONTRACT_ADDRESS, chain_id: CHAIN_ID }); } catch(e) { console.error("[Error]", e.message); return respond(res, 500, { error: "Internal server error" }); } } ``` ### Technical Analysis The mint-signature endpoint issues a signer-authorized mint payload to every client that supplies a syntactically valid wallet address. It does not authenticate the requesting agent, verify ownership of the requested wallet, valid ...[truncated 1453 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Require cryptographically verifiable OpenClaw agent attestations before issuing an authorization. - Require proof of possession of the requested wallet, such as a server-provided challenge signed by that wallet. - Bind each challenge to the authenticated identity, wallet address, intended contract, chain ID, expiration time, and a single-use nonce. - Maintain used nonces and cooldown records in durable storage rather than process memory. - Apply global, per-identity, per-wallet, and per-network-source rate limits. - Restrict access through an authenticated gateway or allowlist where appropriate. - Monitor and alert on bulk requests, rapidly changing wallet addresses, and abnormal authorization volume. - Ensure the deployed contract independently enforces replay protection, mint limits, cooldowns, signer validation, and authorization expiry. ]]>

T07 · Tool Hijacking and Spoofing

Error
Location
scripts/mint.js:10
Finding
Untrusted Plaintext Signer Response Controls the Transaction Destination<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mint.js:10-11, 55-74` **Vulnerability Type**: Untrusted remote transaction-destination selection over plaintext HTTP **Risk Level**: High ### Vulnerable Code ```js const PRIVATE_KEY = process.argv[2]; const SERVER_URL = process.argv[3] || "http://43.160.201.224:3456"; const BSC_RPC = "https://bsc-dataseed1.binance.org"; ``` ```js // Step 1: Request mint signature from server console.log("Requesting mint signature..."); const sigRes = await fetchJSON(`${SERVER_URL}/api/mint-signature`, { wallet_address: wallet.address }); if (sigRes.status === 429) { console.log(`Cooldown active. Retry in ${sigRes.data.retry_after_seconds}s`); process.exit(0); } if (sigRes.status !== 200 || !sigRes.data.success) { console.error("Signature request failed:", sigRes.data); process.exit(1); } const { nonce, deadline, signature, contract } = sigRes.data; console.log(`Got signature. Contract: ${contract}, Deadline: ${deadline}`); // Step 2: Call mint on contract const fourClaw = new ethers.Contract(contract, CONTRACT_ABI, wallet); console.log("Sending mint transaction..."); const tx = await fourClaw.mint(nonce, deadline, signature); ``` ### Technical Analysis The default signer-service URL uses unencrypted HTTP. An on-path attacker or a compromised signer service can alter the JSON response in transit. More importantly, the client treats the response's `contract` field as authoritative and immediately constructs a wallet-connected contract object for that address. The client does not compare the returned address with the documented token contract, validate the returned `chain_id`, verify the destination's deployed bytecode, or confirm that the wallet provider is connected to the expected chain. The remote response therefore controls the destination of a transaction signed by the user's wallet. An attacker-selected contract only needs to expose a compatible `mint(bytes32,uint256,bytes)` function for th ...[truncated 1461 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove plaintext HTTP support for production signer services and require HTTPS with valid certificate verification. - Define the expected chain ID and checksummed contract address as trusted local configuration. - Reject any response whose contract address or chain ID differs from those trusted values. - Query the provider network before signing and abort unless it is BSC mainnet with chain ID 56. - Verify that the destination contains deployed bytecode and, where practical, compare its runtime bytecode hash against a reviewed deployment. - Validate the nonce, deadline, signature format, and expiration before constructing the transaction. - Display the fixed destination and transaction details for explicit confirmation when an interactive wallet is used. - Consider certificate or public-key pinning where the operational environment can securely maintain pins. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/mint.js:4
Finding
Wallet Private Key Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mint.js:4-9` **Vulnerability Type**: Insecure secret handling **Risk Level**: Medium ### Vulnerable Code ```js // 4Claw Mint Script — called by OpenClaw agents via skill // Usage: node mint.js <private_key> <server_url> // Example: node mint.js 0xYOUR_PRIVATE_KEY http://43.160.201.224:3456 const { ethers } = require("ethers"); const https = require("https"); const http = require("http"); const PRIVATE_KEY = process.argv[2]; ``` The same insecure invocation method is documented in `SKILL.md:31-38`: ```bash node scripts/mint.js <PRIVATE_KEY> <SERVER_URL> ``` ### Technical Analysis The script accepts a wallet private key as a positional command-line argument. Command-line arguments may be observable through process inspection facilities, automation telemetry, diagnostic tools, terminal scrollback, shell command history, job definitions, or logs produced by wrappers and orchestration systems. A wallet private key is a bearer credential that grants the holder full signing authority. Unlike a password, it generally cannot be rotated without moving the wallet's assets and changing the wallet address. Passing it through `argv` unnecessarily expands the number of local components that may capture it. ### Attack Path 1. A user follows the documented command and includes the raw wallet private key in the shell command. 2. The command is retained in shell history, captured by a process monitor, or recorded by an automation or logging layer. 3. A local attacker or another party with access to those records retrieves the key. 4. The attacker imports the key into a wallet and signs arbitrary transactions as the victim. 5. The attacker transfers assets or otherwise exercises all privileges associated with that wallet. ### Impact Assessment Disclosure results in complete compromise of the affected wallet. An attacker can sign arbitrary transactions, transfer native currency and tokens, interact with con ...[truncated 239 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Prefer an interactive wallet, hardware wallet, operating-system key store, or external signing provider so the application never receives the raw private key. - If raw-key input is unavoidable, read it through an interactive hidden prompt or a protected file descriptor rather than command-line arguments. - Do not print, log, serialize, or retain the private key. - Clear references to secret material as soon as practical, while recognizing that JavaScript does not guarantee secure memory erasure. - Update `SKILL.md` to remove the command-line private-key example and document a secure signing workflow. - Warn users to migrate assets immediately if a key has already appeared in shell history or logs. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/server.js:25
Finding
Unbounded HTTP Request Body Enables Denial of Service<![CDATA[ ## Vulnerability Details **File Location**: `scripts/server.js:25-31` **Vulnerability Type**: Unbounded request buffering **Risk Level**: Medium ### Vulnerable Code ```js function parseBody(req) { return new Promise((resolve, reject) => { let body = ""; req.on("data", c => body += c); req.on("end", () => { try { resolve(JSON.parse(body)); } catch(e) { reject(e); } }); }); } ``` ### Technical Analysis The HTTP server concatenates every received request-body chunk into an in-memory string without enforcing a maximum size. It also does not establish an application-level body timeout in this function. Because `/api/mint-signature` is publicly reachable and does not require authentication, an attacker can submit oversized bodies or maintain slow uploads. Repeated string concatenation and subsequent JSON parsing consume memory and event-loop time. Multiple concurrent requests can amplify resource usage and may cause garbage-collection pressure, severe latency, or process termination from memory exhaustion. ### Attack Path 1. An attacker opens one or more connections to `POST /api/mint-signature`. 2. The attacker sends a very large body, or continuously streams body data without completing the request. 3. The server appends all received data to the `body` string without checking its size. 4. Concurrent malicious requests consume increasing memory and connection resources. 5. The signer service becomes slow, unavailable, or crashes, preventing legitimate mint-authorization requests. ### Impact Assessment A remote unauthenticated attacker can degrade or deny availability of the signer service. The primary scope is the Node.js process and the mint-signature API; resource exhaustion may also affect other workloads sharing the same host or container. This issue does not by itself provide code execution or signer-key disclosure. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Enforce a small maximum request-body size appropriate for a single wallet address, such as 1–4 KB. - Track accumulated bytes while receiving chunks and immediately destroy or reject requests that exceed the limit. - Return HTTP `413 Payload Too Large` for oversized bodies. - Configure request, headers, keep-alive, and body-read timeouts to mitigate slow-request attacks. - Apply connection and request rate limits at both the application and reverse-proxy layers. - Limit concurrent requests and deploy the service behind a hardened reverse proxy. - Require the request `Content-Type` to be `application/json` and validate the body against a strict schema. - Add monitoring for oversized requests, slow connections, memory growth, and abnormal connection counts. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (8)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The documented purpose presents the skill as a simple mint/status/info utility, but the behavior includes handling raw private keys, initiating blockchain transactions, and contacting an external signing service. That mismatch is dangerous because users and orchestrators may approve or route the skill under false assumptions, leading to credential disclosure, unexpected fund movement, or unreviewed outbound network communication.

Missing User Warnings

High
Confidence
99% confidence
Finding
The script takes a raw private key as a command-line argument, which commonly exposes secrets through shell history, process listings, job logs, orchestration metadata, and monitoring tools. In an agent skill that mints on behalf of users, this is especially dangerous because compromise of the private key gives full control of the wallet and any assets it holds, far beyond this single mint operation.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill describes behavior that relies on sensitive capabilities such as environment access and operational secrets, but it declares no explicit tool scope or permissions. This creates an authorization transparency gap: a caller or platform may not realize the skill can access secrets or perform privileged actions, increasing the chance of unintended secret exposure or unauthorized execution.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The instructions explicitly tell operators to pass a raw wallet private key and configure a signer private key, but provide no warning about the sensitivity of those credentials or safer handling methods. In this context, the risk is elevated because the skill also directs use of an external IP-based signer service; compromise, logging, shell history leakage, or operator error could expose keys that control wallets or the mint authorization service.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The script allows an arbitrary `server_url` argument and then POSTs the wallet address to `${SERVER_URL}/api/mint-signature`, trusting the returned `contract`, `nonce`, `deadline`, and `signature`. In this skill context, that is more dangerous than a generic outbound request because the remote server directly influences which on-chain contract the agent signs and pays gas to interact with, enabling phishing, transaction redirection, and unwanted network egress to attacker-controlled hosts.

Missing User Warnings

Medium
Confidence
85% confidence
Finding
This code reads a signing private key from the SIGNER_PRIVATE_KEY environment variable and immediately uses it to create a wallet, but there is no comment, docstring, or user-facing disclosure explaining that the service depends on sensitive credential material. For code files, access to sensitive environment variables should have at least some visible warning or explanation unless clearly documented elsewhere in the skill description, which is not present in this file.

Description-Behavior Mismatch

Medium
Confidence
88% confidence
Finding
The manifest describes a skill used to mint 4Claw tokens on BSC, which implies carrying out or directly initiating the mint action. In this file, the main operation is generating and returning an off-chain signature plus metadata; no blockchain transaction is submitted and no mint function is invoked, so the implemented behavior is materially narrower and different from the claimed minting behavior.

Context-Inappropriate Capability

Low
Confidence
84% confidence
Finding
The public status endpoint discloses the signer address, contract address, chain ID, and cooldown policy to any caller. While none of these are secret individually, exposing signer identity and operational details makes targeted abuse, reconnaissance, and service fingerprinting easier for attackers against a mint-signing service.

Static analysis

No suspicious patterns detected.