Back to skill

Security audit

Webfetch Md

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to do what it claims, but it can fetch and return content from any URL reachable by the host network without safeguards, and its dependency metadata has review-worthy supply-chain issues.

Install only if you are comfortable with a tool that can make network requests from your environment to any URL it is given and return the result. Use it only for public webpages, avoid localhost/private/cloud-metadata or URLs containing secrets, and prefer a version with URL allowlisting or private-network blocking plus pinned, audited dependencies.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Error
Location
index.js:76
Finding

Unrestricted URL Fetching Enables Server-Side Request Forgery (SSRF)

Content
View full analysis

Vulnerability Details

File Location: index.js:76-86
Vulnerability Type: Server-Side Request Forgery (SSRF)
Risk Level: High

Vulnerable Code

javascript
/**
 * Fetch a webpage and convert it to Markdown.
 * @param {string} url - Target URL
 * @param {object} options - Options
 * @returns {Promise<object>} - Result object
 */
async function fetchAsMarkdown(url, options = {}) {
  try {
    // 1. Fetch webpage
    const response = await fetch(url, {
      headers: { ...DEFAULT_HEADERS, ...options.headers },
      ...options.fetchOptions
    });

The affected function is directly exposed to untrusted input by both command-line entry points:

  • cli.js:12-20,29
  • webfetch-md-tool.js:17-25

Technical Analysis

fetchAsMarkdown passes the supplied URL directly to the Node.js fetch API without validating its scheme, hostname, resolved IP address, port, or redirect destinations.

This allows callers to make HTTP requests using the network privileges of the process running the Skill. There are no controls blocking requests to:

  • Loopback addresses such as 127.0.0.1 or [::1]
  • RFC 1918 private networks
  • Link-local addresses, including cloud instance metadata services
  • Internal DNS hostnames
  • Reserved or otherwise non-public address ranges
  • Public endpoints that redirect to internal destinations

The default redirect behavior of fetch can also permit an initially public URL to redirect to a protected internal resource. Validating only the initial textual hostname would therefore be insufficient.

After the request completes, the response body is parsed and converted to Markdown. The resulting content is returned to the caller, making this a response-disclosing SSRF rather than a blind SSRF.

The exported module API additionally allows callers to supply options.headers and options.fetchOptions. In integrations where those values are influenced by an ...[truncated 1690 chars]

Remediation
View remediation

Remediation Suggestions

  1. Parse the input with new URL(url) and reject malformed URLs.
  2. Permit only explicitly required protocols, normally https: and, if necessary, http:. Reject credentials embedded in URLs and all other schemes.
  3. Resolve the hostname before connecting and reject every resolved IPv4 and IPv6 address that is loopback, private, link-local, multicast, unspecified, reserved, or otherwise non-public.
  4. Protect against DNS rebinding by ensuring the validated address is the address actually used for the connection. Consider using a controlled outbound proxy or custom dispatcher that enforces destination policy.
  5. Disable automatic redirects with redirect: "manual" and validate every redirect target using the same protocol, hostname, and resolved-address checks. Set a small maximum redirect count.
  6. Prefer an explicit hostname allowlist when the deployment has a known set of permitted sources.
  7. Add request timeouts, connection limits, and a maximum response-body size to reduce denial-of-service exposure.
  8. Restrict or remove caller-controlled headers and fetchOptions in untrusted integrations. Explicitly block sensitive forwarding headers such as Authorization, Cookie, and proxy-related headers unless required.
  9. Apply outbound firewall or sandbox rules so the Skill process cannot reach metadata endpoints, localhost services, or private networks.
  10. Add tests covering direct private addresses, IPv6 loopback, alternative numeric IP representations, internal DNS names, DNS rebinding, and public-to-private redirect chains.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (16)

Known Vulnerable Dependency: undici==7.22.0 — 16 advisory(ies): CVE-2026-1525 (Undici has an HTTP Request/Response Smuggling issue); CVE-2026-6733 (undici vulnerable to HTTP response queue poisoning via keep-alive socket reuse); CVE-2026-1527 (Undici has CRLF Injection in undici via `upgrade` option) +13 more

High
Category
Supply Chain
Confidence
95% confidence
Finding

The lockfile pins transitive dependency undici to 7.22.0, and the supplied advisory set indicates this version is affected by multiple high-severity issues including request/response smuggling, response queue poisoning, and CRLF injection. In a skill whose purpose is fetching web content, an HTTP client vulnerability is directly relevant because it processes attacker-controlled remote responses and headers, increasing the chance that malicious servers could exploit parsing or connection-reuse flaws.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill performs network access to arbitrary URLs but does not declare an explicit tool scope such as permissions or allowed-tools. In an agent environment, missing capability declarations can mislead operators about what the skill can do and reduce policy enforcement, increasing the chance of unintended outbound requests or SSRF-like usage.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The documentation encourages fetching arbitrary URLs but does not warn that doing so sends outbound requests to remote servers and may expose internal hostnames, tokens in URLs, or private infrastructure endpoints. In agent contexts, this omission makes SSRF-style misuse and accidental data disclosure more likely because users may treat the tool as a harmless local transformer rather than a network client.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

Using npx webfetch-md without pinning an exact version allows execution of whatever package version is currently published or resolved at install time. That creates a supply-chain risk where a compromised, typosquatted, or newly malicious release could run arbitrary code in the user's environment.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

This example invokes npx webfetch-md without a fixed version, which can pull and execute unreviewed code from the registry. In security-sensitive agent workflows, that materially increases supply-chain exposure because the command may run under user or automation privileges.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

The unpinned npx webfetch-md example can resolve to different code over time, enabling arbitrary code execution if the package or dependency chain is compromised. Because npx executes the downloaded package, this is more than a documentation issue when copied into real environments.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

Another floating npx webfetch-md invocation repeats the same supply-chain hazard: users may execute a future package version that has not been reviewed. Repetition in examples increases the likelihood that consumers copy insecure usage patterns into scripts or CI jobs.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The default Accept-Language header is hard-coded to prefer zh-CN and zh, which imposes a locale choice on all requests. This is a natural-language/locale policy issue because the skill does not offer the user a language choice or document a justified region-specific constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The natural-language description and instructions are presented exclusively in Chinese, and the file does not indicate that the skill is region-specific or provide an opt-in language choice. Under the stated policy, forcing a specific language without user choice can be a locale-policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The file includes the CLI description, comments, error text, and usage string in Chinese only. This can violate language/locale policy when a skill forces a specific language without user opt-in or documented justification.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

This function performs an outbound HTTP request to an arbitrary URL, which can disclose the target URL and request metadata such as headers to a remote server. Although the code has internal comments, it lacks any user-facing warning, confirmation, or logging about this network activity within the file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest description is written only in Chinese ("抓取网页并转换为 Markdown,保留图片链接"), which implies a language-specific presentation without any indication of user choice or region-specific justification. Under the policy, language constraints should be optional or clearly documented when they are intentional.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
84% confidence
Finding

Using semver ranges for dependencies can allow newer transitive or direct package versions to be installed over time, which may introduce vulnerable or malicious code through the supply chain. In a tool that fetches and processes untrusted web content, dependency compromise is somewhat more relevant because parsing libraries run on attacker-controlled input.

Content

Scanner excerpt · package.json (reported line 13)May include surrounding context.

json
"test": "node test.js"
  },
  "dependencies": {
    "turndown": "^7.1.2",
    "cheerio": "^1.0.0-rc.12"
  }
}

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The file contains multiple user-facing strings exclusively in Chinese, including the script description and all console messages. This can violate a language/locale policy when the skill forces a specific language without giving the user a choice or documenting a justified locale restriction.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The header comments and usage text are written only in Chinese, which indicates a language-specific interaction pattern without any opt-in or alternative locale. Under the policy criteria, forcing a specific language without user choice can be a natural-language policy violation unless clearly justified.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.