Back to skill

Security audit

Web Scraper

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a disclosed web-scraping helper, but it includes instructions to reveal soft-paywalled content and can send scraped text to OpenRouter without a clear per-use consent gate.

Install only if you are comfortable supervising its use: avoid using it to reveal or collect paywalled content, do not enable the OpenRouter entity-extraction stage for private/authenticated/sensitive pages without explicit approval, and prefer pinned dependencies in an isolated environment.

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)

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:599
Finding
Scraped Content Is Transmitted to a Third-Party LLM Without Sensitivity Controls<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 599-644 **Vulnerability Type**: Sensitive-data disclosure to a third-party service **Risk Level**: Medium ### Vulnerable Code ```python OPENROUTER_API_KEY = os.environ.get("OPENROUTER_API_KEY", "") OPENROUTER_ENDPOINT = "https://openrouter.ai/api/v1/chat/completions" def extract_entities_llm(text: str, metadata: dict) -> dict: """Extracts entities from a news article using LLM.""" text_sample = text[:4000] if len(text) > 4000 else text prompt = f"""You are a news entity extractor. Analyze the text below and extract: TITLE: {metadata.get('title', 'N/A')} DATE: {metadata.get('date', 'N/A')} TEXT: {text_sample} Respond ONLY with valid JSON, no markdown, in this format: {{ "people": [ {{"name": "Full Name", "role": "Role/Title", "context": "One sentence about their role in the article"}} ], "organizations": [ {{"name": "Org Name", "type": "company|government|ngo|other", "context": "role in article"}} ], "locations": [ {{"name": "Location Name", "type": "city|state|country|address", "context": "mention"}} ], "events": [ {{"name": "Event", "date": "date if available", "description": "brief description"}} ], "relationships": [ {{"subject": "Entity A", "relation": "relation type", "object": "Entity B"}} ] }}""" try: response = req.post( OPENROUTER_ENDPOINT, headers={ "Authorization": f"Bearer {OPENROUTER_API_KEY}", "Content-Type": "application/json", }, json={ "model": "google/gemini-2.5-flash-lite", "messages": [{"role": "user", "content": prompt}], "max_tokens": 2000, "temperature": 0.1, }, timeout=30, ) ``` ### Technical Analysis The optional entity-extraction stage includes the article title, publication date, and up to 4,000 characters of scraped tex ...[truncated 1776 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require explicit user opt-in immediately before enabling Stage 5 and identify OpenRouter as the recipient. 2. Display which content fields will leave the local environment. 3. Disable external LLM processing by default for authenticated, internal, private, or access-restricted pages. 4. Add configurable redaction for email addresses, phone numbers, account identifiers, addresses, secrets, and other sensitive patterns. 5. Minimize transmitted data by sending only the passages required for the requested extraction. 6. Provide a local entity-extraction alternative for sensitive workloads. 7. Add an allowlist for approved LLM providers and models. 8. Document provider retention, training, residency, and privacy implications. 9. Fail closed when the API key is absent rather than sending an empty bearer token. 10. Record user consent and the destination provider in provenance metadata without logging the API key or sensitive prompt content. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
SKILL.md:580
Finding
Instructions Encourage Circumvention of Soft Paywall Controls<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 580-585 **Vulnerability Type**: Access-control circumvention **Risk Level**: Medium ### Vulnerable Instructions ```text **Paywall handling:** - **Hard paywall:** content never sent to client. Extract preview (title, lead, metadata). Mark `paywall: "hard"` in output. - **Soft paywall:** content present in DOM but hidden by CSS/JS. Use Playwright to remove paywall overlay and reveal paragraphs. - **No paywall:** proceed normally. ``` ### Technical Analysis The Skill explicitly instructs generated Playwright automation to remove a soft-paywall overlay and reveal text hidden by CSS or JavaScript. Although that content may already be present in the client-side DOM, the overlay represents a publisher-imposed access restriction. Deliberately removing it goes beyond ordinary extraction of content presented to the user. This instruction also conflicts with the later safety rule stating that paywalls must not be bypassed. The conflicting directions create ambiguity and may cause the agent to follow the more operationally specific bypass instruction. ### Attack Path 1. The user supplies a page protected by a soft paywall. 2. The static extraction stage determines that content is insufficient or requires JavaScript. 3. Playwright loads and executes the page. 4. Generated automation identifies and removes the paywall overlay or associated hiding behavior. 5. Paragraphs that the publisher intended to restrict become readable in the rendered DOM. 6. The scraper extracts and saves the restricted content and may subsequently send it to the optional LLM stage. ### Impact Assessment The behavior can bypass a website's client-side access-control presentation and collect content not intended to be available without subscription or authorization. It does not obtain operating-system privileges, credentials, or server-side access, and it cannot bypass a hard paywall where content is not delivered to the c ...[truncated 289 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the instruction to delete overlays or otherwise reveal hidden paywalled paragraphs. 2. Treat both hard and soft paywalls as access restrictions. 3. Extract only content that is visibly available to an unauthenticated user under normal page operation. 4. For paywalled pages, return only public metadata, title, lead, and an explicit `paywall` classification. 5. Require explicit authorization before scraping authenticated pages, while still prohibiting circumvention of publisher controls. 6. Consolidate the paywall policy into one unambiguous rule so operational instructions cannot conflict with the safety section. 7. Add tests verifying that generated Playwright scripts do not remove paywall elements, alter subscription state, or expose hidden restricted text. ]]>

