Back to skill

Security audit

Fetch Url

Security checks for vulnerabilities and agentic risk

Overview

This skill is a user-directed URL fetcher, but it can make unrestricted network requests with caller-supplied headers, which deserves review before installation.

Install only if you are comfortable giving the agent a broad raw network fetch tool. Avoid sending Authorization, Cookie, API keys, session tokens, or internal routing headers through it, and avoid using it on localhost, private-network, cloud metadata, or untrusted redirecting URLs unless that access is explicitly intended.

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
scripts/fetch.mjs:59
Finding

Unrestricted URL Fetching Enables Server-Side Request Forgery

Content
View full analysis

Vulnerability Details

File Location: scripts/fetch.mjs, lines 59–81
Vulnerability Type: Server-Side Request Forgery (SSRF)
Risk Level: High

Vulnerable Code

js
// Validate URLs
for (const url of urls) {
  try {
    new URL(url);
  } catch {
    console.error(`Invalid URL: ${url}`);
    process.exit(1);
  }
}

async function fetchUrl(url, customHeaders = {}) {
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), timeout);

  try {
    const resp = await fetch(url, {
      headers: {
        "User-Agent": new UserAgent().toString(),
        ...customHeaders,
      },
      signal: controller.signal,
    });

Technical Analysis

The script accepts user-controlled URLs and verifies only that each value can be parsed by the JavaScript URL constructor. This is syntactic validation and does not establish whether the destination is safe.

There are no controls preventing requests to loopback, private, link-local, multicast, or other reserved network ranges. The code also does not constrain the allowed protocols, resolve and validate hostnames before connecting, reject embedded credentials, or validate redirect destinations.

Node.js fetch follows HTTP redirects by default. Therefore, even if validation of the initial hostname were later introduced, an attacker-controlled public endpoint could redirect the request to an internal address unless every redirect target is separately validated.

The caller can also supply arbitrary request headers. This can increase the impact against internal services that rely on special headers, bearer tokens supplied by the caller, virtual-host routing, or other header-based access controls.

Attack Path

  1. An attacker causes the skill to be invoked with a URL targeting an internal resource, such as http://127.0.0.1:<port>/, a private-network host, or a link-local cloud metadat ...[truncated 1638 chars]
Remediation
View remediation

Remediation Suggestions

  1. Permit only explicitly required protocols, normally https: and, only where necessary, http:. Reject all other URL schemes.
  2. Reject URLs containing embedded usernames or passwords.
  3. Prefer an explicit allowlist of approved domains and ports when the expected destinations are known.
  4. Resolve destination hostnames before connecting and reject every loopback, private, link-local, multicast, unspecified, documentation, and reserved IPv4 or IPv6 address.
  5. Protect against DNS rebinding by ensuring the validated address is the address used for the connection, or by enforcing equivalent destination controls at the network layer.
  6. Disable automatic redirects with redirect: "manual" or validate the scheme, hostname, port, and resolved address of every redirect target before following it.
  7. Apply the same validation to every URL in a multi-URL request.
  8. Restrict caller-controlled headers to a small allowlist. Explicitly reject sensitive or routing-relevant headers unless they are required, including Authorization, Cookie, Host, forwarding headers, and proxy-related headers.
  9. Enforce egress firewall or proxy rules that block access to localhost, private networks, and cloud metadata ranges as defense in depth.
  10. Add automated tests covering direct private addresses, IPv6 loopback and private ranges, alternative IP representations, hostname resolution to private addresses, DNS rebinding scenarios, and public-to-private redirects.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (10)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill explicitly supports arbitrary URL fetching and custom headers, but its documentation does not warn that using it will contact external hosts and may transmit caller-supplied header values to those hosts. In an agent setting, this can enable unintended data egress, SSRF-style access attempts, or leakage of tokens/cookies if users or upstream components pass sensitive headers through the interface.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
81% confidence
Finding

This usage example documents support for arbitrary destinations plus caller-controlled custom headers, which increases the risk of sending sensitive header content to untrusted hosts. In an agent environment, this makes the capability more dangerous than a simple fixed-endpoint fetcher because it can be used for data exfiltration or to probe internal/external services with crafted requests.

Content

Scanner excerpt · SKILL.md (reported line 18)May include surrounding context.

md
node {baseDir}/scripts/fetch.mjs "https://api.example.com/data"

# Multiple URLs
node {baseDir}/scripts/fetch.mjs '["https://api.example.com/data1", "https://api.example.com/data2"]'

# With custom headers (per-URL)
node {baseDir}/scripts/fetch.mjs '["https://api.example.com/json", "https://api.example.com/text"]' '[{"accept":"application/json"}, {"accept":"text/plain"}]'

External Transmission

Medium
Category
Data Exfiltration
Confidence
76% confidence
Finding

This example shows setting a custom User-Agent header when calling an external API, reinforcing that arbitrary headers can be attached to outbound requests. While harmless in the example, the documented capability can be misused to transmit sensitive values or impersonate clients/services when driven by untrusted input.

Content

Scanner excerpt · SKILL.md (reported line 32)May include surrounding context.

JSON API

bash
# GitHub API - get repository info
node {baseDir}/scripts/fetch.mjs "https://api.github.com/repos/microsoft/vscode" '{"accept":"application/json","user-agent":"Mozilla/5.0"}'

XML

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 15)May include surrounding context.

