Back to skill

Security audit

auto-md2img

Security checks for vulnerabilities and agentic risk

Overview

This Markdown-to-image skill matches its stated purpose, but it needs Review because it renders user Markdown in an unsandboxed browser and overstates its file path and size protections.

Install only if you trust the Markdown being converted or can run it in a contained environment. Avoid feeding it untrusted user Markdown, do not run it with elevated privileges, choose a dedicated output directory, keep debug mode off for private content, and be aware that the documented security limits are not actually enforced in the inspected script.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/md_to_png.js:458
Finding

Untrusted Markdown Is Rendered as Active HTML in an Unsandboxed Browser

Content
View full analysis
${html}`, { waitUntil: 'networkidle0' }); ``` ```javascript const browser = await puppeteer.launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'], headless: true }); const page = await browser.newPage(); await page.setContent(fullHtml, { waitUntil: 'networkidle0' }); ``` ```javascript // Convert to HTML const htmlContent = marked.parse(pageContentWithFooter); // Generate output path let pageOutputPath; ``` ### Technical Analysis The application parses attacker-controllable Markdown through `marked.parse()` and inserts the resulting HTML directly into a live Chromium document. No HTML sanitizer, Content Security Policy, request interception, URL allowlist, JavaScript disabling, or network isolation is applied. Raw HTML supported by the Markdown parser can therefore introduce active elements such as scripts, iframes, event handlers, and remote resources. Ordinary Markdown image syntax can also cause Chromium to request an attacker-selected URL. Because `page.setContent()` waits for network activity, these requests occur both during block-height measurement and final image rendering. This permits blind server-side request forgery against services reachable from the host, including loopback and private-network endpoints. Same-origin restrictions may prevent direct reading of many responses, but they do not prevent outbound requests or state-changing requests to poorly protected internal services. Attacker-controlled browser code can also consume reso ...[truncated 1995 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/md_to_png.js:480
Finding

Caller-Controlled Output Path Permits Writes Outside the Intended Output Directory

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/md_to_png.js:663
Finding

Missing Input and Rendering Limits Allow Resource-Exhaustion Denial of Service

Content
View full analysis
${html}`, { waitUntil: 'networkidle0' }); const elementHandle = await page.$('div'); const { height } = await elementHandle.boundingBox(); await elementHandle.dispose(); const blockHeight = Math.ceil(height); blockHeights.push({ content: block, height: blockHeight, index: i }); totalHeight += blockHeight; debugLog(`Content block ${i + 1}/${blocks.length} height: ${blockHeight}px`); } ``` ```javascript await page.setViewport({ width: 900, height: imageHeight, deviceScaleFactor: 2 }); // Ensure directory exists ensureDirExists(outputPath); const ext = path.extname(outputPath).toLowerCase(); const isJpeg = ext === '.jpg' || ext === '.jpeg'; const screenshotOptions = { path: outputPath, fullPage: true, type: isJpeg ? 'jpeg' : 'png' }; ``` ```javascript const mdContent = fs.readFileSync(inputPath, 'utf8'); ``` ### Technical Analysis The entire input file is loaded synchronously into memory without checking its byte size. No limit is enforced on the number of lines, content blocks, pages, rendered height, image dimensions, processing duration, or output size. Height-based pagination renders every content block separately to measure it and then renders the assembled pages again. This creates work proportional to the number of blocks and may cause many expensive Chromium document loads. Pagination can also be disabled by setting a non-positive threshold, permitting c ...[truncated 1657 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (46)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 41)May include surrounding context.

md
2. Call `scripts/md_to_png.js` to generate images

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 50)May include surrounding context.

md
2. Call `scripts/md_to_png.js` to generate images

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 53)May include surrounding context.

md
2. Call `scripts/md_to_png.js` to generate images

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 56)May include surrounding context.

md
2. Call `scripts/md_to_png.js` to generate images

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 59)May include surrounding context.

md
2. Call `scripts/md_to_png.js` to generate images

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 62)May include surrounding context.

md
2. Call `scripts/md_to_png.js` to generate images

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 65)May include surrounding context.

md
2. Call `scripts/md_to_png.js` to generate images

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 68)May include surrounding context.

md
2. Call `scripts/md_to_png.js` to generate images

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 114)May include surrounding context.

md
2. Call `scripts/md_to_png.js` to generate images

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 116)May include surrounding context.

md
2. Call `scripts/md_to_png.js` to generate images

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 140)May include surrounding context.

md
2. Call `scripts/md_to_png.js` to generate images

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 174)May include surrounding context.

md
2. Call `scripts/md_to_png.js` to generate images

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 177)May include surrounding context.

md
2. Call `scripts/md_to_png.js` to generate images

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 180)May include surrounding context.

md
2. Call `scripts/md_to_png.js` to generate images

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 187)May include surrounding context.

md
2. Call `scripts/md_to_png.js` to generate images

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 276)May include surrounding context.

md
2. Call `scripts/md_to_png.js` to generate images

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 282)May include surrounding context.

md
2. Call `scripts/md_to_png.js` to generate images

Instruction Override

High
Category
Prompt Injection
Confidence
70% confidence
Finding

This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 67)May include surrounding context.

Disable pagination entirely (output single image)

node scripts/md_to_png.js input.md ./output --height 0

Enable Debug mode (output detailed logs + save pagination content)

node scripts/md_to_png.js input.md ./output --debug

text

Instruction Override

High
Category
Prompt Injection
Confidence
70% confidence
Finding

This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 80)May include surrounding context.

Disable pagination entirely (output single image)

node scripts/md_to_png.js input.md ./output --height 0

Enable Debug mode (output detailed logs + save pagination content)

node scripts/md_to_png.js input.md ./output --debug

text

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill description is written entirely in Chinese and presents the behavior and usage instructions in that language only. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is clearly documented and justified, which is not present here.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The feature list says '自动缓存清理,保护隐私,无残留文件', and the security section repeats '自动清理临时文件,无残留'. However, the debug-mode section states that the tool saves per-page Markdown files and detailed debug log files, which is a direct contradiction to the 'no residual files' claim.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The security section states '路径遍历防护,禁止输出到非指定目录', implying the tool enforces output-directory restrictions. Elsewhere, the README documents user-controlled output paths such as 'output.png' or '/tmp/output/' without identifying any configured allowed directory or validation behavior, so the documentation contradicts itself about whether output location is restricted.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · README.md (reported line 124)May include surrounding context.

  1. Linux 环境下可能需要安装额外的字体和依赖:
    bash
    # Ubuntu/Debian
    sudo apt install fonts-wqy-microhei fonts-wqy-zenhei fonts-noto-color-emoji libnss3 libxss1 libasound2
    

🤝 贡献

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · SKILL-CN.md (reported line 264)May include surrounding context.

  1. Linux 环境下可能需要安装额外的字体和依赖:
    bash
    # Ubuntu/Debian
    sudo apt install fonts-wqy-microhei fonts-wqy-zenhei fonts-noto-color-emoji libnss3 libxss1 libasound2
    

🤝 贡献

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger scope is extremely broad: it claims applicability to essentially all Markdown-output scenarios, which increases the chance the skill is invoked automatically in contexts where image rendering is unnecessary, costly, or inappropriate. In an agent setting, over-broad activation can cause unintended file creation, external tool execution, and degraded transparency to users about why content was transformed.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.