Back to skill

Security audit

md-to-pdf

Security checks for vulnerabilities and agentic risk

Overview

This Markdown-to-PDF skill does what it claims, but its converter renders untrusted Markdown as active browser content with browser sandboxing disabled and unrestricted network access.

Install only if you will convert trusted Markdown or run it in an isolated environment. Avoid using it on files from other people until it disables JavaScript, sanitizes HTML, blocks unexpected network requests, and stops disabling the browser sandbox.

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
convert.js:35
Finding

Untrusted Markdown Is Rendered in a Browser with Sandbox Protections Disabled

Content
View full analysis
${htmlContent} ``` ```javascript const browser = await puppeteer.launch({ executablePath: browserPath, headless: 'new', args: [ '--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage', '--disable-gpu', '--no-first-run', '--no-default-browser-check', '--disable-extensions' ] }); ``` ### Technical Analysis The input Markdown file is entirely user-controlled. It is converted to HTML through `marked` and inserted directly into the page document without HTML sanitization. The reviewed configuration does not disable raw HTML or JavaScript execution. Consequently, Markdown containing active HTML elements, scripts, event handlers, iframes, or other browser-interpreted content may execute when Puppeteer calls `page.setContent()`. The browser is also started with both `--no-sandbox` and `--disable-setuid-sandbox`. These flags disable important operating-system isolation boundaries normally used to contain compromised browser renderer processes. Although browser-side script execution alone does not automatically grant operating-system code execution, disabling the sandbox materially increases the impact of a browser vulnerability or malicious browser-exploit payload. ### Attack Path 1. An attacker creates or modifies a Markdown file containing active HTML or JavaScript, such as a script element, event handler, iframe, or browser-exploit payload. 2. The victim invokes `node convert.js attacker-controlled.md`. 3. `fs.readFileSync()` reads the untrusted document. 4. `marked()` converts the document while allowing acti ...[truncated 1057 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
convert.js:127
Finding

Markdown Conversion Allows Unrestricted Outbound and Internal Resource Requests

Content
View full analysis
${htmlContent} ``` ```javascript const page = await browser.newPage(); await page.setContent(fullHtml, { waitUntil: 'networkidle0' }); ``` ### Technical Analysis URLs embedded in Markdown or raw HTML are rendered by a real browser. The implementation does not intercept requests, restrict permitted protocols, validate destination addresses, or apply a domain allowlist. An attacker-controlled document can therefore cause the conversion host to request remote or internal resources through images, scripts, stylesheets, iframes, media, or other browser-supported elements. This can expose the converter's public IP address and request metadata, trigger tracking endpoints, or reach HTTP services available from the converter's network. Browser same-origin and CORS controls may prevent an attacker-controlled script from reading many cross-origin responses. They do not reliably prevent blind requests, resource loads, state-changing GET requests, or disclosure through attacker-observed callbacks. Therefore, the issue can support blind SSRF-style behavior even where response contents cannot be read. Using `waitUntil: 'networkidle0'` also allows a malicious page to prolong conversion through recurring or deliberately slow network activity until Puppeteer's timeout is reached. ### Attack Path 1. An attacker supplies a Markdown document containing a reference to an attacker-controlled URL, loopback address, private-network host, link-local endpoint, or slow resource. 2. The victim converts the document using `convert.js`. 3. The URL survives Markdown conversion or is su ...[truncated 1052 chars]
Remediation
View remediation
{ const url = new URL(request.url()); if (url.protocol === 'data:' || url.protocol === 'about:') { request.continue(); return; } request.abort(); }); ``` 3. If remote resources are required, permit only explicitly approved HTTPS origins. 4. Resolve destination hostnames and block loopback, private, link-local, multicast, and reserved IP ranges for both IPv4 and IPv6. 5. Revalidate every redirect destination to prevent allowlist bypasses. 6. Reject dangerous or unnecessary schemes such as `file:`, `javascript:`, `ftp:`, and custom protocols. 7. Apply connection timeouts, response-size limits, document-size limits, and an overall conversion deadline. 8. Prefer downloading approved images through a hardened fetcher, validating their content type and size, and embedding them as local or `data:` resources. 9. Combine request controls with HTML sanitization and JavaScript disabling so raw HTML cannot introduce additional network-capable elements. ]]>
Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (2)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The overall primary purpose matches markdown-to-PDF conversion with styling. However, two material parts of the declared description are not supported by the implementation: syntax/code highlighting is not implemented, and CJK support is not specifically handled. The browser path discovery and PDF generation are supporting details consistent with the conversion task, not separate mismatched capabilities.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.