Back to skill

Security audit

mcp-best-practices

Security checks across malware telemetry and agentic risk

Overview

This is a documentation-only MCP best-practices skill with some developer examples that should be reviewed before reuse, but it does not install, execute, persist, or exfiltrate anything itself.

Installers should treat this as reference material. Before copying examples into a real MCP server, pin dependency versions, use lockfiles, avoid arbitrary URL fetch tools without SSRF protections, and only expose local MCP endpoints through a tunnel after adding appropriate authentication and authorization.

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

T09 · Insecure Skill Coding Practices

Error
Location
references/error-handling.md:64
Finding
Caller-Controlled URL Fetch Enables Server-Side Request Forgery## Vulnerability Details **File Location**: `references/error-handling.md`, lines 64-81 **Vulnerability Type**: Server-Side Request Forgery (SSRF) **Risk Level**: High **Vulnerable code:** ```typescript async function fetchHandler({ url }: { url: string }) { try { const response = await fetch(url); if (!response.ok) { return { isError: true, content: [{ type: "text", text: `Upstream returned ${response.status}: ${response.statusText}. Try a different URL or check if the service is available.` }], }; } const data = await response.json(); return { content: [{ type: "text", text: JSON.stringify(data) }] }; } catch (err) { return { isError: true, content: [{ type: "text", text: `Network error fetching ${url}: ${err instanceof Error ? err.message : "unknown"}. The service may be down.` }], }; } } ``` ### Technical Analysis The example passes a caller-controlled `url` directly to `fetch()` and returns the resulting response to the caller. It does not restrict URL schemes or destinations, reject private and link-local addresses, validate redirects, protect against DNS rebinding, or limit response size. If copied into an MCP server, this creates an SSRF primitive. An attacker could request loopback addresses, private network ranges, internal administrative services, or cloud instance metadata endpoints. Redirect-based and DNS time-of-check/time-of-use techniques could bypass superficial validation added by downstream implementers. The project contains appropriate SSRF mitigation guidance elsewhere, including private-address blocking in `references/security-auth.md`, but the directly reusable example does not apply or reference those controls. ### Attack Path 1. A server author copies the example into a remotely accessible MCP tool. 2. An attacker invokes the tool with an internal URL, such as a loopback service, private network e ...[truncated 891 chars]
Remediation
## Remediation Suggestions - Prefer accepting a resource identifier rather than an arbitrary URL. - If arbitrary URLs are required, restrict schemes to HTTPS and enforce an explicit hostname or domain allowlist. - Resolve the hostname before connecting and reject loopback, private, link-local, multicast, reserved, and unspecified IPv4 and IPv6 ranges. - Pin the validated DNS result for the connection to prevent DNS rebinding and TOCTOU attacks. - Disable automatic redirects or validate every redirect target using the same scheme, hostname, and resolved-address policy. - Explicitly block cloud metadata ranges, including `169.254.0.0/16`. - Apply connection, read, and total-request timeouts. - Stream responses through a strict byte limit rather than calling `response.json()` on an unbounded body. - Restrict accepted content types and avoid returning sensitive upstream headers or verbose network errors. - Route outbound requests through a policy-enforcing egress proxy where possible. - Add tests covering loopback, private IPv4, private IPv6, encoded IP addresses, redirect-to-private-host, and DNS-rebinding cases.

T08 · Insecure Dependencies

Warning
Location
references/mcp-apps.md:208
Finding
Mutable Dependency Installation and Unpinned Package Execution## Vulnerability Details **File Location**: `references/mcp-apps.md`, lines 208-220 and 266-279 **Vulnerability Type**: Unsafe third-party dependency and tooling execution **Risk Level**: Medium **Vulnerable setup commands:** ```bash npm install @modelcontextprotocol/ext-apps @modelcontextprotocol/sdk npm install -D typescript vite vite-plugin-singlefile express cors @types/express @types/cors tsx ``` ```json { "type": "module", "scripts": { "build": "INPUT=mcp-app.html vite build", "serve": "npx tsx server.ts" } } ``` **Vulnerable testing commands:** ```bash git clone https://github.com/modelcontextprotocol/ext-apps.git cd ext-apps/examples/basic-host && npm install SERVERS='["http://localhost:3001/mcp"]' npm start # Navigate to http://localhost:8080 ``` ```bash # Terminal 1: Run your server npm run build && npm run serve # Terminal 2: Expose to internet npx cloudflared tunnel --url http://localhost:3001 ``` ### Technical Analysis The instructions install dependencies without exact versions, clone a mutable default branch, and execute command-line tools through `npx`. The artifacts executed by these commands can therefore differ from those reviewed when the Skill was published. Package installation can execute lifecycle scripts with the invoking user's privileges. An upstream account compromise, malicious package release, compromised transitive dependency, or unexpected default-branch change could consequently introduce and execute attacker-controlled code. Running `npx cloudflared` without an exact version may download and execute a package dynamically. The tunnel command also publishes the local MCP endpoint to the Internet, while the example does not explicitly require endpoint authentication or warn users to verify that the server contains no development-only privileged tools. ### Attack Path 1. A user follows the setup instructions in a developm ...[truncated 1104 chars]
Remediation
## Remediation Suggestions - Pin all direct dependencies to reviewed exact versions rather than unbounded latest releases. - Commit a lockfile and use `npm ci` for reproducible installation. - Review transitive dependencies and package lifecycle scripts before installation. - Consider initially installing with lifecycle scripts disabled, then explicitly enabling only reviewed build steps. - Replace `npx tsx` with the project-local pinned binary invoked through an npm script. - Install a verified, pinned Cloudflare Tunnel binary or exact package version rather than dynamically executing the latest resolution. - Pin the cloned repository to a reviewed commit or signed release tag, and document the expected commit hash. - Use dependency provenance, integrity verification, lockfile auditing, and automated vulnerability scanning. - Require authentication and authorization on the MCP endpoint before creating a public tunnel. - Bind development services to loopback, expose only the required port, and disable destructive or privileged tools during public testing. - Warn users that a generated tunnel URL is publicly reachable and should be revoked immediately after testing.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep

VirusTotal

64/64 vendors flagged this skill as clean.

View on VirusTotal

Static analysis

No suspicious patterns detected.