Back to skill

Security audit

Screenshot Visual

Security checks for vulnerabilities and agentic risk

Overview

This web reconnaissance screenshot skill has a real security-testing purpose, but it automatically probes sensitive paths and stores captured page data without strong scoping or opt-in controls.

Install only if you intend to run authorized web reconnaissance and are comfortable with it probing common admin/debug/config paths automatically. Use it only on targets you control or are explicitly permitted to test, avoid internal or sensitive network targets unless that is intended, and treat the generated screenshots and JSON reports as potentially sensitive local evidence that may need protection or deletion.

Vulnerability Patterns
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/screenshot.js:21
Finding
Unrestricted Browser Access to Internal and Link-Local Network Resources<![CDATA[ ## Vulnerability Details **File Location**: `scripts/screenshot.js`, lines 21–27 and 50–71 **Vulnerability Type**: Server-Side Request Forgery (SSRF)-like unrestricted network access **Risk Level**: Medium ### Vulnerable Code ```js let parsed; try { parsed = new URL(targetUrl); } catch { console.error('Invalid URL:', targetUrl); process.exit(1); } const hostname = parsed.hostname.replace(/\./g, '_'); ``` ```js const pathsToTry = [ parsed.pathname || '/', '/login', '/admin', '/dashboard', '/register', '/signup', '/api', '/debug', '/phpmyadmin', '/wp-admin', '/.env', '/config', '/swagger', '/swagger-ui', '/api-docs', ]; for (const p of pathsToTry) { const url = `${parsed.origin}${p}`; const slug = p.replace(/\//g, '_').replace(/^_/, '') || 'index'; const screenshotPath = path.join(runDir, `${slug}-${timestamp}.png`); const metaPath = path.join(runDir, `${slug}-${timestamp}.json`); try { const response = await page.goto(url, { timeout: 10000, waitUntil: 'domcontentloaded' }); ``` ### Technical Analysis The validation only confirms that the input is syntactically compatible with the Node.js `URL` parser. It does not enforce an allowed protocol or reject loopback, private, link-local, reserved, or otherwise sensitive network destinations. The browser can therefore be directed to resources such as localhost services, RFC 1918 private addresses, or cloud metadata addresses such as `169.254.169.254`. The program also automatically appends sensitive paths including `/.env`, `/config`, `/debug`, `/admin`, and `/api`. Playwright follows HTTP redirects by default. The code does not inspect or revalidate the destination after each redirect, so an initially permitted-looking public address can redirect the browser to an internal service. DNS resolution is also not validated, leaving the implementation potentially exposed to DNS rebinding or hostnames resolving to non-public addresses. Returned pages are c ...[truncated 1748 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Restrict target URLs to the `http:` and `https:` protocols. 2. Require an explicit allowlist of authorized hostnames or target domains. 3. Resolve the hostname before navigation and reject all loopback, private, link-local, multicast, unspecified, and reserved IPv4 and IPv6 ranges. 4. Revalidate the destination after every redirect. Disable automatic redirects where practical and process each redirect only after validating its target. 5. Protect against DNS rebinding by validating every resolved address and ensuring the browser connects only to an approved address. 6. Explicitly reject common metadata destinations, including `169.254.169.254` and relevant IPv6 link-local equivalents. 7. Do not automatically probe sensitive paths. Require each path or path set to be explicitly authorized by the operator. 8. Run Chromium in a network-isolated environment with egress policies that block internal and metadata networks. 9. Apply response-size, navigation-time, and download restrictions to reduce resource-exhaustion and unintended data collection risks. 10. Record the validated final URL and resolved address in the report for auditability. ]]>

T08 · Insecure Dependencies

Note
Location
SKILL.md:8
Finding
Unpinned and Inconsistent Playwright Dependency Installation<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 8 and 42 **Vulnerability Type**: Mutable third-party dependency and runtime dependency mismatch **Risk Level**: Low ### Vulnerable Code ```yaml metadata: {"openclaw":{"emoji":"📸","os":["linux","darwin","win32"],"requires":{"bins":["playwright-mcp","npx"]},"install":[{"id":"npm-playwright-mcp","kind":"npm","package":"@playwright/mcp","bins":["playwright-mcp"],"label":"Install Playwright MCP"}]}} ``` ```bash npx playwright install chromium ``` The script directly imports a different package: ```js const { chromium } = require('playwright'); ``` ### Technical Analysis The installation metadata names `@playwright/mcp` without a fixed version. The documented `npx playwright install chromium` command can also resolve tooling from the configured npm registry when a suitable local executable is unavailable. This makes installation behavior dependent on mutable registry state rather than a reviewed and reproducible dependency set. A future compromised or unexpectedly changed package version could execute code during installation or alter the behavior of the skill. There is also a dependency mismatch: the skill declares `@playwright/mcp`, while `scripts/screenshot.js` imports `playwright` directly. Installing the declared package does not clearly guarantee that the runtime module required by the script will be available. This inconsistency may lead operators to install additional unreviewed packages manually or invoke `npx` in a way that downloads current registry content. No evidence was found that the currently named package is malicious. The risk arises from unpinned dependency resolution and the inconsistency between the declared and imported packages. ### Attack Path 1. An operator installs or initializes the skill using its documented dependency instructions. 2. npm or `npx` resolves an unpinned package version from the configured package registry. 3. A compromised registry accou ...[truncated 1080 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Declare the exact runtime package used by the script, namely `playwright`, rather than an unrelated MCP package unless the implementation is changed to use MCP. 2. Pin dependencies to exact reviewed versions instead of using floating package references. 3. Commit a lockfile containing integrity hashes and install dependencies with `npm ci`. 4. Use a dedicated `package.json` that explicitly lists all runtime dependencies. 5. Run the browser installation through the locally locked executable, for example: ```bash npx --no-install playwright install chromium ``` 6. Avoid commands that implicitly download packages during normal skill execution. 7. Review npm lifecycle scripts and disable them where they are not required. 8. Use a trusted registry configuration and consider dependency provenance or signature verification. 9. Add automated dependency scanning and controlled update review. 10. Keep the installation metadata, documentation, and actual `require()` statements consistent. ]]>
Vulnerability Patterns
  • 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
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (8)

Ae1

High
Category
analysis-evasion
Content
node scripts/screenshot.js https://example.com
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Credential Access

High
Category
Privilege Escalation
Content
'/debug',
    '/phpmyadmin',
    '/wp-admin',
    '/.env',
    '/config',
    '/swagger',
    '/swagger-ui',
Confidence
97% confidence
Finding
Including '/.env' in the probe list specifically targets a well-known location that can expose application secrets, API keys, database credentials, and other confidential configuration if misconfigured. In the context of a screenshot tool, this is especially dangerous because it turns the skill into credential-oriented reconnaissance rather than simple visual capture.

Vague Triggers

Medium
Confidence
87% confidence
Finding
The example trigger phrase `Check login pages for issues` is broad and generic enough that it could match common user requests outside a clearly bounded security-testing context. Overly broad activation phrases can cause unintended invocation of a skill that performs network reconnaissance and screenshot capture, potentially leading to accidental scanning or collection against targets the user did not explicitly scope. The recon-focused context makes this somewhat more dangerous than a generic utility skill because the actions involve external browsing and artifact collection.

Rp1

Medium
Category
MCP Rug Pull
Confidence
86% confidence
Finding
The skill instructs users to run `npx playwright install chromium`, which resolves and executes tooling without pinning an explicit version. This creates a supply-chain risk: a compromised or unexpectedly changed upstream package/version could execute unreviewed code in the user's environment during installation. In a security-oriented skill, this is more concerning because users may run the setup on analyst workstations with elevated trust and broad network access.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The skill claims to take screenshots of a target, but it also performs multi-endpoint probing and collects security-relevant metadata across common sensitive paths. This expands behavior beyond the stated purpose, creating undisclosed active scanning that can surprise users, trigger alerts, or be misused for reconnaissance.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
The hardcoded path list includes administrative and sensitive endpoints such as /admin, /phpmyadmin, /wp-admin, /.env, and /debug that are commonly used for reconnaissance. Probing these locations is riskier than ordinary screenshot capture because it actively searches for exposed management surfaces and sensitive files.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The code actively requests multiple potentially sensitive paths on the target without an explicit warning that it will perform scanning behavior beyond visiting the provided URL. This can cause unauthorized or unexpected interactions with target systems and may violate user expectations or organizational policies.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The script stores screenshots, page text snippets, headers, form details, and interesting links to disk, which may capture credentials, tokens, internal URLs, or other sensitive information. Persisting this data without prominent notice, minimization, or protection increases the chance of inadvertent data exposure on the operator's system.

Static analysis

No suspicious patterns detected.