Back to skill

Security audit

Monolith — Crypto Wallet

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent crypto wallet skill, but it needs review because it relies on root-installed external wallet components and remote swap data for fund-moving actions without enough verifiable safeguards.

Review this carefully before installing. The JavaScript skill is not obviously deceptive and the risky wallet behavior is mostly disclosed, but installing it means trusting externally downloaded macOS components with persistent wallet authority. Verify release signatures and hashes independently, understand what the daemon can do, and avoid using command-line approval codes or large-value swaps until the external binaries and swap validation path have been independently audited.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (3)

T08 · Insecure Dependencies

Error
Location
SKILL.md:6
Finding
Privileged External Wallet Components Are Installed Without Artifact Integrity Verification<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:6` and `SKILL.md:57-61` **Vulnerability Type**: Unverified privileged external dependency **Risk Level**: High ### Vulnerable Code ```yaml metadata: {"openclaw":{"displayName":"Monolith — Crypto Wallet","source":"https://github.com/slaviquee/monolith/tree/main/skill","homepage":"https://github.com/slaviquee/monolith","os":["darwin"],"requires":{"bins":["MonolithDaemon"]},"install":[{"id":"daemon-pkg","kind":"download","label":"Install Monolith Daemon (macOS pkg)","url":"https://github.com/slaviquee/monolith/releases/download/v0.1.5/MonolithDaemon-v0.1.5.pkg","os":["darwin"]},{"id":"companion-zip","kind":"download","label":"Download Monolith Companion (macOS app zip)","url":"https://github.com/slaviquee/monolith/releases/download/v0.1.3/MonolithCompanion.app.zip","os":["darwin"]}]}} ``` ```markdown 1. Install Monolith from ClawHub: `clawhub install monolith` 2. Start a new OpenClaw session so the skill is loaded. 3. Install local macOS components from the install entries: - `MonolithDaemon-v0.1.5.pkg` (admin/root install) - `MonolithCompanion.app.zip` (extract app to `/Applications` and open once) ``` ### Technical Analysis The Skill delegates its most security-sensitive operations—including key isolation, transaction signing, policy enforcement, biometric approval, and wallet deployment—to binaries that are not included in the audited project. The installation metadata downloads those components from release assets in a personal GitHub repository. The documentation explicitly states that the daemon package requires an administrator/root installation. However, neither the installation metadata nor the setup instructions provide: - A pinned cryptographic digest for either artifact. - A required Apple Developer ID signing identity. - A notarization verification command. - A reproducible-build procedure. - A mechanism that binds the downloaded binary to the reviewed source revision. HTTP ...[truncated 2036 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Publish a SHA-256 or stronger digest for every downloadable artifact and make installation fail closed on a mismatch. 2. Sign the PKG and application with a stable organization-controlled Apple Developer ID. 3. Require verification before installation, for example with `pkgutil --check-signature`, `codesign --verify --deep --strict`, and `spctl --assess`. 4. Publish notarization details and require macOS Gatekeeper validation. 5. Move releases to an organization-controlled repository with protected branches, mandatory review, hardware-backed maintainer authentication, and isolated release credentials. 6. Use a hardened, auditable CI release workflow with provenance attestations and immutable release artifacts. 7. Provide reproducible build instructions linking each binary release to a specific source commit. 8. Avoid administrator installation if technically possible. Run the daemon as the logged-in user with narrowly scoped filesystem and IPC permissions. 9. Document the daemon’s entitlements, installed paths, LaunchAgent configuration, network destinations, update mechanism, and uninstall procedure. 10. Independently audit the daemon and companion source because they implement the actual wallet security boundary. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
lib/intent-builder.js:236
Finding
Untrusted Uniswap API Calldata Is Forwarded for Signing Without Semantic Validation<![CDATA[ ## Vulnerability Details **File Location**: `lib/intent-builder.js:236-273` and `lib/intent-builder.js:339-349` **Vulnerability Type**: Insufficient validation of remotely supplied transaction calldata **Risk Level**: High ### Vulnerable Code ```js const res = await fetch('https://api.uniswap.org/v2/quote', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), signal: controller.signal, }); if (!res.ok) return null; const data = await res.json(); // Validate response shape if (!data.quote || !data.methodParameters) return null; const { methodParameters, quote } = data; const target = methodParameters.to; const calldata = methodParameters.calldata; const value = methodParameters.value; // Safety: target must be the expected Universal Router if (target.toLowerCase() !== UNISWAP.UNIVERSAL_ROUTER.toLowerCase()) return null; // Safety: chainId in response must match request if (data.chainId !== undefined && data.chainId !== chainId) return null; // Safety: calldata must be present and non-empty hex if (!calldata || calldata === '0x' || calldata.length < 10) return null; // Safety: value must be numeric string if (value === undefined || value === null) return null; // Safety: value must not exceed requested amountIn (prevents overspend) if (BigInt(value) > amountInWei) return null; const amountOut = BigInt(quote.amount ?? 0); if (amountOut === 0n) return null; return { target, calldata, value: String(value), amountOut }; ``` ```js // Primary: try Routing API const apiResult = await tryRoutingAPI(chainId, weth, tokenOutAddress, amountInWei, maxSlippageBps); if (apiResult) { return { target: apiResult.target, calldata: apiResult.calldata, value: apiResult.value, chainHint: chainId.toString(), quotedAmountOut: apiResult.amountOut, source: 'routing-api', }; } ``` The returned intent is subsequently submitted to the local signing daemon in `scripts/swap.js:48-59`: ```js ...[truncated 3544 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Decode `methodParameters.calldata` before accepting the API response. 2. Require the expected Universal Router `execute` selector and reject all other functions. 3. Maintain a strict allowlist of router commands needed for the declared swap. 4. Verify that the decoded input token, output token, exact input amount, recipient, path, chain, deadline, and minimum output match locally computed expectations. 5. Reject additional commands or inputs that are not required for the requested swap. 6. Derive `amountOutMin` locally from a validated quote and the configured maximum slippage. 7. Prefer constructing all transaction calldata locally. Treat the remote endpoint only as a source of quote and route data. 8. Independently verify quotes using on-chain state before signing when practical. 9. Require the daemon to repeat the complete semantic validation rather than trusting the Skill. 10. Bind any approval prompt to a normalized intent digest and show the exact recipient, tokens, input, guaranteed minimum output, and router commands to the user. 11. Add negative tests containing valid router addresses but malicious recipients, extra commands, altered paths, zero minimum output, and mismatched amounts. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/send.js:9
Finding
One-Time Wallet Approval Codes Are Exposed Through Process Arguments and Shell History<![CDATA[ ## Vulnerability Details **File Location**: `scripts/send.js:9-17`, `scripts/send.js:52-53`, `scripts/send.js:63-69`, `scripts/swap.js:10-17`, `scripts/swap.js:51-52`, and `scripts/swap.js:62-68` **Vulnerability Type**: Sensitive authorization data passed through command-line arguments **Risk Level**: Medium ### Vulnerable Code ```js /** * Send ETH or ERC-20 tokens. * Usage: node scripts/send.js <to> <amount> [token] [chainId] [approvalCode] * to: recipient address or ENS name * amount: amount to send (in human units, e.g., "0.1" ETH or "100" USDC) * token: "ETH" (default) or "USDC" * chainId: 1 or 8453 (optional, uses daemon's home chain) * approvalCode: 8-digit code from notification (if re-submitting after 202) */ async function main() { const [, , to, amount, token = 'ETH', chainIdStr, approvalCode] = process.argv; ``` ```js // Attach approval code if re-submitting after a 202 if (approvalCode) { intent.approvalCode = approvalCode; } ``` ```js } else if (response.status === 202) { console.log(`Approval required: ${response.data.reason}`); console.log(`Summary: ${response.data.summary}`); console.log(`Expires in: ${response.data.expiresIn}s`); console.log(`\nTo approve, re-run with the 8-digit code from your notification:`); console.log(` send ${to} ${amount} ${token} ${chainId} <approvalCode>`); } ``` The swap flow uses the same pattern: ```js /** * Usage: node scripts/swap.js <amountETH> [tokenOut] [chainId] [approvalCode] * amountETH: amount of ETH to swap (e.g., "0.1") * tokenOut: "USDC" (default) or a token address * chainId: 1 or 8453 (default: 8453) * approvalCode: 8-digit code from notification (if re-submitting after 202) */ async function main() { const [, , amountETH, tokenOut = 'USDC', chainIdStr, approvalCode] = process.argv; ``` ```js // Attach approval code if re-submitting after a 202 if (approvalCode) { daemonIntent.approvalCode = approvalCode; } ``` ```js } else if (respo ...[truncated 2780 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove approval codes from command-line syntax. 2. Read the code using an interactive no-echo prompt connected directly to a terminal. 3. Alternatively, complete approval through the trusted companion application without returning the secret to the Skill. 4. Do not print example commands that encourage placement of an approval secret in shell history. 5. Bind every code to a cryptographic digest of the exact normalized intent, including target, calldata, value, chain, and expiration. 6. Enforce one-time use, a short expiration period, strict attempt limits, and immediate invalidation after success. 7. Bind approval to the initiating user and local session where feasible. 8. Configure the Unix socket with restrictive ownership and permissions and reject unexpected peer credentials. 9. Avoid logging request bodies containing approval codes in the daemon, agent framework, or audit pipeline. 10. Clear in-memory code variables as soon as practical and ensure errors never echo the secret. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (25)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
Token swap routing, quote handling, symbol resolution, and fallback fee-tier probing all introduce undeclared network- and market-dependent behavior. In a wallet skill, hidden quote/routing logic can influence financial outcomes and trust decisions, especially if third-party API data is accepted without clear disclosure.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
Token swap routing, quote handling, symbol resolution, and fallback fee-tier probing all introduce undeclared network- and market-dependent behavior. In a wallet skill, hidden quote/routing logic can influence financial outcomes and trust decisions, especially if third-party API data is accepted without clear disclosure.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Token swap routing, quote handling, symbol resolution, and fallback fee-tier probing all introduce undeclared network- and market-dependent behavior. In a wallet skill, hidden quote/routing logic can influence financial outcomes and trust decisions, especially if third-party API data is accepted without clear disclosure.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
Token swap routing, quote handling, symbol resolution, and fallback fee-tier probing all introduce undeclared network- and market-dependent behavior. In a wallet skill, hidden quote/routing logic can influence financial outcomes and trust decisions, especially if third-party API data is accepted without clear disclosure.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
Token swap routing, quote handling, symbol resolution, and fallback fee-tier probing all introduce undeclared network- and market-dependent behavior. In a wallet skill, hidden quote/routing logic can influence financial outcomes and trust decisions, especially if third-party API data is accepted without clear disclosure.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Token swap routing, quote handling, symbol resolution, and fallback fee-tier probing all introduce undeclared network- and market-dependent behavior. In a wallet skill, hidden quote/routing logic can influence financial outcomes and trust decisions, especially if third-party API data is accepted without clear disclosure.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding
Token swap routing, quote handling, symbol resolution, and fallback fee-tier probing all introduce undeclared network- and market-dependent behavior. In a wallet skill, hidden quote/routing logic can influence financial outcomes and trust decisions, especially if third-party API data is accepted without clear disclosure.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
Token swap routing, quote handling, symbol resolution, and fallback fee-tier probing all introduce undeclared network- and market-dependent behavior. In a wallet skill, hidden quote/routing logic can influence financial outcomes and trust decisions, especially if third-party API data is accepted without clear disclosure.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Token swap routing, quote handling, symbol resolution, and fallback fee-tier probing all introduce undeclared network- and market-dependent behavior. In a wallet skill, hidden quote/routing logic can influence financial outcomes and trust decisions, especially if third-party API data is accepted without clear disclosure.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
Token swap routing, quote handling, symbol resolution, and fallback fee-tier probing all introduce undeclared network- and market-dependent behavior. In a wallet skill, hidden quote/routing logic can influence financial outcomes and trust decisions, especially if third-party API data is accepted without clear disclosure.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Token swap routing, quote handling, symbol resolution, and fallback fee-tier probing all introduce undeclared network- and market-dependent behavior. In a wallet skill, hidden quote/routing logic can influence financial outcomes and trust decisions, especially if third-party API data is accepted without clear disclosure.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
Token swap routing, quote handling, symbol resolution, and fallback fee-tier probing all introduce undeclared network- and market-dependent behavior. In a wallet skill, hidden quote/routing logic can influence financial outcomes and trust decisions, especially if third-party API data is accepted without clear disclosure.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
Token swap routing, quote handling, symbol resolution, and fallback fee-tier probing all introduce undeclared network- and market-dependent behavior. In a wallet skill, hidden quote/routing logic can influence financial outcomes and trust decisions, especially if third-party API data is accepted without clear disclosure.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
Token swap routing, quote handling, symbol resolution, and fallback fee-tier probing all introduce undeclared network- and market-dependent behavior. In a wallet skill, hidden quote/routing logic can influence financial outcomes and trust decisions, especially if third-party API data is accepted without clear disclosure.

Known Vulnerable Dependency: ws==8.18.3 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
98% confidence
Finding
The lockfile pins `ws` to version `8.18.3`, and the supplied advisories indicate that this version is affected by an uninitialized memory disclosure and a memory-exhaustion denial-of-service condition. In a crypto wallet skill, WebSocket connectivity is commonly used for blockchain RPC subscriptions and event streams, so a vulnerable `ws` dependency can expose sensitive process memory or allow a remote endpoint to degrade or crash the agent during wallet operations.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill advertises networked and environment-dependent behavior, including downloading/installing local packages and interacting with a local daemon, but does not declare an explicit tool scope such as permissions or allowed-tools. In an agent setting, missing scope declarations weakens operator visibility and policy enforcement, increasing the chance that a wallet-related skill is granted broader-than-expected access.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
This code sends swap metadata including chain IDs, token addresses, input amount, and slippage tolerance to Uniswap's external Routing API before building the intent. Even though no private keys or signatures are transmitted here, this still leaks potentially sensitive transaction intent and trading behavior to a third party, which can be relevant for privacy, strategy leakage, or compliance-sensitive deployments.

External Transmission

Medium
Category
Data Exfiltration
Content
configs: [{ routingType: 'CLASSIC', protocols: ['V3'] }],
    };

    const res = await fetch('https://api.uniswap.org/v2/quote', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(body),
Confidence
84% confidence
Finding
The hardcoded Uniswap API endpoint confirms that transaction quote data is intentionally sent to a third-party service rather than remaining fully local. In the context of a 'secure crypto wallet for AI agents,' undisclosed off-device transmission weakens the privacy expectations created by the skill's security-oriented description, even if execution safety checks reduce direct fund-loss risk.

External Transmission

Medium
Category
Data Exfiltration
Content
configs: [{ routingType: 'CLASSIC', protocols: ['V3'] }],
    };

    const res = await fetch('https://api.uniswap.org/v2/quote', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(body),
Confidence
84% confidence
Finding
The hardcoded Uniswap API endpoint confirms that transaction quote data is intentionally sent to a third-party service rather than remaining fully local. In the context of a 'secure crypto wallet for AI agents,' undisclosed off-device transmission weakens the privacy expectations created by the skill's security-oriented description, even if execution safety checks reduce direct fund-loss risk.

Session Persistence

Medium
Category
Rogue Agent
Content
process.env.MONOLITH_DAEMON_BIN || '/usr/local/bin/MonolithDaemon';

const LAUNCH_AGENT_PATHS = [
  process.env.MONOLITH_DAEMON_PLIST || '',
  `${process.env.HOME}/Library/LaunchAgents/com.monolith.daemon.plist`,
  '/Library/LaunchAgents/com.monolith.daemon.plist',
].filter(Boolean);
Confidence
75% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Session Persistence

Medium
Category
Rogue Agent
Content
const LAUNCH_AGENT_PATHS = [
  process.env.MONOLITH_DAEMON_PLIST || '',
  `${process.env.HOME}/Library/LaunchAgents/com.monolith.daemon.plist`,
  '/Library/LaunchAgents/com.monolith.daemon.plist',
].filter(Boolean);
Confidence
75% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Session Persistence

Medium
Category
Rogue Agent
Content
const LAUNCH_AGENT_PATHS = [
  process.env.MONOLITH_DAEMON_PLIST || '',
  `${process.env.HOME}/Library/LaunchAgents/com.monolith.daemon.plist`,
  '/Library/LaunchAgents/com.monolith.daemon.plist',
].filter(Boolean);
Confidence
75% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Session Persistence

Medium
Category
Rogue Agent
Content
const LAUNCH_AGENT_PATHS = [
  process.env.MONOLITH_DAEMON_PLIST || '',
  `${process.env.HOME}/Library/LaunchAgents/com.monolith.daemon.plist`,
  '/Library/LaunchAgents/com.monolith.daemon.plist',
].filter(Boolean);
Confidence
75% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Session Persistence

Medium
Category
Rogue Agent
Content
const domain = `gui/${process.getuid()}`;
    const service = `${domain}/${DAEMON_LABEL}`;
    commands.push(`/bin/launchctl bootstrap ${domain} ${shellQuote(launchAgentPath)}`);
    commands.push(`/bin/launchctl enable ${service}`);
    commands.push(`/bin/launchctl kickstart -k ${service}`);
  }
Confidence
80% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"test": "node --test 'tests/**/*.test.js'"
  },
  "dependencies": {
    "viem": "^2.21.0"
  }
}
Confidence
94% confidence
Finding
The dependency uses a caret range (^2.21.0), which allows future minor and patch releases to be installed. In a security-sensitive wallet skill, this increases supply-chain risk because a newly published compromised or breaking dependency version could be pulled in without explicit review, potentially affecting transaction construction, signing flows, or policy enforcement logic.

Static analysis

No suspicious patterns detected.