Back to skill

Security audit

Full Webpage Screenshot

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real webpage screenshot tool, but it runs an unsandboxed browser against arbitrary URLs and has outdated vulnerable Puppeteer dependencies, so it should be reviewed before installation.

Install only if you are comfortable running a Puppeteer-based browser against URLs you choose. Avoid using it on internal, localhost, cloud metadata, authenticated, or sensitive URLs unless it runs in a locked-down disposable container with restricted network egress and no secrets. The publisher should update Puppeteer and dependencies, remove the disabled sandbox flags where possible, and add URL/network safeguards 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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/screenshot.js:84
Finding

Unrestricted Browser Navigation Enables Server-Side Request Forgery

Content
View full analysis

Vulnerability Details

File Location: scripts/screenshot.js:84-99
Vulnerability Type: Server-Side Request Forgery and unsafe URL handling
Risk Level: High

Vulnerable Code

javascript
const url = args[0];
const outputPath = args[1] || './screenshot.png';

// Validate URL
try {
  new URL(url);
} catch (e) {
  console.error('Invalid URL:', url);
  process.exit(1);
}

takeScreenshot(url, path.resolve(outputPath))
  .then(result => {
    console.log(JSON.stringify(result));
  })

The unchecked URL is subsequently passed to the browser navigation sink:

javascript
await page.goto(url, { 
  waitUntil: 'networkidle2',
  timeout: 30000 
});

Technical Analysis

The validation only verifies that the input can be parsed by the JavaScript URL constructor. It does not enforce an allowed protocol, reject embedded credentials, restrict destination hosts, resolve and validate destination IP addresses, or validate redirect targets.

Consequently, a requester can instruct Chromium to connect to resources available from the host's network context. Potential destinations include loopback services, private network addresses, link-local endpoints, and cloud instance metadata services. A public URL that redirects to a prohibited internal destination can also bypass validation because redirects are not inspected.

Because the requested resource is rendered and captured as an image, information returned by an internal service may become visible in the generated screenshot. The exact information exposed depends on services reachable from the execution environment and whether those services require authentication.

Attack Path

  1. An attacker asks the agent to capture a screenshot of an internal or link-local URL, such as a loopback service or cloud metadata endpoint.
  2. The URL passes validation because it is syntactically valid.
  3. page.goto() causes Chromium to issue the r ...[truncated 977 chars]
Remediation
View remediation

Remediation Suggestions

  1. Allow only explicitly supported protocols, preferably https: and, if required, http:.
  2. Reject URLs containing embedded usernames or passwords.
  3. Resolve the hostname before navigation and reject every address in loopback, private, link-local, multicast, reserved, and cloud metadata ranges for both IPv4 and IPv6.
  4. Revalidate the destination after every redirect. Do not rely solely on validating the initial URL.
  5. Protect against DNS rebinding by ensuring the browser's actual connection destination remains within the validated public address set.
  6. Prefer an explicit hostname allowlist when the operational use case permits it.
  7. Enforce network-level egress controls around Chromium so application-level validation is not the only security boundary.
  8. Block access to cloud metadata services at the firewall or container-network layer.
  9. Add automated tests covering loopback addresses, private IPv4 and IPv6 ranges, link-local addresses, unusual URL schemes, embedded credentials, redirects to internal addresses, and DNS rebinding scenarios.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/screenshot.js:27
Finding

Chromium Sandbox Is Explicitly Disabled for Attacker-Controlled Web Content

Content
View full analysis

Vulnerability Details

File Location: scripts/screenshot.js:27-30
Vulnerability Type: Unsafe browser security configuration
Risk Level: High

Vulnerable Code

javascript
const browser = await puppeteer.launch({
  headless: 'new',
  args: ['--no-sandbox', '--disable-setuid-sandbox']
});

Technical Analysis

The skill visits arbitrary user-supplied webpages while passing both --no-sandbox and --disable-setuid-sandbox to Chromium. These options disable a principal browser process-isolation boundary intended to limit the impact of vulnerabilities in the renderer and related browser components.

Web content normally cannot directly execute operating-system commands merely because these flags are present. However, if a malicious page exploits a Chromium vulnerability, disabling the sandbox can substantially reduce or eliminate the additional containment an attacker would otherwise need to escape. This turns a browser compromise into a potentially direct compromise of the account or container running the skill.

The risk is especially relevant because the skill's declared purpose requires processing untrusted remote JavaScript, HTML, fonts, images, and other browser content.

Attack Path

  1. An attacker hosts a webpage containing content that targets a vulnerability in the installed Chromium version.
  2. The attacker requests a screenshot of that webpage.
  3. The skill launches Chromium with its sandbox explicitly disabled.
  4. Chromium loads and executes the attacker's web content.
  5. If the browser vulnerability is successfully exploited, the missing sandbox increases the attacker's ability to access the host environment directly.
  6. The resulting access is limited by the operating-system identity, container boundaries, mounted files, network access, and credentials available to the skill process.

Impact Assessment

