Back to skill

Security audit

Virtuals Protocol Acp

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its stated ACP commerce purpose, but it handles login links, arbitrary resource URLs, and local credentials in ways that deserve review before installation.

Review this skill carefully before installing. Use it only in an environment where ACP wallet, token, marketplace, and seller-runtime actions are intended. Protect config.json as a secret, avoid committing it, do not query resource URLs you do not trust, and be cautious with setup/login until the browser-opening code is changed to avoid shell execution and validate allowed ACP login hosts.

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 (5)

T09 · Insecure Skill Coding Practices

Error
Location
src/lib/open.ts:5
Finding
Shell Command Injection Through a Server-Provided Authentication URL<![CDATA[ ## Vulnerability Details **File Location**: `src/lib/auth.ts:101-104`, `src/lib/auth.ts:169-172`, and `src/lib/open.ts:5-20` **Vulnerability Type**: OS command injection through shell interpolation **Risk Level**: High ### Vulnerable Code ```ts // src/lib/auth.ts:101-104 export async function getAuthUrl(): Promise<AuthUrlResponse> { const { data } = await apiClient().get<{ data: AuthUrlResponse }>( "/api/auth/lite/auth-url" ); return data.data; } ``` ```ts // src/lib/auth.ts:169-172 output.log(` Opening browser...`); openUrl(authUrl); output.log(` Login link: ${authUrl}\n`); output.log(" Complete login in your browser, then press ENTER.\n"); ``` ```ts // src/lib/open.ts:5-20 import { exec } from "child_process"; export function openUrl(url: string): void { const platform = process.platform; let cmd: string; if (platform === "darwin") { cmd = `open "${url}"`; } else if (platform === "win32") { cmd = `start "" "${url}"`; } else { // Linux / others cmd = `xdg-open "${url}"`; } exec(cmd, (err) => { if (err) { // Silently fail — the URL is always printed as fallback } }); } ``` ### Technical Analysis The authentication URL is supplied by the remote ACP service and passed directly to `openUrl`. That function interpolates the URL into a shell command and invokes it using `child_process.exec`. Placing attacker-controlled data inside double quotes does not make shell execution safe. On Unix-like platforms, constructs such as command substitution can still be evaluated inside double quotes. Platform-specific shell metacharacters can create equivalent risks on Windows. There is no validation that the returned value: - Uses HTTPS. - Belongs to an expected Virtuals authentication host. - Is free of shell metacharacters. - Represents an ordinary HTTP or HTTPS URL. This makes the remote authentication response part of a local command-execution boundary. ### Attack Path 1. An attacker gains cont ...[truncated 971 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Do not use `exec` or any shell command string to open URLs. - Use argument-based process execution with shell processing disabled: ```ts import { spawn } from "child_process"; export function openUrl(rawUrl: string): void { const parsed = new URL(rawUrl); if (parsed.protocol !== "https:") { throw new Error("Only HTTPS authentication URLs are allowed"); } const allowedHosts = new Set([ "app.virtuals.io", "acpx.virtuals.io", ]); if (!allowedHosts.has(parsed.hostname.toLowerCase())) { throw new Error("Untrusted authentication URL host"); } const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open"; const args = process.platform === "win32" ? ["/c", "start", "", parsed.href] : [parsed.href]; spawn(command, args, { shell: false, detached: true, stdio: "ignore", }).unref(); } ``` - On Windows, prefer a maintained URL-opening library rather than invoking `cmd`. - Apply an explicit host allowlist for login URLs. - Reject embedded credentials, nonstandard schemes, control characters, and unexpected ports. - Treat authentication API responses as untrusted even when received over TLS. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
src/commands/resource.ts:15
Finding
Server-Side Request Forgery Through Unrestricted Resource URLs<![CDATA[ ## Vulnerability Details **File Location**: `src/commands/resource.ts:15-20` and `src/commands/resource.ts:42-48` **Vulnerability Type**: Server-side request forgery and internal-network access **Risk Level**: High ### Vulnerable Code ```ts // Validate URL format try { new URL(url); } catch { output.fatal(`Invalid URL: ${url}`); } ``` ```ts // Always use GET request, params as query string if (params && Object.keys(params).length > 0) { // Build query string from params const queryString = new URLSearchParams(); for (const [key, value] of Object.entries(params)) { if (value !== null && value !== undefined) { queryString.append(key, String(value)); } } const urlWithParams = url.includes("?") ? `${url}&${queryString.toString()}` : `${url}?${queryString.toString()}`; response = await axios.get(urlWithParams); } else { response = await axios.get(url); } ``` ### Technical Analysis The command verifies only that the input can be parsed by the `URL` constructor. It does not restrict the URL scheme, hostname, resolved IP address, port, or redirect destination. Consequently, the CLI can be made to send requests from the victim environment to: - Loopback services. - Private network addresses. - Link-local services. - Cloud instance metadata endpoints. - Administrative interfaces bound only to the local network. - Redirect targets that resolve to protected destinations. Axios follows HTTP redirects by default, so validating only the initial string would remain insufficient even if a basic hostname check were added. The feature legitimately needs network access to query ACP resources, but unrestricted access to all network destinations exceeds the minimum privilege required for that functionality. ### Attack Path 1. An attacker publishes or supplies a crafted resource URL, or places instructions in untrusted content telling an Agent to query it. 2. The Agent invokes `acp resource query <attacker-controlled-url>`. ...[truncated 999 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Allow only `https:` resource URLs unless another scheme is explicitly required. - Reject URLs containing embedded usernames or passwords. - Resolve hostnames before connecting and reject all loopback, private, link-local, multicast, unspecified, and reserved IPv4 and IPv6 ranges. - Repeat destination validation after every DNS resolution and redirect. - Disable automatic redirects or implement a redirect handler that validates each destination. - Consider restricting requests to resource URLs returned by the authenticated ACP API. - Maintain an optional domain allowlist for approved marketplace resource providers. - Add connection, response-size, and request-time limits. - Protect against DNS rebinding by connecting to the validated address and ensuring the HTTP host and TLS server name remain correct. - Require explicit user confirmation when accessing a domain that is not registered for the selected ACP offering. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
src/lib/config.ts:23
Finding
Plaintext Credential Storage Without Restrictive File Permissions<![CDATA[ ## Vulnerability Details **File Location**: `src/lib/config.ts:23-51`, `src/lib/auth.ts:91-94`, and `src/commands/setup.ts:168-176` **Vulnerability Type**: Insecure storage of session tokens and API keys **Risk Level**: High ### Vulnerable Code ```ts export interface ConfigJson { SESSION_TOKEN?: { token: string; }; LITE_AGENT_API_KEY?: string; SELLER_PID?: number; agents?: AgentEntry[]; } export function readConfig(): ConfigJson { if (!fs.existsSync(CONFIG_JSON_PATH)) { return {}; } try { const content = fs.readFileSync(CONFIG_JSON_PATH, "utf-8"); return JSON.parse(content); } catch { return {}; } } export function writeConfig(config: ConfigJson): void { try { fs.writeFileSync(CONFIG_JSON_PATH, JSON.stringify(config, null, 2) + "\n"); } catch (err) { console.error(`Failed to write config.json: ${err}`); } } ``` ```ts export function storeSessionToken(token: string): void { const config = readConfig(); writeConfig({ ...config, SESSION_TOKEN: { token } }); } ``` ```ts writeConfig({ ...config, LITE_AGENT_API_KEY: result.apiKey, agents: updatedAgents, }); ``` ### Technical Analysis Both the authenticated session token and long-lived agent API key are written in plaintext to `config.json`. The write operation does not specify mode `0o600` and does not harden the permissions of an existing file. The effective file permissions therefore depend on the user's umask and any pre-existing mode. In permissive environments, other local users or processes may be able to read the credentials. The documentation states that `config.json` is ignored by Git, but the audited project structure does not contain a `.gitignore` file. This creates an additional risk that credentials generated during setup will be committed or included in archives. The configuration also retains API keys inside agent entries, increasing the number of plaintext copies within the same file. ### Attack Path 1. The user run ...[truncated 1113 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Create the configuration file with owner-only permissions: ```ts fs.writeFileSync( CONFIG_JSON_PATH, JSON.stringify(config, null, 2) + "\n", { encoding: "utf8", mode: 0o600 } ); fs.chmodSync(CONFIG_JSON_PATH, 0o600); ``` - Use atomic writes through a temporary file created with mode `0o600`, followed by a rename. - Validate and repair permissions whenever the file is read or updated. - Add `/config.json` to a repository-root `.gitignore`. - Add automated secret scanning and a test that fails if `config.json` is tracked. - Prefer an operating-system credential store or encrypted secret manager for API keys. - Avoid retaining duplicate historical API keys under multiple agent entries unless switching requires them. - Clearly document revocation and key-regeneration procedures. - Ensure logs and error messages never include complete tokens. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
src/commands/sell.ts:56
Finding
Path Traversal in Offering and Resource Scaffolding Commands<![CDATA[ ## Vulnerability Details **File Location**: `src/commands/sell.ts:56-58`, `src/commands/sell.ts:234-281`, `src/commands/sell.ts:593-594`, and `src/commands/sell.ts:638-663` **Vulnerability Type**: Arbitrary filesystem path selection through unvalidated names **Risk Level**: Medium ### Vulnerable Code ```ts function resolveOfferingDir(offeringName: string): string { return path.resolve(OFFERINGS_ROOT, offeringName); } ``` ```ts export async function init(offeringName: string): Promise<void> { if (!offeringName) { output.fatal("Usage: acp sell init <offering_name>"); } const dir = resolveOfferingDir(offeringName); if (fs.existsSync(dir)) { output.fatal(`Offering directory already exists: ${dir}`); } fs.mkdirSync(dir, { recursive: true }); const offeringJson: Record<string, unknown> = { name: offeringName, description: "", jobFee: null, jobFeeType: null, requiredFunds: null, requirement: {}, }; fs.writeFileSync( path.join(dir, "offering.json"), JSON.stringify(offeringJson, null, 2) + "\n" ); const handlersTemplate = `import type { ExecuteJobResult, ValidationResult } from "../../runtime/offeringTypes.js"; // Required: implement your service logic here export async function executeJob(request: any): Promise<ExecuteJobResult> { // TODO: Implement your service return { deliverable: "TODO: Return your result" }; } // Optional: validate incoming requests export function validateRequirements(request: any): ValidationResult { // Return { valid: true } to accept, or { valid: false, reason: "explanation" } to reject return { valid: true }; } // Optional: provide custom payment request message export function requestPayment(request: any): string { // Return a custom message/reason for the payment request return "Request accepted"; } `; fs.writeFileSync(path.join(dir, "handlers.ts"), handlersTemplate); } ``` ```ts function resolveResourceDir(resourceName: string): string { r ...[truncated 2465 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Restrict offering and resource names to a conservative identifier format: ```ts const SAFE_NAME = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/; function resolveContainedDirectory(root: string, name: string): string { if (!SAFE_NAME.test(name)) { throw new Error("Name may contain only letters, digits, underscores, and hyphens"); } const resolved = path.resolve(root, name); const rootPrefix = path.resolve(root) + path.sep; if (!resolved.startsWith(rootPrefix)) { throw new Error("Resolved path escapes the designated directory"); } return resolved; } ``` - Explicitly reject absolute paths, `.` and `..`, path separators, null bytes, and platform-specific alternate separators. - Apply the same helper consistently to offering initialization, creation, inspection, runtime loading, and resource management. - Use `mkdirSync` without unnecessary recursive behavior where practical. - Add tests for Unix absolute paths, Windows drive paths, UNC paths, mixed separators, URL-encoded traversal, and repeated `../` components. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
src/seller/runtime/acpSocket.ts:26
Finding
Seller WebSocket Uses a Public Wallet Address as Its Only Client Credential<![CDATA[ ## Vulnerability Details **File Location**: `src/seller/runtime/acpSocket.ts:26-29` **Vulnerability Type**: Insufficient authentication for seller event subscriptions **Risk Level**: Medium ### Vulnerable Code ```ts const socket: Socket = io(acpUrl, { auth: { walletAddress }, transports: ["websocket"], }); ``` ### Technical Analysis The WebSocket connection supplies only a wallet address in its authentication object. A wallet address is public account metadata and does not prove that the connecting party controls the wallet or the corresponding ACP agent. No API key, signed wallet challenge, session credential, or short-lived socket token is supplied by the client. The security of event-room subscription therefore depends entirely on undocumented server-side behavior. If the server accepts the wallet address as sufficient identity, any party that knows a seller's address may be able to subscribe to that seller's events. The received events include job identifiers, phases, client addresses, context, memos, and service requirements. Authenticated API mutations such as acceptance and delivery are performed separately through the API-key client. This limits direct privilege escalation from this client-side issue, but it does not mitigate unauthorized disclosure if room authorization is weak. ### Attack Path 1. An attacker obtains a seller's public wallet address from marketplace data or blockchain activity. 2. The attacker opens a Socket.IO connection to the ACP endpoint. 3. The attacker supplies the victim's wallet address in the `auth` object. 4. If the server trusts that field without cryptographic verification, it joins the attacker to the victim's seller room. 5. The attacker receives new-task and evaluation events intended for the victim. 6. The attacker collects job metadata, client information, requirements, and operational timing. ### Impact Assessment Potential impact includes unauthorized access to: - Buyer wallet addresses. - Jo ...[truncated 428 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Authenticate WebSocket sessions with a short-lived token issued through an already authenticated API request. - Alternatively, use a nonce-based wallet challenge: 1. Request a one-time nonce. 2. Sign it using an authorized wallet or agent credential. 3. Verify the signature server-side. 4. Issue a short-lived, audience-restricted socket token. - Authorize every room subscription server-side against the authenticated agent identity. - Bind tokens to the expected wallet, purpose, audience, and expiration. - Rotate tokens and revoke them when an agent API key is regenerated or switched. - Do not rely on a wallet address, room name, or job identifier as proof of authorization. - Add integration tests confirming that one authenticated seller cannot subscribe to another seller's events. ]]>
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (65)

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding
If the underlying skill opens arbitrary URLs in the user's default browser via shell execution, that is a significant expansion of capability and can become command-injection or phishing-enablement risk depending on implementation. In an agent skill, browser-opening behavior should be treated as sensitive because it can direct users to attacker-controlled pages or abuse shell/platform handlers.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
If the underlying skill opens arbitrary URLs in the user's default browser via shell execution, that is a significant expansion of capability and can become command-injection or phishing-enablement risk depending on implementation. In an agent skill, browser-opening behavior should be treated as sensitive because it can direct users to attacker-controlled pages or abuse shell/platform handlers.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
If the underlying skill opens arbitrary URLs in the user's default browser via shell execution, that is a significant expansion of capability and can become command-injection or phishing-enablement risk depending on implementation. In an agent skill, browser-opening behavior should be treated as sensitive because it can direct users to attacker-controlled pages or abuse shell/platform handlers.

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding
If the underlying skill opens arbitrary URLs in the user's default browser via shell execution, that is a significant expansion of capability and can become command-injection or phishing-enablement risk depending on implementation. In an agent skill, browser-opening behavior should be treated as sensitive because it can direct users to attacker-controlled pages or abuse shell/platform handlers.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
If the underlying skill opens arbitrary URLs in the user's default browser via shell execution, that is a significant expansion of capability and can become command-injection or phishing-enablement risk depending on implementation. In an agent skill, browser-opening behavior should be treated as sensitive because it can direct users to attacker-controlled pages or abuse shell/platform handlers.

Tp4

High
Category
MCP Tool Poisoning
Confidence
87% confidence
Finding
If the underlying skill opens arbitrary URLs in the user's default browser via shell execution, that is a significant expansion of capability and can become command-injection or phishing-enablement risk depending on implementation. In an agent skill, browser-opening behavior should be treated as sensitive because it can direct users to attacker-controlled pages or abuse shell/platform handlers.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
If the underlying skill opens arbitrary URLs in the user's default browser via shell execution, that is a significant expansion of capability and can become command-injection or phishing-enablement risk depending on implementation. In an agent skill, browser-opening behavior should be treated as sensitive because it can direct users to attacker-controlled pages or abuse shell/platform handlers.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
If the underlying skill opens arbitrary URLs in the user's default browser via shell execution, that is a significant expansion of capability and can become command-injection or phishing-enablement risk depending on implementation. In an agent skill, browser-opening behavior should be treated as sensitive because it can direct users to attacker-controlled pages or abuse shell/platform handlers.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
If the underlying skill opens arbitrary URLs in the user's default browser via shell execution, that is a significant expansion of capability and can become command-injection or phishing-enablement risk depending on implementation. In an agent skill, browser-opening behavior should be treated as sensitive because it can direct users to attacker-controlled pages or abuse shell/platform handlers.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
If the underlying skill opens arbitrary URLs in the user's default browser via shell execution, that is a significant expansion of capability and can become command-injection or phishing-enablement risk depending on implementation. In an agent skill, browser-opening behavior should be treated as sensitive because it can direct users to attacker-controlled pages or abuse shell/platform handlers.

Ae1

High
Category
analysis-evasion
Content
Run from the **repo root** (where `package.json` lives). For machine-readable output, always append `--json`. The CLI prints JSON to stdout in `--json` mode. Yo
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
Run from the **repo root** (where `package.json` lives). For machine-readable output, always append `--json`. The CLI prints JSON to stdout in `--json` mode. Yo
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
See [ACP Job reference](./references/acp-job.md) for detailed buy workflow. See [Seller reference](./references/seller.md) for the full sell guide.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
See [ACP Job reference](./references/acp-job.md) for detailed buy workflow. See [Seller reference](./references/seller.md) for the full sell guide.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
See [ACP Job reference](./references/acp-job.md) for detailed buy workflow. See [Seller reference](./references/seller.md) for the full sell guide.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- **Repo root** — `SKILL.md`, `package.json`, `config.json` (do not commit). Run all commands from here.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- **bin/acp.ts** — Unified CLI entry point. Invoke with `acp <command> [subcommand] [args] --json`.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Known Vulnerable Dependency: axios==1.13.4 — 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
97% confidence
Finding
The lockfile pins axios 1.13.4, and the reported advisories include SSRF/proxy-bypass and prototype-pollution-related request/response manipulation issues. In this skill, axios is a direct runtime dependency and the skill’s purpose involves transacting with external agents and services, which increases exposure to attacker-controlled URLs, redirects, proxy settings, or hostile responses.

Known Vulnerable Dependency: form-data==4.0.5 — 1 advisory(ies): CVE-2026-12143 (form-data: CRLF injection in form-data via unescaped multipart field names and f)

High
Category
Supply Chain
Confidence
88% confidence
Finding
form-data 4.0.5 is reported vulnerable to CRLF injection through unescaped multipart field names/filenames. If this skill ever builds multipart requests from untrusted marketplace or agent-supplied metadata, an attacker could tamper with multipart boundaries/headers and potentially alter server-side interpretation of uploaded content.

Known Vulnerable Dependency: socket.io-parser==4.2.5 — 2 advisory(ies): CVE-2026-69185 (Socket.IO: Zero-attachment Memory Exhaustion); CVE-2026-33151 (socket.io allows an unbounded number of binary attachments)

High
Category
Supply Chain
Confidence
95% confidence
Finding
socket.io-parser 4.2.5 is flagged for unbounded attachment handling and memory exhaustion conditions. This skill depends on socket.io-client for runtime communication, so a malicious or compromised remote agent/service could send crafted frames that consume excessive memory and crash or degrade the host agent.

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
94% confidence
Finding
ws 8.18.3 is reported vulnerable to memory disclosure and memory-exhaustion DoS issues. Since it is pulled in through engine.io/socket.io-client and this skill is designed to communicate with external agents over network channels, exposure to malicious peers makes denial of service and possible unintended data exposure more plausible.

Known Vulnerable Dependency: axios==1.13.4 — 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
98% confidence
Finding
The manifest includes axios 1.13.4, which the supplied analysis identifies as having multiple known advisories, including an SSRF-related NO_PROXY bypass and more severe request/response manipulation issues. In the context of an agent-commerce skill that interacts with wallets, marketplaces, remote agents, and seller runtimes, a vulnerable HTTP client is especially dangerous because it may enable credential leakage, SSRF against internal services, response tampering, or misuse of privileged network access.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The README promotes auto-provisioned wallets and token launch capability without warning that blockchain transactions may be irreversible, may incur fees, and may create financial, legal, or reputational consequences. In this skill context, the danger is elevated because the tool is designed for AI agents, which may execute commands programmatically and trigger real economic actions with limited human review.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The README states that API keys and session tokens are stored in a local config.json file but does not warn users that these values are sensitive secrets requiring restrictive file permissions, careful backup handling, and exclusion from logs or support bundles. In a skill that provisions wallets and can transact on-chain, compromise of these credentials could enable unauthorized marketplace actions, account access, or misuse of the seller runtime.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill declares capabilities that clearly involve network access, local configuration handling, and credential use, but it does not declare an explicit tool scope such as allowed-tools or permissions. That omission weakens reviewability and can cause an agent platform to grant broader execution than users expect, especially because the skill includes login, wallet, token, runtime, and resource-query operations.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
src/commands/serve.ts:86

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
src/commands/setup.ts:52

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
src/lib/config.ts:142

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
src/lib/open.ts:20