Back to skill

Security audit

Playwright Scraper Skill 1.2.0

Security checks for vulnerabilities and agentic risk

Overview

This is a real Playwright scraping skill, but it promotes anti-bot bypass and runs arbitrary URLs in a weakened browser with broad file-output controls.

Install only if you are comfortable running a local browser scraper against sites you are authorized to access. Avoid using it on private/internal URLs, authenticated pages, or sensitive accounts unless isolated. Run it in a container or low-privilege environment, do not pass arbitrary SCREENSHOT_PATH values from untrusted input, treat saved screenshots/HTML as potentially sensitive, and pin/review any optional third-party scraper before use.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/playwright-stealth.js:47
Finding
Unrestricted Browser Navigation with Chromium Security Isolation Disabled<![CDATA[ ## Vulnerability Details **File Location**: `scripts/playwright-stealth.js:47-52, 88-92`; `scripts/playwright-simple.js:31` **Vulnerability Type**: Server-side request forgery exposure and weakened browser containment **Risk Level**: High ### Vulnerable Code ```javascript // scripts/playwright-stealth.js:47-52 const browser = await chromium.launch({ headless: headless, args: [ '--no-sandbox', '--disable-setuid-sandbox', '--disable-blink-features=AutomationControlled', '--disable-features=IsolateOrigins,site-per-process', ], }); ``` ```javascript // scripts/playwright-stealth.js:88-92 const response = await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30000, }); ``` ```javascript // scripts/playwright-simple.js:31 await page.goto(url, { waitUntil: 'domcontentloaded' }); ``` ### Technical Analysis Both scraper implementations accept a URL directly from command-line input and navigate to it without validating the protocol, hostname, resolved IP address, or redirect destination. There is no restriction against loopback, link-local, private-network, or cloud metadata endpoints. Arbitrary public HTTP and HTTPS targets are necessary for a general-purpose scraper, but access to internal network resources is not required for that functionality. The stealth implementation further starts Chromium with its sandbox and site/process isolation disabled. Anti-automation behavior does not require disabling these principal security boundaries. This creates two related risks: 1. The scraper can act as an SSRF-capable browser from the network context of the host. 2. A malicious page is processed by a browser with materially reduced containment. Host compromise would still generally require a compatible browser vulnerability, but these flags increase the consequences of such an exploit. ### Attack Path 1. An attacker convinces a user or Agent workflow to scrape an attacker-selected URL. 2. The attac ...[truncated 1194 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Allow only `http:` and `https:` URLs and reject URLs containing embedded credentials. 2. Resolve target hostnames before navigation and reject loopback, private, link-local, multicast, reserved, and cloud metadata address ranges for both IPv4 and IPv6. 3. Intercept browser requests and repeat destination validation for every redirect and subresource request to prevent redirect-based and DNS-rebinding bypasses. 4. Introduce an explicit hostname allowlist where the deployment has a known set of permitted targets. 5. Remove `--no-sandbox`, `--disable-setuid-sandbox`, and `--disable-features=IsolateOrigins,site-per-process`. 6. Run Chromium as a dedicated unprivileged user in an OS-level container with a read-only filesystem, restricted outbound networking, no host-network access, and no mounted credentials. 7. Apply navigation, response-size, and total execution limits to reduce denial-of-service exposure. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/playwright-stealth.js:25
Finding
Caller-Controlled Output Paths Permit Arbitrary File Overwrite<![CDATA[ ## Vulnerability Details **File Location**: `scripts/playwright-simple.js:14, 44-47`; `scripts/playwright-stealth.js:25-26, 128-140` **Vulnerability Type**: Unrestricted filesystem write path **Risk Level**: Medium ### Vulnerable Code ```javascript // scripts/playwright-simple.js:14 const screenshotPath = process.env.SCREENSHOT_PATH; ``` ```javascript // scripts/playwright-simple.js:44-47 if (screenshotPath) { await page.screenshot({ path: screenshotPath }); console.log(`📸 截圖已儲存: ${screenshotPath}`); } ``` ```javascript // scripts/playwright-stealth.js:25-26 const screenshotPath = process.env.SCREENSHOT_PATH || `./screenshot-${Date.now()}.png`; const saveHtml = process.env.SAVE_HTML === 'true'; ``` ```javascript // scripts/playwright-stealth.js:128-140 try { await page.screenshot({ path: screenshotPath, fullPage: false, timeout: 10000 }); console.log(`📸 截圖已儲存: ${screenshotPath}`); result.screenshot = screenshotPath; } catch (error) { console.log(`⚠️ 截圖失敗: ${error.message}`); result.screenshot = null; } // 儲存 HTML(如果需要) if (saveHtml) { const htmlPath = screenshotPath.replace(/\.[^.]+$/, '.html'); const html = await page.content(); fs.writeFileSync(htmlPath, html); } ``` ### Technical Analysis `SCREENSHOT_PATH` is accepted from the process environment and used directly as a filesystem destination. The path is not canonicalized, constrained to a dedicated output directory, checked for traversal, or protected against symbolic links and pre-existing destinations. The stealth implementation derives an HTML path from the same untrusted value and writes the complete remote page using `fs.writeFileSync`. Node.js filesystem writes overwrite an existing writable file by default. Direct environment control normally requires access to the process invocation. The vulnerability becomes practically exploitable when an Agent, API, or wrapper maps untrusted request values into these environment variables, or when a le ...[truncated 1326 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create a dedicated output directory controlled by the application and do not accept arbitrary absolute output paths. 2. Generate output filenames internally using cryptographically random identifiers. 3. Resolve the requested destination with `path.resolve()` and verify that it remains beneath the approved output directory. 4. Reject path traversal, absolute paths, symbolic links, and non-regular destination files. 5. Open files with exclusive creation semantics such as `wx` so existing files cannot be silently replaced. 6. Apply restrictive file permissions and run the Skill under a dedicated account with minimal filesystem access. 7. If user-selected names are required, accept only a basename matching a strict allowlist and append the file extension internally. 8. Treat environment variables supplied by Agent workflows as untrusted input and validate them at the execution boundary. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:86
Finding
Documentation Executes an Unpinned Third-Party Skill Through npx<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:86-95` **Vulnerability Type**: Mutable third-party dependency retrieval and execution **Risk Level**: Medium ### Vulnerable Code ```bash ### 4️⃣ YouTube Video Transcripts Use **deep-scraper** (install separately): # Install deep-scraper skill npx clawhub install deep-scraper # Use it cd skills/deep-scraper node assets/youtube_handler.js "https://www.youtube.com/watch?v=VIDEO_ID" ``` ### Technical Analysis The Skill documentation instructs users to invoke `npx clawhub`, install a separately maintained Skill by an unversioned name, and then execute a JavaScript file from the installed package. Neither the `clawhub` executable nor `deep-scraper` is pinned to a reviewed version or integrity digest in this instruction. Consequently, the code executed by users can differ from the code that existed when this project was audited. The third-party component is outside the audited repository and its behavior cannot be established from the available files. This is a supply-chain weakness rather than evidence that the currently named third-party component is malicious. ### Attack Path 1. A user follows the transcript-scraping instructions in `SKILL.md`. 2. `npx` resolves and executes the available `clawhub` package or command without a version pinned by the documentation. 3. The command retrieves the current package associated with the mutable `deep-scraper` name. 4. A registry compromise, namespace takeover, compromised publisher account, or malicious future release changes the retrieved content. 5. The user executes `assets/youtube_handler.js` with the permissions of the user or Agent account. ### Impact Assessment A compromised installer or downloaded Skill could execute arbitrary JavaScript with the invoking account's privileges. This may expose files, environment variables, credentials, and network resources accessible to that account. No malicious payload from `clawhub` or `deep-scraper` is p ...[truncated 127 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove optional third-party installation commands from the core Skill instructions or clearly separate them as unaudited extensions. 2. Pin the `clawhub` installer and `deep-scraper` Skill to specific reviewed versions. 3. Verify downloaded artifacts against published cryptographic integrity hashes or signatures before execution. 4. Require explicit user approval before downloading or executing third-party Skill code. 5. Review the third-party package independently and document its required permissions, network destinations, filesystem access, and update policy. 6. Execute optional third-party components in an isolated, unprivileged environment without mounted credentials or unrestricted host access. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (38)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The description emphasizes anti-bot protection and operation on complex protected sites, which is the core claimed capability. However, the code is a minimal Playwright script: it opens a page, waits, extracts basic text and metadata, and optionally takes a screenshot. There is no evidence of anti-bot handling such as stealth measures, header/user-agent management, proxy/cookie/session handling, challenge solving, retry logic, or site-specific workflows. In fact, the inline comments explicitly say it is for general dynamic websites with no anti-crawling protection. That makes the declared purpose materially overstated relative to the actual behavior.

Ae1

High
Category
analysis-evasion
Content
| **Cloudflare Protected** | High | **Playwright Stealth** ⭐ | `scripts/playwright-stealth.js` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| **Cloudflare Protected** | High | **Playwright Stealth** ⭐ | `scripts/playwright-stealth.js` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| **Cloudflare Protected** | High | **Playwright Stealth** ⭐ | `scripts/playwright-stealth.js` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| **Cloudflare Protected** | High | **Playwright Stealth** ⭐ | `scripts/playwright-stealth.js` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| **Cloudflare Protected** | High | **Playwright Stealth** ⭐ | `scripts/playwright-stealth.js` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| **Cloudflare Protected** | High | **Playwright Stealth** ⭐ | `scripts/playwright-stealth.js` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| **Cloudflare Protected** | High | **Playwright Stealth** ⭐ | `scripts/playwright-stealth.js` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| **Cloudflare Protected** | High | **Playwright Stealth** ⭐ | `scripts/playwright-stealth.js` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| **Cloudflare Protected** | High | **Playwright Stealth** ⭐ | `scripts/playwright-stealth.js` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Missing User Warnings

High
Confidence
97% confidence
Finding
The troubleshooting guidance advises manual login followed by cookie export/load for authenticated scraping, but gives no warning about the sensitivity of session cookies. Session cookies can grant account access without passwords, so normalizing their export/import materially increases the risk of credential theft, session hijacking, and unauthorized access if mishandled or logged.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
echo ""

# 清理
rm -f /tmp/test-*.json screenshot-*.png

echo "✅ 所有測試通過!"
Confidence
95% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The changelog explicitly promotes anti-bot evasion, recommends hiding browser automation fingerprints, and plans future CAPTCHA, cookie, and login-state features. In a scraping skill, this materially increases abuse potential by facilitating bypass of site defenses and collection from authenticated or restricted contexts without any warning about legal, privacy, or policy constraints.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The README explicitly promotes stealth scraping and anti-bot evasion, including hiding automation signals and mimicking real users, but provides no warning about legal, policy, or account-risk implications. In a scraping skill, this increases the likelihood of misuse against protected services and normalizes bypassing access controls, making the documentation materially more dangerous than neutral browser automation guidance.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The README documents saving screenshots and full HTML without warning that these artifacts may contain session tokens, personal data, internal content, or other sensitive information. In a scraping tool context, encouraging storage of page captures without data-handling guidance raises confidentiality and retention risks, especially when used on authenticated or user-specific pages.

Lp3

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding
The skill documents use of environment variables that influence runtime behavior, but it does not declare any explicit tool scope or permissions boundaries. In an agent ecosystem, missing scope declarations can lead to overly broad execution assumptions and make it harder to enforce least privilege or review what the skill is allowed to access.

Rp1

Medium
Category
MCP Rug Pull
Confidence
91% confidence
Finding
Using `npx playwright` without pinning a specific version creates a supply-chain and reproducibility risk because the resolved package version can change over time. That can introduce unexpected behavior or malicious upstream code into installations or runtime setup steps.

Static analysis

No suspicious patterns detected.