Back to skill

Security audit

Markdown → 图片卡片

Security checks for vulnerabilities and agentic risk

Overview

This skill makes image cards, but it can quietly fetch links, read referenced local files, and erase output folders, so it needs review before installing.

Install only if you will render trusted Markdown and can run it in a constrained environment. Avoid processing untrusted Markdown, avoid custom --output paths, and use a dedicated disposable output folder. The publisher should add path confinement, non-destructive output handling, remote-fetch opt-in with allowlists and size limits, HTML sanitization/CSP, request blocking, dependency updates, and sandboxed browser execution before this is treated as low risk.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
src/markdown-parser.js:39
Finding

Unrestricted Remote Image Retrieval Enables Server-Side Request Forgery and Resource Exhaustion

Content
View full analysis
{ if (response.statusCode === 200) { const fileStream = fs.createWriteStream(localPath); response.pipe(fileStream); fileStream.on('finish', () => { fileStream.close(); resolve(localPath); }); fileStream.on('error', (err) => { fs.unlink(localPath, () => {}); reject(err); }); } else { reject(new Error(`下载图片失败: ${url} (状态码: ${response.statusCode})`)); } }).on('error', (err) => { reject(new Error(`下载图片失败: ${url} (${err.message})`)); }); ``` ```js if (imagePath.startsWith('http://') || imagePath.startsWith('https://')) { try { console.log(` 下载远程图片: ${imagePath}`); absolutePath = await downloadImage(imagePath); ``` ### Technical Analysis Remote image URLs are taken directly from Markdown and passed to Node.js HTTP clients. The implementation does not restrict destination hosts, resolve and reject private IP ranges, validate redirects, impose a response-size limit, or configure an effective request timeout. Consequently, a Markdown document can cause the host to send HTTP GET requests to arbitrary destinations accessible from the execution environment. Relevant targets include: - Loopback interfaces such as `127.0.0.1` and `::1` - Private network ranges - Link-local services - Cloud instance metadata endpoints - Internal administrative interfaces - Attacker-controlled tracking servers The response body is streamed directly to disk. A server that returns an extremely large or indefinitely streaming response can consume disk space, network bandwidth, and process resources. ### Attack Path 1. An attacker supplies or influences a Markdown docu ...[truncated 1143 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/generator.js:175
Finding

User-Controlled Output Paths Can Cause Arbitrary Recursive Directory Deletion

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/generator.js:646
Finding

Unsanitized Markdown HTML Executes in a Sandbox-Disabled Browser

Content
View full analysis
${marked.parseInline(token.text)}`; ``` ```js const htmlContent = `

${marked.parseInline(textContent)}

`; blocks.push({ type: 'html', content: htmlContent, isAtomic: false }); ``` The resulting HTML is inserted directly into the rendered document: ```js for (const block of blocks) { if (block.type === 'html') { contentHtml += `
${block.content}
`; } else if (block.type === 'image') { contentHtml += `
${block.alt || ''}
`; } } const html = template .replace('{{content}}', contentHtml) .replace(/{{pageNumber}}/g, String(pageNumber).padStart(2, '0')) .replace(/{{totalPages}}/g, String(totalPages).padStart(2, '0')) .replace(/{{pageFormat}}/g, pageFormat); await page.setContent(html, { waitUntil: 'load', timeout: 120000 }); ``` Chromium is launched without its sandbox: ```js const browser = await puppeteer.launch({ headless: true, executablePath: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', args: ['--no-sandbox', '--disable-setuid-sandbox'] }); ``` Mermaid rendering also uses a permissive security mode: ```js mermaid.initialize({ startOnLoad: false, theme: 'neutral', securityLevel: 'loose', fontSize: 32, flowchart: { useMaxWidth: true, htmlLabels: true } }); ``` ### Technical Analysis Markdown-derived HTML is embedded into a complete browser document and loaded using `page.setContent()`. No HTML sanitizer, restrictive Content Security Policy, or browser ...[truncated 1991 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
src/markdown-parser.js:200
Finding

Markdown Image Paths Permit Unauthorized Local File Reads

Content
View full analysis
Remediation
View remediation
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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (46)

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

The implementation reportedly goes beyond simple rendering by reading arbitrary local files, deleting and recreating output directories, using a fixed Chrome path, and enabling Mermaid rendering with loose security mode. These behaviors materially expand risk: arbitrary file access can expose unintended local data, destructive output handling can remove user files, and loose Mermaid security may enable script-like or unsafe embedded content during rendering.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The implementation reportedly goes beyond simple rendering by reading arbitrary local files, deleting and recreating output directories, using a fixed Chrome path, and enabling Mermaid rendering with loose security mode. These behaviors materially expand risk: arbitrary file access can expose unintended local data, destructive output handling can remove user files, and loose Mermaid security may enable script-like or unsafe embedded content during rendering.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: basic-ftp==5.2.0 — 4 advisory(ies): GHSA-6v7q-wjvx-w8wg (basic-ftp: Incomplete CRLF Injection Protection Allows Arbitrary FTP Command Exe); CVE-2026-39983 (basic-ftp has FTP Command Injection via CRLF); CVE-2026-41324 (basic-ftp vulnerable to denial of service via unbounded memory consumption in Cl) +1 more

High
Category
Supply Chain
Confidence
80% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: js-yaml==4.1.1 — 4 advisory(ies): CVE-2026-84375 (js-yaml: maxTotalMergeKeys does not limit CPU use for empty merge sources); CVE-2026-59869 (js-yaml: YAML merge-key chains can force quadratic CPU consumption); GHSA-5p4m-2wfm-xmqj (JS-YAML: Quadratic CPU consumption in !!omap resolution (3.x and 4.x) — CVE-2026) +1 more

High
Category
Supply Chain
Confidence
80% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: extract-zip==2.0.1 — 2 advisory(ies): CVE-2026-19693 (extract-zip allows arbitrary file writes through symlink archive entries); CVE-2026-56876 (extract-zip unvalidated symlink path traversal)

High
Category
Supply Chain
Confidence
80% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: ip-address==10.1.0 — 2 advisory(ies): CVE-2026-69192 (ip-address: Address4 decodes leading-zero octets as decimal while resolvers deco); CVE-2026-42338 (ip-address has XSS in Address6 HTML-emitting methods)

High
Category
Supply Chain
Confidence
80% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: ws==8.19.0 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
80% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding

The skill directs reading Markdown files, running a local Node script, and the referenced implementation reportedly uses environment, file access, and network capabilities, yet the skill declares no explicit tool scope or permissions. This creates a least-privilege failure: the agent may invoke broader capabilities than users or reviewers expect, especially because the workflow says to 'directly execute' and read full files before prompting.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger phrases are broad enough to match ordinary requests, which increases the chance the skill activates in situations the user did not clearly intend. In this skill, that matters because activation leads to automatic file reading and output generation, so over-triggering can cause unnecessary file access or side effects.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The skill specifies automatic output to ~/Downloads// without a user-facing warning. Writing files to a common personal directory can expose generated content to other local processes, overwrite prior outputs if naming collides, and create privacy surprises if the Markdown contains sensitive information.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The generated HTML imports Google Fonts and the workflow may also load externally hosted images, causing outbound network requests during what appears to be a local Markdown-to-image conversion. This can leak usage metadata and potentially sensitive content-derived URLs to third parties without an explicit user opt-in, which is a real security/privacy issue even if the feature was added for aesthetics.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Rendering the HTML causes remote fetches such as Google Fonts without a clear warning to the user. Silent outbound requests are dangerous in automation contexts because they violate user expectations of local processing and can leak operational metadata or fail unpredictably in restricted environments.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script scans Markdown for YouTube URLs and automatically transforms them into thumbnail fetches, which extends behavior beyond simple Markdown rendering into content-driven network activity. Because the trigger is embedded in user content rather than an explicit option, users may unknowingly cause external requests and metadata disclosure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The tool derives a YouTube thumbnail URL from Markdown content and uses it during rendering without clearly notifying the user that their input can trigger network access. In a skill expected to process local files, this creates a privacy and transparency issue and could expose document-derived links or usage patterns externally.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This code file contains natural-language content that fixes the skill's user-facing behavior to Chinese, including Chinese-only descriptions and messages. Under the policy rule, forcing a specific language or locale without opt-in is a violation unless the constraint is clearly justified as region-specific, which is not present here.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill’s stated purpose is local Markdown-to-image conversion, but this code performs outbound network requests to third-party services (noembed.com and YouTube image hosts) during conversion. Unexpected network access expands the trust boundary, can leak user-supplied URLs and metadata to external services, and creates a dependency on remote content for a task that users may reasonably expect to be local-only.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This helper can download arbitrary URLs to an arbitrary local path, which is broader than the advertised Markdown-to-image role. Even though it is not invoked in the current flow, retaining generic download functionality in a skill increases the chance of future misuse, SSRF-style access to internal resources if wired up later, or unintended overwrites if save paths are attacker-controlled.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The HTML output explicitly sets lang="zh-CN", which fixes the rendered artifact to a specific locale. The file does not provide any user choice or documented justification for this locale restriction, so it matches the natural-language policy violation criteria.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill reads local files for every Markdown image block via fs.readFile(block.content) without constraining the path. A crafted Markdown file can therefore cause the agent to ingest arbitrary local files and embed their contents into generated output, which is especially dangerous because this skill is explicitly designed to process untrusted Markdown content.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code resolves an output path from user-controllable input and then unconditionally deletes it with fs.rm(..., { recursive: true, force: true }) before generation. In an agent skill context, this can erase arbitrary local directories if outputDir is influenced by the user or upstream automation, causing destructive data loss beyond the skill's intended scope.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The recursive deletion of the resolved output directory occurs silently, with no user warning, prompt, or dry-run safeguard. In an interactive agent workflow, users may not realize that converting Markdown to images can destroy preexisting files, making accidental destructive behavior materially more dangerous.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The command description, option help text, and runtime messages are presented only in Chinese, which imposes a specific language on all users. The file does not offer any language selection or indicate that the tool is intended only for a Chinese-language context.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The parser performs unrestricted outbound HTTP/HTTPS fetches on attacker-controlled Markdown image URLs, creating an SSRF-style primitive and allowing access to internal or unexpected network destinations. Because this occurs during content parsing, a user can trigger network activity simply by supplying Markdown, which expands the attack surface beyond ordinary rendering.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The file-level comments and exported parser API describe parsing Markdown and extracting content blocks, which implies local transformation of Markdown input. In addition to parsing, the code dereferences remote image URLs via HTTP/HTTPS and persists them under .temp-images, which is materially broader behavior than parsing alone.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This file contains natural-language comments and console output in Chinese, including operational messages shown during downloads and error handling. Under the policy, forcing a specific language without user opt-in or a documented regional justification is a locale/language policy violation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.