Back to skill

Security audit

Smart Scraper

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent user-directed web scraping skill, but users should treat scraped output and arbitrary target URLs with care.

Install only if you are comfortable running a browser-based scraper on URLs you choose. Avoid feeding it untrusted or internal/private-network URLs, confirm you have permission to scrape the target site, and treat exported CSV files as untrusted website data before opening them in spreadsheet software.

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
src/extractors/BrowserManager.ts:22
Finding
Unrestricted URL Navigation Enables Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `src/extractors/BrowserManager.ts:22-31` **Related Input Location**: `src/cli.ts:57-59` **Vulnerability Type**: Server-Side Request Forgery (SSRF) **Risk Level**: High ### Vulnerable Code ```ts async scrapePage(url: string, options: ScrapeOptions): Promise<{ content: string; screenshot: Buffer; structure: PageStructure; }> { const page = await this.newPage(); try { await page.goto(url, { waitUntil: 'networkidle' }); ``` The CLI accepts the navigation target without validation: ```ts case '--url': case '-u': options.url = args[++i]; break; ``` ### Technical Analysis The user-controlled URL is passed directly to Playwright's `page.goto()` method. The implementation does not validate the URL scheme, hostname, resolved IP addresses, port, or redirect destinations. Because the request originates from the machine running the Skill, an attacker who can control the URL may direct Chromium to resources that are inaccessible from the attacker's own network position. Relevant targets include: - Loopback services such as `127.0.0.1` and `::1` - RFC 1918 private networks - Link-local services and cloud instance metadata endpoints - Internal administrative panels or development services - Public URLs that redirect to private destinations After navigation, the Skill extracts `document.body.innerText`, selected page text, or table content and returns it to the caller. This creates a response-reading SSRF condition rather than merely a blind request primitive. ### Attack Path 1. An attacker supplies an internal target, for example `http://127.0.0.1:8080/admin`, as the `--url` argument or through the exported `SmartScraper.scrape()` API. 2. `src/cli.ts` stores the value in `options.url` without validation. 3. `SmartScraper.scrape()` passes the URL to `BrowserManager.scrapePage()`. 4. Headless Chromium sends the request from the Skill host's network context. 5. The extractor reads the result ...[truncated 781 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse targets with the standard `URL` class and reject malformed URLs. 2. Allow only explicitly required schemes, normally `https:` and optionally `http:`. 3. Reject embedded usernames and passwords, nonstandard schemes, and unexpected ports. 4. Resolve the hostname before navigation and block all loopback, private, link-local, multicast, unspecified, and reserved IPv4 and IPv6 ranges. 5. Protect against DNS rebinding by validating the address actually used for each connection rather than relying exclusively on an initial DNS lookup. 6. Intercept Playwright requests with `page.route()` or browser-context routing and validate every outgoing destination, including subresources. 7. Validate every redirect destination before following it. 8. Prefer an explicit hostname allowlist when the set of legitimate scraping targets is known. 9. Apply network-level egress restrictions so the scraper process cannot reach cloud metadata endpoints, internal management networks, or sensitive local services. 10. Add tests covering loopback, private IPv4, private IPv6, link-local addresses, alternate address encodings, DNS rebinding, and public-to-private redirects. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
src/utils/DataFormatter.ts:42
Finding
Attacker-Controlled Scraped Content Is Exported as Unsafe CSV<![CDATA[ ## Vulnerability Details **File Location**: `src/utils/DataFormatter.ts:42-68` **Vulnerability Type**: CSV Formula Injection and Improper CSV Escaping **Risk Level**: Medium ### Vulnerable Code ```ts toCSV(data: ScrapedData): string { if (data.type === 'table') { const headers = data.headers.join(','); const rows = data.rows.map(row => data.headers.map(h => { const val = row[h]; const str = String(val ?? ''); return str.includes(',') ? `"${str}"` : str; }).join(',') ); return [headers, ...rows].join('\n'); } if (data.type === 'list') { if (data.items.length === 0) return ''; const headers = Object.keys(data.items[0]).join(','); const rows = data.items.map(item => Object.values(item).map(v => { const str = String(v ?? ''); return str.includes(',') ? `"${str}"` : str; }).join(',') ); return [headers, ...rows].join('\n'); } // Article to CSV (single row) return `title,content,author,date\n"${data.title}","${data.content.substring(0, 200)}...",${data.author || ''},${data.publishDate || ''}`; } ``` ### Technical Analysis CSV fields originate from attacker-controlled webpage content. The formatter does not neutralize cells beginning with spreadsheet formula markers such as: - `=` - `+` - `-` - `@` When a generated file is opened in spreadsheet software, such cells may be interpreted as formulas instead of inert text. Merely surrounding a value with double quotes does not reliably prevent formula evaluation in spreadsheet applications. The implementation also quotes fields only when they contain a comma. It does not correctly handle embedded double quotes, carriage returns, or newline characters. Article fields are interpolated directly into quoted fields without doubling embedded quotes. This can allow malicious content to terminate a field, create additional rows or columns, or place a formula at the beginning of a newly constructed c ...[truncated 1623 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the custom CSV construction with a maintained, standards-compliant CSV serialization library. 2. Quote fields consistently and double every embedded double quote according to RFC 4180. 3. Correctly preserve or normalize carriage-return and newline characters within quoted fields. 4. Apply the same encoding rules to headers, table cells, list values, article titles, article content, authors, and publication dates. 5. Before serialization, neutralize text cells whose first non-whitespace character is `=`, `+`, `-`, or `@`. A common defensive approach is to prefix such values with an apostrophe, while documenting that transformation. 6. Consider offering a strict CSV mode that treats every scraped value as text. 7. Add tests for commas, double quotes, CR/LF sequences, Unicode, and every common formula prefix. 8. Warn users that generated CSV files contain untrusted website data and should not be opened with formula execution enabled unless the content has been sanitized. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The declared description promises a broad AI-powered web scraper that can extract multiple content types from any website with automatic type detection. The supplied code chunk only implements an ArticleExtractor operating on already-provided content strings and a URL. It uses basic regex and line heuristics to pull article metadata and truncate content. There is no evidence of website fetching, scraping, AI-powered analysis, structure recognition, or support for lists/tables in this code. This is a materially narrower and different capability than described.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The declared description promises a broad web-scraping capability with intelligent structure recognition across multiple content types (lists, articles, tables). The supplied code chunk only implements a narrow ListExtractor operating on an input string already provided to it. Its behavior is limited to parsing JSON or splitting text lines, then applying regex/line-based heuristics to populate list item fields. There is no code for fetching web pages, traversing DOM structure, recognizing arbitrary website layouts, detecting content type, or extracting articles/tables. This is a material mismatch in primary purpose and capabilities rather than a mere supporting implementation detail.

Missing User Warnings

Low
Confidence
85% confidence
Finding
This markdown file describes web scraping, scrolling dynamic pages, and examples that save output to local files, but it does not include any user-facing warning about possible effects on privacy, site terms, or local data handling. Under the markdown criteria for missing user warnings, behaviors that can affect user data or system integrity should be disclosed.

Known Vulnerable Dependency: esbuild==0.27.3 — 1 advisory(ies): GHSA-g7r4-m6w7-qqqr (esbuild allows arbitrary file read when running the development server on Window)

Low
Category
Supply Chain
Confidence
90% confidence
Finding
The lockfile pins esbuild to 0.27.3, and this version is reported as affected by GHSA-g7r4-m6w7-qqqr. In this skill, esbuild is only a dev dependency pulled in via tsx, so the issue is less exposed in normal runtime use, but it is still a real supply-chain vulnerability if developers run affected esbuild development-server functionality on Windows.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"test": "tsx src/test.ts"
  },
  "dependencies": {
    "playwright": "^1.40.0",
    "zod": "^3.22.0"
  },
  "devDependencies": {
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Unpinned Dependencies

Low
Category
Supply Chain
Content
},
  "dependencies": {
    "playwright": "^1.40.0",
    "zod": "^3.22.0"
  },
  "devDependencies": {
    "@types/node": "^20.10.0",
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"zod": "^3.22.0"
  },
  "devDependencies": {
    "@types/node": "^20.10.0",
    "tsx": "^4.7.0",
    "typescript": "^5.3.0"
  }
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Unpinned Dependencies

Low
Category
Supply Chain
Content
},
  "devDependencies": {
    "@types/node": "^20.10.0",
    "tsx": "^4.7.0",
    "typescript": "^5.3.0"
  }
}
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"devDependencies": {
    "@types/node": "^20.10.0",
    "tsx": "^4.7.0",
    "typescript": "^5.3.0"
  }
}
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Static analysis

No suspicious patterns detected.