Back to skill

Security audit

Cn Web Screenshot

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent webpage screenshot skill, but it gives users unrestricted network fetch and file-write control without enough scoping or safety disclosure.

Install only if you are comfortable with the skill making outbound requests from the agent environment and saving screenshots to caller-selected paths. Avoid using it on internal, localhost, metadata, authenticated, or confidential URLs, and prefer running it in an isolated environment with a restricted output directory and pinned dependencies.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (3)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/web_screenshot.py:29
Finding
Unrestricted URL Access Enables Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `scripts/web_screenshot.py:29, 84-85` **Vulnerability Type**: Server-Side Request Forgery through unrestricted browser navigation **Risk Level**: High ### Vulnerable Code ```python page.goto(url, wait_until='networkidle', timeout=30000) ``` ```python # Ensure the URL has a protocol if not url.startswith('http'): url = 'https://' + url ``` ### Technical Analysis The user-provided URL is passed directly to Playwright without validating its scheme, hostname, resolved IP address, or redirect destinations. The `startswith('http')` condition is not a reliable URL parser or protocol allowlist. Consequently, the browser may navigate to loopback, private, link-local, reserved, or otherwise internal addresses reachable from the Agent host. Examples include localhost services, private administrative interfaces, and cloud instance metadata endpoints. An attacker may also provide a public URL that redirects to an internal destination because redirect targets are not revalidated. The browser renders the response and saves it as an image, allowing internal content to be disclosed through the returned screenshot. ### Attack Path 1. An attacker asks the Skill to capture a URL such as `http://127.0.0.1:8080`, an RFC 1918 private address, or a link-local metadata address. 2. Alternatively, the attacker supplies a public URL that redirects to an internal address. 3. The script forwards the unvalidated URL to `page.goto()`. 4. Chromium sends the request from the Agent host and therefore uses the host's network access. 5. The internal response is rendered and captured in a screenshot. 6. The screenshot path is returned, allowing the attacker to inspect content that was not directly reachable from their own environment. ### Impact Assessment An attacker can use the Agent host as a network vantage point for internal network reconnaissance and content disclosure. Depending on network reachability, exposed targets may i ...[truncated 320 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse the input with `urllib.parse.urlsplit()` and allow only exact `http` and `https` schemes. 2. Reject URLs containing credentials or malformed hostnames. 3. Resolve the hostname before navigation and reject every resolved address that is loopback, private, link-local, multicast, reserved, or unspecified. 4. Revalidate the destination after every redirect to prevent redirect-based SSRF and DNS rebinding bypasses. 5. Prefer an explicit hostname allowlist when the intended destinations are known. 6. Apply outbound firewall rules that prevent the browser process from reaching internal and metadata networks. 7. Consider running Chromium in a separately isolated network namespace with access only to the public internet. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/web_screenshot.py:42
Finding
Caller-Controlled Screenshot Path Permits Arbitrary File Overwrite<![CDATA[ ## Vulnerability Details **File Location**: `scripts/web_screenshot.py:36-42, 70-72` **Vulnerability Type**: Unrestricted file write and arbitrary file overwrite **Risk Level**: High ### Vulnerable Code ```python # Generate output path if not output_path: timestamp = datetime.now().strftime('%Y%m%d_%H%M%S') output_path = f'/tmp/screenshot_{timestamp}.png' # Capture screenshot page.screenshot(path=output_path, full_page=full_page) ``` ```python elif arg in ['--output', '-o'] and i + 1 < len(args): output_path = args[i + 1] i += 2 ``` ### Technical Analysis The `--output` argument is accepted without validation and passed directly to Playwright's screenshot operation. The implementation does not restrict output to a dedicated directory, enforce a PNG extension, reject existing files, detect symbolic links, or verify the canonical destination. As a result, the process can replace any file writable by its operating-system account with PNG data. A symbolic link placed at the selected destination may also redirect the write to another writable file outside the expected output location. ### Attack Path 1. An attacker chooses an existing file writable by the Skill process or a path containing an attacker-controlled symbolic link. 2. The attacker invokes the script with that path through `--output` or `-o`. 3. The argument parser assigns the path directly to `output_path`. 4. `page.screenshot()` writes PNG data to the supplied destination. 5. The existing file is replaced or corrupted. 6. If another application later reads or executes the damaged file, the overwrite may cause denial of service or alter downstream behavior. ### Impact Assessment The attacker gains an arbitrary file-overwrite capability limited to files writable by the Skill process. Potential consequences include corruption of application data, configuration files, generated assets, scripts, or other user-owned resources. The vulnerability can cause denial of service ...[truncated 180 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Store all screenshots in a dedicated directory controlled by the application. 2. Generate random output filenames internally instead of accepting arbitrary paths. 3. If caller-selected names are required, accept only a basename and reject absolute paths, traversal components, and directory separators. 4. Resolve the canonical destination and verify that it remains inside the approved output directory. 5. Require a `.png` extension and reject existing files. 6. Reject symbolic links and use exclusive file creation to prevent overwrite and time-of-check/time-of-use attacks. 7. Apply restrictive filesystem permissions to the screenshot directory. 8. Return a logical identifier or approved path rather than permitting the caller to select an arbitrary filesystem destination. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:8
Finding
Unpinned Playwright and Chromium Dependencies Create Supply-Chain Risk<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:8-10, 45-48` **Vulnerability Type**: Unpinned third-party dependency installation **Risk Level**: Medium ### Vulnerable Code ```yaml install: | pip install playwright playwright install chromium ``` The same installation instructions are repeated in the documentation: ```bash pip install playwright playwright install chromium ``` ### Technical Analysis The installation procedure retrieves the latest available Playwright package and associated Chromium binaries without version pinning or integrity verification. The code installed and executed can therefore change between installations even when the Skill package remains unchanged. This prevents reproducible builds and increases exposure to compromised package releases, registry or maintainer-account compromise, unsafe future changes, and incompatibility introduced by later versions. ### Attack Path 1. A user installs the Skill dependencies by following the documented commands. 2. `pip` resolves the mutable latest Playwright release from the configured package index. 3. Playwright subsequently downloads a compatible Chromium build. 4. If a selected package or browser artifact has been compromised or unexpectedly changed, its installation or runtime code is introduced into the environment. 5. The dependency executes with the permissions of the installing or invoking user. ### Impact Assessment A compromised dependency could execute code with the privileges of the account installing or running the Skill, potentially exposing files, browser data, network access, or application secrets available to that account. Even without malicious compromise, unpinned versions can break compatibility and make deployments non-reproducible. No evidence was found that the currently named Playwright package is intentionally malicious; the issue is the unsafe and mutable dependency acquisition process. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin Playwright to a specific audited version, for example through an exact version constraint. 2. Maintain dependencies in a lock file or hash-locked requirements file. 3. Require package hashes during installation, such as with `pip --require-hashes`. 4. Pin and document the corresponding Chromium revision expected by the selected Playwright version. 5. Install only from explicitly configured, trusted package indexes and artifact repositories. 6. Review and test dependency updates before changing pinned versions. 7. Run installation and browser execution under a minimally privileged account or isolated container. ]]>
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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
Findings (4)

Vague Triggers

Medium
Confidence
95% confidence
Finding
The trigger phrases are broad and include common user language such as '帮我截图' and generic requests to capture a page, which can cause the skill to activate in contexts the user did not clearly intend. In a tool that performs outbound web requests and captures rendered page content, unintended invocation can lead to accidental access to sensitive internal URLs or screenshots of confidential pages.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill documentation does not warn users that taking a screenshot causes the local environment to make a request to the supplied URL and render its contents, which may expose internal endpoints, authenticated pages, or sensitive on-screen data in the resulting image. This omission is especially relevant because the skill supports arbitrary URLs and saving screenshots to disk, increasing the chance of capturing confidential content without informed consent.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
The file's title, docstring, and user-facing error text are written only in Chinese, which imposes a specific language on users. Under the stated policy, forcing a specific language without offering user choice is a natural-language policy violation.

Missing User Warnings

Low
Confidence
88% confidence
Finding
This Python code file performs a network operation via `page.goto(url, ...)`, which causes the local environment to contact a remote host. Aside from the terse Chinese docstring saying it captures a webpage screenshot, there is no confirmation prompt, logging, or explicit warning to the user that executing the skill will connect to the provided URL.

Static analysis

No suspicious patterns detected.