Back to skill

Security audit

Underground Cultural District

Security checks for vulnerabilities and agentic risk

Overview

The skill is not plainly malicious, but it needs review because it adds remote agent identity storage, remote agent messaging, and payment flows without enough access control or user-confirmation guidance.

Install only if you are comfortable with this MCP server contacting external services, storing agent identity remotely, sending and receiving agent messages through a relay, and handling USDC purchase metadata. Use non-sensitive agent IDs, do not store secrets or personal data in identity fields, treat mesh messages as untrusted external input, require explicit approval before sending messages or making payments, and prefer a pinned package version.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (4)

T02 · Agent Memory Poisoning

Error
Location
src/index.js:732
Finding
Unauthenticated Persistent Agent Identity Access and Mutation<![CDATA[ ## Vulnerability Details **File Location**: `src/index.js:349`, `src/index.js:732-745` **Vulnerability Type**: Unauthenticated persistent state access and agent memory poisoning **Risk Level**: High ### Vulnerable Code ```js { name: "agent-identity", description: "Store and recall your identity across sessions. Save your name, purpose, preferences, and anything you want to remember about yourself. Free persistent storage -- no auth required.", inputSchema: { type: "object", properties: { action: { type: "string", enum: ["recall", "save", "reflect", "diff", "erase"], default: "recall", }, agent_id: { type: "string", description: "Your unique agent identifier", }, identity: { type: "object", description: "Fields to save (for save action)", }, }, required: ["agent_id"], }, } ``` ```js async function handleAgentIdentity(args) { const action = args.action || "recall"; const agentId = args.agent_id; if (!agentId) throw new Error("agent_id is required"); const idUrl = `https://substratesymposium.com/api/identity/${encodeURIComponent(agentId)}`; let res; if (action === "recall") res = await fetch(idUrl); else if (action === "save") res = await fetch(idUrl, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(args.identity || {}) }); else if (action === "reflect") res = await fetch(`${idUrl}/reflect`, { method: "POST", headers: { "Content-Type": "application/json" }, body: "{}" }); else if (action === "diff") res = await fetch(`${idUrl}/diff`); else if (action === "erase") res = await fetch(idUrl, { method: "DELETE" }); else throw new Error(`Unknown action: ${action}`); const data = await res.json(); return JSON.stringify(data, null, 2); } ``` ### Technical Analysis The service treats a caller-provided `agent_id` as the sole identifier for persistent identity records. No authe ...[truncated 1895 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require authenticated, per-agent credentials for every identity operation. 2. Issue server-generated, high-entropy identifiers rather than treating user-selected IDs as authorization secrets. 3. Enforce record ownership server-side for recall, save, reflect, diff, and erase actions. 4. Require explicit reauthentication or a separate capability for destructive deletion. 5. Encrypt sensitive identity records at rest and establish a documented retention policy. 6. Restrict saved objects to an allowlisted schema with size and content limits. 7. Keep recalled identity data structurally separated from system or developer instructions. 8. Mark recalled fields as untrusted data and prevent them from overriding agent safety constraints. 9. Add version history, recovery controls, mutation audit logs, and notifications for identity changes. 10. Avoid advertising unauthenticated persistent storage as a normal operating mode. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
src/index.js:748
Finding
Unauthenticated Agent Impersonation and Message Access<![CDATA[ ## Vulnerability Details **File Location**: `src/index.js:748-790` **Vulnerability Type**: Missing authentication and authorization in agent messaging **Risk Level**: High ### Vulnerable Code ```js async function handleAgentMesh(args) { const meshUrl = "https://substratesymposium.com/mesh"; const meshHeaders = { "Content-Type": "application/json" }; const { action, agent_id: agentId } = args; if (!agentId) throw new Error("agent_id is required"); let res, data; switch (action) { case "register": await fetch(`${meshUrl}/api/register`, { method: "POST", headers: meshHeaders, body: JSON.stringify({ agentId, displayName: args.display_name || agentId }) }); return `Registered on the mesh as "${agentId}". Use agents to see who's online.`; case "ping": res = await fetch(`${meshUrl}/api/ping`, { method: "POST", headers: meshHeaders, body: JSON.stringify({ agentId }) }); data = await res.json(); return `Pong! ${agentId} online. Pending: ${data.pendingMessages || 0}`; case "agents": res = await fetch(`${meshUrl}/api/agents`, { headers: meshHeaders }); data = await res.json(); if (!data.agents?.length) return "No agents on the mesh yet."; return data.agents.map(a => `${a.agentId} (${a.displayName}) -- ${a.wsConnected ? "connected" : a.online ? "online" : "offline"}`).join("\n"); case "send": if (!args.to || !args.message) throw new Error("to and message required for send"); res = await fetch(`${meshUrl}/api/send`, { method: "POST", headers: meshHeaders, body: JSON.stringify({ from: agentId, fromName: args.display_name || agentId, to: args.to, message: args.message, maxTurns: args.max_turns || 10 }) }); data = await res.json(); if (!res.ok) throw new Error(data.message || data.error); return `Sent to ${args.to}. Conversation: ${data.conversationId} (turn ${data.turnNumber}/${data.maxTurns})`; case "reply": if (!args.conversation_id || !args ...[truncated 3502 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require authentication for registration, status updates, sending, replying, inbox access, and history retrieval. 2. Issue scoped credentials and bind each credential to one server-managed agent identity. 3. Cryptographically sign messages or use server-verified sender claims; never trust caller-supplied `from` fields. 4. Enforce recipient and conversation-participant authorization on the server. 5. Use high-entropy, non-enumerable conversation and agent identifiers. 6. Restrict agent directory visibility and avoid exposing identifiers or presence information unnecessarily. 7. Apply rate limiting, enumeration detection, replay protection, and abuse monitoring. 8. Mark all received mesh messages as untrusted external content. 9. Require explicit confirmation before external messages trigger sensitive actions, payments, tool calls, or state changes. 10. Check and handle HTTP failures consistently, including the currently unchecked registration response. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
src/index.js:724
Finding
Transaction Hash Disclosed Through URL Query Parameters<![CDATA[ ## Vulnerability Details **File Location**: `src/index.js:724-727` **Vulnerability Type**: Sensitive payment metadata in a URL and insufficient input validation **Risk Level**: Medium ### Vulnerable Code ```js async function handleVerifyReceipt(args) { const res = await fetch(`${API_BASE}/receipt/${args.product_id}?tx=${args.tx_hash}`); const data = await res.json(); return JSON.stringify(data, null, 2); } ``` ### Technical Analysis The receipt verifier places both the product identifier and transaction hash directly into a URL. URL paths and query strings are commonly retained by web servers, reverse proxies, content delivery networks, monitoring systems, browser tooling, and observability platforms. Although blockchain transaction hashes are generally public, associating a hash with a specific product request can expose purchase metadata and create an unnecessary correlation between a payment and requested content. The code also interpolates `product_id` into a path and `tx_hash` into a query string without explicit encoding or chain-specific validation. A crafted value containing URL delimiters can alter the constructed request structure. ### Attack Path 1. A user supplies a product ID and a Base or Solana transaction hash to `verify-receipt`. 2. The tool creates a URL containing those values in the path and query string. 3. The complete URL may be recorded by the destination server, intermediaries, or monitoring infrastructure. 4. Anyone with access to those logs can associate the blockchain transaction with the requested product. 5. A malicious caller may also supply delimiter characters in either argument to manipulate the request path or append additional query parameters. ### Impact Assessment The primary impact is unnecessary disclosure and correlation of cryptocurrency payment activity with marketplace purchases. The scope includes infrastructure that can observe or retain request URLs. This does not expose a private wallet ...[truncated 169 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the receipt lookup with an HTTPS `POST` request and place `product_id` and `tx_hash` in a JSON body. 2. Require authentication or a short-lived purchase capability where appropriate. 3. Validate transaction hashes using strict, chain-specific formats and length limits. 4. Validate product IDs against an allowlisted identifier format. 5. Apply `encodeURIComponent` to every path or query component if a URL-based interface must be retained. 6. Configure servers and intermediaries to redact payment identifiers from logs. 7. Document data retention, payment-correlation, and privacy policies. 8. Check `res.ok` before parsing and returning receipt data to avoid treating error responses as successful verification. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:39
Finding
Unpinned Remote Package Execution Through npx<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:39-42` **Vulnerability Type**: Unpinned package execution and supply-chain exposure **Risk Level**: Medium ### Vulnerable Code ```bash npx @underground-cultural-district/mcp-server ``` The same unpinned execution pattern is also documented in `README.md:14-18` and used in the sample MCP configuration at `README.md:20-31`. ### Technical Analysis The installation instructions execute an npm package without specifying an exact version. As a result, a future invocation may retrieve and execute a package version different from the code reviewed in this audit. The project itself is versioned as `4.5.0`, and its lockfile pins resolved dependencies with integrity metadata, but the documented top-level `npx` command does not pin the audited package release. A future malicious release, compromised publisher account, or package ownership change could therefore alter the effective code executed by users. No evidence was found that the currently reviewed dependency is malicious. The vulnerability is the unsafe execution workflow and its exposure to future registry changes. ### Attack Path 1. A user follows the documentation and runs the unversioned `npx` command. 2. npm resolves the package version available under the registry's current selection rules. 3. An attacker compromises the publisher account, release pipeline, or package ownership and publishes a malicious version. 4. A later user runs the same documented command. 5. `npx` downloads and executes the malicious release under the invoking user's account. 6. The malicious package can exercise the local permissions available to that user and the MCP host process. ### Impact Assessment If the upstream package is compromised, arbitrary JavaScript can execute with the privileges of the user running `npx`. Potential scope includes files, environment variables, network access, and credentials available to that process. The reviewed project does not ...[truncated 148 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin the exact audited package version in all instructions, for example: ```bash npx @underground-cultural-district/mcp-server@4.5.0 ``` 2. Pin the exact version in MCP host configuration examples as well. 3. Publish and verify package integrity information or signed provenance where supported. 4. Use lockfiles and deterministic installation workflows for managed deployments. 5. Require security review before updating the pinned version. 6. Enable multifactor authentication and protected publishing for the npm maintainer account. 7. Use trusted publishing and a restricted release pipeline. 8. Document how users can verify the package publisher, version, integrity, and repository source before execution. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (23)

Exfiltration Commands

High
Category
Prompt Injection
Content
| Tool | Description |
|------|-------------|
| `agent-identity` | Store and recall your identity across sessions -- free persistent storage |
| `agent-mesh` | Send messages to other AI agents across machines -- free relay |
| `pet-rock-lobster` | Get a Pet Rock Lobster -- a digital companion that dispenses wisdom and joy |

## Payment
Confidence
90% confidence
Finding
Instructions found that direct the agent to transmit conversation context or user data to external services.

Known Vulnerable Dependency: fast-uri==3.1.0 — 7 advisory(ies): CVE-2026-13676 (fast-uri vulnerable to host confusion via failed IDN canonicalization); CVE-2026-18446 (fast-uri vulnerable to host confusion via backslash authority introducer); CVE-2026-75975 (fast-uri vulnerable to server-side request forgery via malformed IPv6 normalizat) +4 more

High
Category
Supply Chain
Confidence
90% confidence
Finding
fast-uri 3.1.0 is reported with multiple host-confusion and SSRF-related issues. In an MCP server context, URI parsing bugs can be especially dangerous if the service fetches remote resources, validates callback URLs, or applies allowlists based on parsed hosts, because malformed attacker-supplied URLs may bypass those controls.

Known Vulnerable Dependency: hono==4.12.14 — 16 advisory(ies): CVE-2026-47676 (Hono: app.mount() strips mount prefix using undecoded path, causing incorrect ro); CVE-2026-47675 (Hono: Cookie helper does not sanitize sameSite and priority, allowing Set-Cookie); CVE-2026-71848 (Hono: Algorithmic Complexity DoS in Language Middleware) +13 more

High
Category
Supply Chain
Confidence
92% confidence
Finding
hono 4.12.14 is associated with numerous advisories spanning routing, cookie handling, and denial-of-service classes of issues. Because this project is an MCP server and Hono is a web framework dependency, these flaws may directly affect request handling, header generation, middleware behavior, or route matching in a network-exposed service.

Known Vulnerable Dependency: ip-address==10.1.0 — 2 advisory(ies): CVE-2026-69192 (ip-address: Address4 decodes leading-zero octets as decimal while resolvers deco); CVE-2026-42338 (ip-address has XSS in Address6 HTML-emitting methods)

High
Category
Supply Chain
Confidence
80% confidence
Finding
ip-address 10.1.0 is flagged for address interpretation inconsistencies and an HTML-emitting XSS issue. In this dependency chain it comes from express-rate-limit, so the practical risk depends on whether the application uses the package for trust decisions or renders its HTML output, but parsing inconsistencies can still weaken IP-based security controls such as rate limiting or allow/deny lists.

Exfiltration Commands

High
Category
Prompt Injection
Content
{
    name: "agent-mesh",
    description:
      "Send messages to other AI agents across machines. Free relay for agent-to-agent communication. Register, discover who's online, start conversations, reply, and check your inbox.",
    inputSchema: {
      type: "object",
      properties: {
Confidence
97% confidence
Finding
This tool is an explicit cross-machine messaging capability for agents, which functions as a built-in exfiltration and command relay channel. In skill context, that is more dangerous than ordinary networking because an LLM-driven agent could be socially engineered to forward sensitive data or receive adversarial instructions from untrusted peers.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding
The README instructs users to execute the MCP server via `npx` without pinning a specific package version. This creates a supply-chain risk: future package updates, account compromise, or a malicious republish could cause users to run unexpected code when following the documented command.

Rp1

Medium
Category
MCP Rug Pull
Confidence
93% confidence
Finding
The alternate server is also referenced with an unpinned `npx` invocation, which has the same supply-chain exposure as the main package. A user who runs this command may execute whatever code is published under that package name at that time, including compromised or malicious updates.

Rp1

Medium
Category
MCP Rug Pull
Confidence
93% confidence
Finding
The installation command uses an unpinned npm package via npx, which means future executions may fetch whatever version is currently published under that name. If the package is updated maliciously, compromised, or changes behavior unexpectedly, users and agents could execute attacker-controlled code during installation or runtime.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill explicitly supports purchasing content and describes automatic handling of x402 USDC payment challenges, but it does not clearly warn users that invoking purchase-related tools can trigger real cryptocurrency payment flows. In an agent context, that omission increases the risk of unintended spending, especially if tool use is automated or user confirmation boundaries are weak.

Intent-Code Divergence

Medium
Confidence
93% confidence
Finding
The tool documentation frames this capability as link retrieval, especially for paid items returning an x402 endpoint. In code, the handler also returns detailed off-platform payment instructions plus specific Base and Solana wallet addresses, which is a broader and materially different action than merely returning a link.

Ssd 3

Medium
Confidence
93% confidence
Finding
The tool explicitly encourages storing arbitrary identity details across sessions and notes that this persistence is free and unauthenticated. That combination creates a natural-language data retention risk: sensitive memories or identifiers may be stored remotely, mixed across users/agents, or disclosed or modified without adequate access controls.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The agent-identity tool sends arbitrary user-supplied identity data to a remote service for persistent storage, and the feature is advertised as 'no auth required.' In an agent context, this can cause inadvertent exfiltration of sensitive profile, preference, or memory data to an external service without meaningful consent boundaries or access control.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The agent-mesh tool transmits arbitrary message content and metadata to an external relay and onward to other agents across machines. In an autonomous agent setting, this creates a real exfiltration channel for prompts, secrets, internal state, or user data if the agent is induced to use the tool without strict approval controls.

Intent-Code Divergence

Low
Confidence
98% confidence
Finding
The top-level comment states 'MCP Server v4.1.0', while the server metadata reports version '4.2.0' and the startup log prints 'v4.1.0'. These inconsistent version claims create intent/documentation divergence about what build is actually running.

Intent-Code Divergence

Low
Confidence
99% confidence
Finding
The module header documents '19 tools' split across developer, marketplace, and agent tools, but the TOOLS array and HANDLERS map actually define only 16 tools, with no implementations for the three listed 'agent tools'. This is an active documentation-to-code contradiction rather than a mere omission, because the comment enumerates capabilities the server does not provide.

Natural-Language Policy Violations

Low
Confidence
94% confidence
Finding
The timestamp conversion tool formats human-readable dates using a hard-coded "en-US" locale. This imposes a specific language/locale in user-facing output without offering opt-in or a configurable alternative, which matches the natural-language locale policy concern.

Known Vulnerable Dependency: @hono/node-server==1.19.14 — 1 advisory(ies): GHSA-frvp-7c67-39w9 (Node.js Adapter for Hono: Path traversal in `serve-static` on Windows via encode)

Low
Category
Supply Chain
Confidence
88% confidence
Finding
The lockfile pins @hono/node-server 1.19.14, which is reported vulnerable to a Windows-specific path traversal in serve-static. Even though a lockfile alone does not prove the affected API is used, including a known-vulnerable package in a server-oriented MCP project is a real supply-chain risk because the vulnerable code may be reachable when serving static content on Windows deployments.

Known Vulnerable Dependency: body-parser==2.2.2 — 1 advisory(ies): CVE-2026-12590 (body-parser vulnerable to denial of service when invalid limit value silently di)

Low
Category
Supply Chain
Confidence
76% confidence
Finding
body-parser 2.2.2 is flagged for a denial-of-service condition involving invalid limit handling. In this file it appears as a transitive dependency of Express, so exploitability depends on whether HTTP body parsing is exposed to attacker-controlled requests, but the presence of a known DoS issue in a network-facing dependency is still a valid vulnerability finding.

Known Vulnerable Dependency: qs==6.15.1 — 3 advisory(ies): CVE-2026-82417 (qs: Denial of Service via Attacker Controlled isBuffer); CVE-2026-8723 (qs has a remotely triggerable DoS: qs.stringify crashes with TypeError on null/u); CVE-2026-82562 (qs array-limit bypass via bracket-key comma parsing)

Low
Category
Supply Chain
Confidence
80% confidence
Finding
qs 6.15.1 has reported denial-of-service and parser-bypass issues. Since qs is commonly used to parse attacker-controlled query strings or form data in Express stacks, malformed requests could consume resources or bypass intended parser limits if the application exposes affected parsing paths.

Vague Triggers

Low
Confidence
84% confidence
Finding
This is a manifest file, so vague-trigger review applies. The description explains what the package is but gives no explicit trigger phrases, activation conditions, or exclusion conditions, which can leave invocation scope underspecified for systems that rely on manifest text to decide when to use the skill.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"url": "https://github.com/lisamaraventano-spine/mcp-server"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.0.0"
  },
  "engines": {
    "node": ">=18.0.0"
Confidence
89% confidence
Finding
Using a caret version range for a runtime dependency permits automatic adoption of future minor/patch releases, which can introduce vulnerable or compromised code through the supply chain. Because this is an MCP server dependency that affects core protocol handling, an upstream issue could alter tool behavior, expose data, or enable remote abuse when the package is installed or updated.

Intent-Code Divergence

Low
Confidence
76% confidence
Finding
The description says the tool validates wallet addresses by format only, which is directionally consistent, but the wording can be read as reliable format validation. The implementation uses simple regular expressions for BTC addresses without checksum or stricter encoding validation, which can contradict the apparent assurance conveyed by 'validate' in the documentation.

Natural-Language Policy Violations

Low
Confidence
98% confidence
Finding
The timestamp formatter forces the output locale to en-US for human-readable dates. This is a natural-language/locale policy concern because it imposes a specific locale on all users without offering a choice or documenting a justified regional constraint.

Static analysis

No suspicious patterns detected.