Back to skill

Security audit

Novel Scraper SPA

Security checks for vulnerabilities and agentic risk

Overview

This is a straightforward novel scraper, but it accepts unrestricted URLs that could make the host access internal or local resources and save the results locally.

Review before installing. Use it only on public novel pages you intend to scrape, avoid internal, localhost, metadata, file://, or untrusted redirected URLs, and check where output will be written before running it.

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

Warning
Location
scripts/scraper.py:45
Finding

Unrestricted URL Navigation Enables Server-Side Request Forgery and Local Resource Access

Content
View full analysis

Vulnerability Details

File Location: scripts/scraper.py:45-48, scripts/scraper.py:139-151, and scripts/browser.py:58-61
Vulnerability Type: Server-Side Request Forgery (SSRF) and unsafe URL scheme handling
Risk Level: Medium

Vulnerable Code

scripts/scraper.py:45-48:

python
if html is None:
    try:
        response = requests.get(url, timeout=10)
        html = response.text

scripts/scraper.py:139-151:

python
if use_browser:
    logger.info("Using browser (SPA detected)")
    html = get_html(url)
else:
    logger.info("Using requests (static site)")
    try:
        response = requests.get(url, timeout=30)
        response.raise_for_status()
        html = response.text
    except requests.RequestException as e:
        logger.error(f"Failed to fetch {url}: {e}")
        if detect_spa(url):
            logger.info("Retrying with browser...")
            html = get_html(url)

scripts/browser.py:58-61:

python
try:
    logger.info(f"Navigating to: {url}")
    self._page.goto(url, timeout=timeout, wait_until="networkidle")
    return True

Technical Analysis

The user-controlled --url argument is passed directly to requests.get() and Playwright's page.goto() without validation of:

  • The URL scheme
  • The hostname
  • The resolved IP address
  • Redirect destinations
  • Loopback, private, link-local, reserved, or cloud metadata address ranges

The requests path can therefore issue HTTP or HTTPS requests to services reachable from the machine running the skill, including internal network services and cloud instance metadata endpoints. Because redirects are followed by default, a public URL may also redirect to a prohibited internal destination.

The forced SPA/browser path provides a broader attack surface because Playwright can navigate schemes other than HTTP and HTTPS. In particular, a supplied file:// URL may allow the browser to load a locally accessible HTML document. If that document contains a ...[truncated 1573 chars]

Remediation
View remediation

Remediation Suggestions

  1. Parse every supplied URL using a standards-compliant URL parser and allow only http and https schemes. Explicitly reject file, data, javascript, and other schemes.
  2. Require a non-empty hostname and reject embedded credentials, malformed ports, and ambiguous host representations.
  3. Resolve the hostname before making a request and reject every resolved address that is loopback, private, link-local, multicast, reserved, or unspecified.
  4. Explicitly block cloud metadata destinations, including link-local metadata addresses and provider-specific metadata hostnames.
  5. Disable automatic redirects or validate every redirect destination using the same scheme, hostname, DNS, and IP-address controls before following it.
  6. Revalidate the actual connection destination to mitigate DNS rebinding and time-of-check/time-of-use discrepancies.
  7. Apply identical URL controls to both the requests and Playwright paths.
  8. Where operationally possible, use an explicit domain allowlist and execute the browser in a network sandbox that cannot reach internal networks or metadata services.
  9. Add automated tests covering loopback addresses, IPv6 loopback, private ranges, link-local addresses, alternative numeric IP representations, redirect-based bypasses, DNS rebinding scenarios, and prohibited schemes.
Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • 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 (4)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill advertises network access and local file output behavior via its documented command, but it declares no explicit tool scope such as permissions or allowed-tools. In an agent setting, this weakens policy boundaries and can enable unintended network fetching or filesystem writes beyond what a reviewer or user expects.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest description is entirely in Chinese and presents the skill as oriented around Chinese novel scraping, without offering a language choice or documenting a justified region-specific constraint. The policy requires flagging language or locale restrictions when a specific language is effectively imposed without user opt-in.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The SKILL.md presents concrete operational behavior under '输出', stating results are saved to ~/.openclaw/workspace/novels/. However, the rest of the file is largely unfinished template material and provides no supporting implementation or validated command behavior in this file, making the documentation materially unreliable.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill states that scraped content will be saved locally under a workspace path but does not warn the user that running it creates files on disk. In agent workflows, undisclosed local writes can surprise users, clutter workspaces, and contribute to unsafe chaining when combined with untrusted remote content.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.