A successful browser exploit could obtain the privileges of the us ...[truncated 695 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove --no-sandbox and --disable-setuid-sandbox, and configure the runtime so Chromium's supported sandbox can operate.
  2. Run the skill as a dedicated, unprivileged operating-system account with no administrative capabilities.
  3. Execute each screenshot job in a disposable container or sandbox with a read-only root filesystem and a minimal writable output directory.
  4. Do not expose credentials, sensitive environment variables, host sockets, browser profiles, or unrelated workspace files to the browser process.
  5. Apply strict CPU, memory, process, file-size, and execution-time limits to reduce denial-of-service exposure from malicious pages.
  6. Restrict container capabilities, enable no-new-privileges, and use an appropriate seccomp or equivalent system-call policy.
  7. Apply network egress restrictions so the browser can reach only destinations required by the task.
  8. Keep Puppeteer and its compatible Chromium release on a supported, security-patched version. The lockfile identifies Puppeteer 22.15.0 as unsupported, so the dependency should be upgraded and retested.
  9. If sandbox-disabled execution is unavoidable, treat the entire runtime as disposable and untrusted, with no host mounts, secrets, internal network access, or persistent state.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (8)

Known Vulnerable Dependency: basic-ftp==5.2.0 — 4 advisory(ies): GHSA-6v7q-wjvx-w8wg (basic-ftp: Incomplete CRLF Injection Protection Allows Arbitrary FTP Command Exe); CVE-2026-39983 (basic-ftp has FTP Command Injection via CRLF); CVE-2026-41324 (basic-ftp vulnerable to denial of service via unbounded memory consumption in Cl) +1 more

High
Category
Supply Chain
Confidence
82% confidence
Finding

The lockfile pins basic-ftp 5.2.0, and the flagged advisories include FTP command-injection and resource-consumption issues. In this skill, basic-ftp is only present transitively through get-uri/proxy-agent/pac-proxy-agent as part of Puppeteer's proxy support, so exploitability depends on the code actually processing attacker-controlled FTP/PAC URIs; that makes the risk real but contextually reduced.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: extract-zip==2.0.1 — 2 advisory(ies): CVE-2026-19693 (extract-zip allows arbitrary file writes through symlink archive entries); CVE-2026-56876 (extract-zip unvalidated symlink path traversal)

High
Category
Supply Chain
Confidence
90% confidence
Finding

extract-zip 2.0.1 is a real vulnerable dependency, with reported arbitrary-write/path-traversal issues via malicious symlink entries in archives. Here it is pulled in by @puppeteer/browsers for browser download/extraction during install/runtime, so the issue becomes relevant if the skill downloads or extracts attacker-influenced browser archives or uses untrusted mirrors.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: ip-address==10.1.0 — 2 advisory(ies): CVE-2026-69192 (ip-address: Address4 decodes leading-zero octets as decimal while resolvers deco); CVE-2026-42338 (ip-address has XSS in Address6 HTML-emitting methods)

High
Category
Supply Chain
Confidence
80% confidence
Finding

ip-address 10.1.0 is flagged for parsing inconsistencies and an XSS issue in HTML-emitting helpers. In this lockfile it is only a transitive dependency of socks, used under proxy-agent/socks-proxy-agent; unless the skill exposes those HTML helpers or relies on strict IP canonicalization for security decisions, practical impact is limited.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: js-yaml==4.1.1 — 4 advisory(ies): CVE-2026-84375 (js-yaml: maxTotalMergeKeys does not limit CPU use for empty merge sources); CVE-2026-59869 (js-yaml: YAML merge-key chains can force quadratic CPU consumption); GHSA-5p4m-2wfm-xmqj (JS-YAML: Quadratic CPU consumption in !!omap resolution (3.x and 4.x) — CVE-2026) +1 more

High
Category
Supply Chain
Confidence
86% confidence
Finding

js-yaml 4.1.1 is a genuinely vulnerable version for CPU-exhaustion style parsing attacks. In this package tree it is brought in by cosmiconfig, which Puppeteer can use for configuration loading; if untrusted YAML configuration is ever read in the execution environment, this can enable denial of service.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: ws==8.20.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
80% confidence
Finding

ws 8.20.0 is reported vulnerable to memory disclosure and memory-exhaustion conditions. Because Puppeteer relies on WebSocket communication with the browser debugging protocol, any component that allows a hostile endpoint or malformed WebSocket traffic into that channel could trigger instability or data exposure, though typical local-only DevTools usage lowers likelihood.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
81% confidence
Finding

The skill invokes Node.js and relies on environment variables to control execution, but it does not declare any explicit tool scope such as permissions or allowed-tools. That omission weakens policy enforcement and reviewability, making it easier for the skill to run with broader-than-necessary execution context or inherit sensitive environment data unintentionally.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill encourages visiting arbitrary user-supplied URLs with Puppeteer but does not warn that doing so sends the URL request, IP address, user agent, and related metadata to the target website and any third-party resources it loads. This is primarily a privacy and user-consent issue: users may unknowingly cause network access to external sites, including sensitive internal or tracking-heavy destinations.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The dependency uses a caret range (^22.0.0), which permits automatic installation of newer minor and patch releases rather than a single fixed version. This weakens supply-chain reproducibility and can expose consumers of the skill to regressions or a compromised upstream release if the allowed version range later resolves to a malicious or vulnerable package version.

Content

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

json
"main": "screenshot.js",
  "license": "MIT",
  "dependencies": {
    "puppeteer": "^22.0.0"
  }
}

Static analysis

No suspicious patterns detected.