md
function usage() {
  console.error(`Usage: fetch.mjs <urls_json> [headers_json] [--timeout 30000]`);
  console.error(`  urls_json: JSON array of URLs, e.g. '["https://api.example.com/data"]'`);
  console.error(`  headers_json: Optional JSON array of headers objects (same length as urls)`);
  console.error(`    e.g. '[{"accept":"application/json"}, {"accept":"text/plain"}]'`);
  process.exit(2);

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 21)May include surrounding context.

md
function usage() {
  console.error(`Usage: fetch.mjs <urls_json> [headers_json] [--timeout 30000]`);
  console.error(`  urls_json: JSON array of URLs, e.g. '["https://api.example.com/data"]'`);
  console.error(`  headers_json: Optional JSON array of headers objects (same length as urls)`);
  console.error(`    e.g. '[{"accept":"application/json"}, {"accept":"text/plain"}]'`);
  process.exit(2);

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 24)May include surrounding context.

md
function usage() {
  console.error(`Usage: fetch.mjs <urls_json> [headers_json] [--timeout 30000]`);
  console.error(`  urls_json: JSON array of URLs, e.g. '["https://api.example.com/data"]'`);
  console.error(`  headers_json: Optional JSON array of headers objects (same length as urls)`);
  console.error(`    e.g. '[{"accept":"application/json"}, {"accept":"text/plain"}]'`);
  process.exit(2);

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 38)May include surrounding context.

md
function usage() {
  console.error(`Usage: fetch.mjs <urls_json> [headers_json] [--timeout 30000]`);
  console.error(`  urls_json: JSON array of URLs, e.g. '["https://api.example.com/data"]'`);
  console.error(`  headers_json: Optional JSON array of headers objects (same length as urls)`);
  console.error(`    e.g. '[{"accept":"application/json"}, {"accept":"text/plain"}]'`);
  process.exit(2);

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 65)May include surrounding context.

md
function usage() {
  console.error(`Usage: fetch.mjs <urls_json> [headers_json] [--timeout 30000]`);
  console.error(`  urls_json: JSON array of URLs, e.g. '["https://api.example.com/data"]'`);
  console.error(`  headers_json: Optional JSON array of headers objects (same length as urls)`);
  console.error(`    e.g. '[{"accept":"application/json"}, {"accept":"text/plain"}]'`);
  process.exit(2);

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/fetch.mjs (reported line 9)May include surrounding context.

js
function usage() {
  console.error(`Usage: fetch.mjs <urls_json> [headers_json] [--timeout 30000]`);
  console.error(`  urls_json: JSON array of URLs, e.g. '["https://api.example.com/data"]'`);
  console.error(`  headers_json: Optional JSON array of headers objects (same length as urls)`);
  console.error(`    e.g. '[{"accept":"application/json"}, {"accept":"text/plain"}]'`);
  process.exit(2);

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency is specified with a caret range (^1.0.710), which allows future non-breaking releases to be installed automatically. This creates supply-chain risk because a newly published upstream version could introduce malicious code or a breaking security change without this package being explicitly reviewed or pinned.

Content

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

json
"version": "1.0.0",
  "type": "module",
  "dependencies": {
    "user-agents": "^1.0.710"
  }
}

Static analysis

No suspicious patterns detected.