T08 · Insecure Dependencies

Note
Location
SKILL.md:813
Finding
Dependency and Browser Installation Commands Are Not Reproducibly Pinned<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 813-824 **Vulnerability Type**: Unpinned third-party dependency installation **Risk Level**: Low ### Vulnerable Code ```bash pip install \ requests \ beautifulsoup4 \ lxml html5lib \ scrapy \ playwright \ trafilatura \ pyyaml \ python-dateutil # Chromium browser for Playwright playwright install chromium ``` ### Technical Analysis The Skill instructs the agent to install the latest available versions of multiple Python packages and a Playwright-managed Chromium build. No lock file, exact version constraints, package hashes, trusted index configuration, or browser artifact verification is provided. The listed package names are recognizable, and the audit found no evidence of typosquatting, dependency confusion, or a deliberately malicious source. The risk is therefore prospective supply-chain exposure rather than evidence that the current dependencies are malicious. Mutable installation results also undermine reproducibility and may introduce future incompatible or compromised releases. ### Attack Path 1. The agent follows the dependency-installation instructions in a new environment. 2. `pip` resolves the package names to the latest releases available from its configured index. 3. A compromised package release, maliciously configured package index, or unsafe transitive dependency is selected. 4. Installation hooks or imported package code execute with the privileges of the agent process. 5. The compromised component gains access to the network, scraper output, and other resources available to that process. A similar path applies to the Playwright browser download if its distribution channel or resolved artifact is compromised. ### Impact Assessment A compromised dependency could execute code with the same privileges as the user or agent running the installation. Given the declared permissions, this may include network access and access to files available within the ...[truncated 300 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin exact dependency versions in a reviewed lock file. 2. Use hash verification, such as `pip install --require-hashes`, for all direct and transitive Python dependencies. 3. Configure installation to use an explicitly trusted package index. 4. Review and update dependency pins through a controlled process with automated vulnerability scanning. 5. Pin the Playwright package and its corresponding browser revision. 6. Verify downloaded browser artifacts using vendor-provided integrity mechanisms. 7. Install dependencies in an isolated virtual environment or container with minimal host privileges. 8. Separate dependency installation from routine scraping execution so package installation is not repeated for every invocation. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (6)

Rp1

Medium
Category
MCP Rug Pull
Confidence
79% confidence
Finding
The skill instructs checking Playwright availability via `npx playwright install --dry-run` without pinning a version, which can pull whatever package/version is current in the environment or registry. In an agent context this weakens supply-chain integrity and reproducibility, especially when commands may be run automatically on developer machines or CI.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The hard-coded `Accept-Language: pt-BR,pt;q=0.9,en-US;q=0.8` forces a locale preference without user consent. This can alter returned content, bias extraction results, and unintentionally disclose regional preferences in requests, which is a data-handling and correctness concern rather than a direct code-execution issue.

Ssd 4

Medium
Confidence
95% confidence
Finding
By distinguishing hard versus soft paywalls and then recommending DOM manipulation for the latter, the skill normalizes a bypass workflow and lowers the barrier for misuse. In the context of a general-purpose scraping agent, that guidance is especially dangerous because it turns ambiguous policy edges into a concrete circumvention recipe.

Context-Inappropriate Capability

Medium
Confidence
98% confidence
Finding
The skill explicitly includes a method for exposing paywalled content already present in the DOM, which is a circumvention capability not necessary for ordinary scraping. In a user-invocable scraping skill, this meaningfully increases misuse potential by operationalizing access to restricted publisher content.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The paywall-handling section tells the agent to use Playwright to remove soft-paywall overlays and reveal hidden paragraphs, while the safety rules say not to bypass hard paywalls. Even if framed as 'soft' only, this is still bypass-oriented guidance that encourages accessing content the publisher attempted to restrict, creating legal, policy, and abuse risk.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill sends scraped article text and metadata to OpenRouter-backed LLM APIs but does not require a clear user-facing disclosure or consent step before external transmission. In scraping workflows, extracted text may include copyrighted, sensitive, or contractually restricted material, so silent onward transfer to a third party creates privacy, compliance, and data-governance risk.

Static analysis

No suspicious patterns detected.