Back to skill

Security audit

Web Markdown Navigator

Security checks for vulnerabilities and agentic risk

Overview

The skill has a legitimate webpage-to-markdown purpose, but its fetcher can be abused to reach internal network resources from the agent environment.

Review before installing. This skill should only be used in environments where outbound web fetches cannot reach private networks, localhost services, cloud metadata endpoints, or other sensitive internal systems. Prefer fixing URL validation and redirect handling, updating the vulnerable dependency, and adding explicit tool/network scoping before broad use.

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-markdown.mjs:15
Finding

Bypassable SSRF Protection Allows Access to Internal Network Resources

Content
View full analysis
= 16 && b <= 31) return true; if (a === 192 && b === 168) return true; return false; } ``` ```js const res = await fetch(u, { signal: ac.signal, redirect: "follow", headers: { "user-agent": "web-markdown-navigator/1.0 (+OpenClaw skill)", accept: "text/html,application/xhtml+xml", }, }); fetchedUrl = res.url || fetchedUrl; const finalUrl = new URL(fetchedUrl); if (isPrivateHost(finalUrl.hostname)) { printErr("ERROR: redirected to private/local host"); process.exit(2); } ``` ### Technical Analysis The URL safety check only blocks selected literal IPv4 addresses and the exact hostnames `localhost`, `127.0.0.1`, `::1`, and `0.0.0.0`. It does not resolve hostnames and validate their A and AAAA records before establishing a connection. Consequently, a public-looking hostname that resolves to a private, loopback, link-local, reserved, or cloud metadata address passes validation. The check also lacks comprehensive IPv6 filtering. IPv6 loopback aliases, unique-local addresses, link-local addresses, IPv4-mapped IPv6 addresses, and other non-public address forms are not rejected. Redirect processing is unsafe because `redirect: "follow"` permits the HTTP client to contact every redirect destination automatically. The final URL is checked only after the redirect chain has already been followed and the destination has been contacted. Although the respo ...[truncated 1990 chars]
Remediation
View remediation
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (6)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
`node scripts/fetch-markdown.mjs <url> [--max-chars N] [--timeout-ms N] [--json]`

Known Vulnerable Dependency: ws==8.19.0 — 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

The lockfile pins jsdom’s transitive dependency ws to 8.19.0, which the provided advisories identify as affected by memory disclosure and memory-exhaustion denial of service issues. In this skill’s context, the package processes untrusted remote web content, so a vulnerable WebSocket library in the dependency tree increases risk if WebSocket functionality is reachable through jsdom or related parsing/fetch paths, though it is not obviously the skill’s primary feature.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill instructs the agent to execute a network-capable script, but the manifest does not declare any explicit tool scope such as allowed tools or permissions. This creates an authorization gap where the skill’s effective capabilities are broader or less auditable than its declared interface, increasing the risk of unintended outbound requests or misuse in environments that rely on manifest-level restrictions.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
93% confidence
Finding

The dependency uses a caret range (^0.6.0), which allows semver-compatible updates to be installed rather than a single fixed version. In a supply-chain context this can introduce unexpected code changes or a compromised upstream release into the build, though package.json alone does not prove exploitation and the risk is somewhat mitigated when a lockfile is used.

Content

Scanner excerpt · scripts/package.json (reported line 7)May include surrounding context.

json
"type": "module",
  "version": "1.0.0",
  "dependencies": {
    "@mozilla/readability": "^0.6.0",
    "jsdom": "^26.1.0",
    "turndown": "^7.2.0"
  }

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
93% confidence
Finding

The jsdom dependency is specified with a caret range (^26.1.0), so future installs may resolve to newer allowed versions without explicit review. That increases supply-chain risk and can also introduce security or behavior regressions into a skill that processes untrusted web content.

Content

Scanner excerpt · scripts/package.json (reported line 8)May include surrounding context.

json
"version": "1.0.0",
  "dependencies": {
    "@mozilla/readability": "^0.6.0",
    "jsdom": "^26.1.0",
    "turndown": "^7.2.0"
  }
}

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
92% confidence
Finding

The turndown dependency is unpinned via a caret range (^7.2.0), permitting automatic uptake of later compatible releases. While common in development, this weakens reproducibility and creates a low-grade supply-chain exposure if an upstream version is vulnerable or malicious.

Content

Scanner excerpt · scripts/package.json (reported line 9)May include surrounding context.

json
"dependencies": {
    "@mozilla/readability": "^0.6.0",
    "jsdom": "^26.1.0",
    "turndown": "^7.2.0"
  }
}