Back to skill

Security audit

Huo15 Markdown Export

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it advertises, but it grants broad local publishing/install authority and renders active Markdown content in ways users should review before installing.

Install only if you are comfortable with a Markdown publishing tool that can render active HTML, fetch remote Mermaid code unless disabled, create public share links through another plugin, archive source documents locally, and install itself across multiple OpenClaw workspaces. Use it only on trusted Markdown, prefer --no-mermaid for sensitive/offline rendering, avoid previewing confidential files on shared networks, use --no-archive for sensitive documents, and run the workspace installer only after a dry run and backup.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
Findings (6)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/lib/render.js:53
Finding

Untrusted Markdown Executes Active Content in a No-Sandbox Browser

Content
View full analysis
Remediation
View remediation

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/lib/render.js:188
Finding

Runtime Execution of Mutable JavaScript from an External CDN

Content
View full analysis
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs'; mermaid.initialize({ startOnLoad: true, securityLevel: 'loose' }); ` : ''; ``` ### Technical Analysis Generated documents dynamically import Mermaid JavaScript from jsDelivr whenever Mermaid support is enabled. The URL pins only the major version (`@10`), so the actual executed file can change after the Skill has been reviewed or installed. Because the import occurs inside generated HTML, the remote payload executes in the Puppeteer renderer and in browsers that open exported HTML. No Subresource Integrity validation is available for this dynamic module import, and the configuration explicitly selects Mermaid's permissive `securityLevel: 'loose'`. This makes the effective executable payload dependent on external CDN and package-registry state. ### Attack Path 1. A user renders a Markdown document while Mermaid support is enabled. 2. The generated HTML imports the current `mermaid@10` module from jsDelivr. 3. Puppeteer or the user's browser downloads the remote module at rendering or viewing time. 4. If the CDN, package publication, DNS path, or upstream package version is compromised, modified JavaScript executes in the document context. 5. The payload can access rendered document content and issue network requests from the rendering host or viewer's browser. ### Impact Assessment A compromised remote module could: - Read and exfiltrate the full rendered document. - Send requests to internal or external services from the renderer. - Alter generated output or inject misleading content. - Exploit the browser runtime, with greater consequences in the no-sandbox Puppeteer workflo ...[truncated 182 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/md-preview.js:62
Finding

Live Preview Server Binds to All Network Interfaces and Serves Active Content

Content
View full analysis
{ if (req.url === '/__sig') { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end(readSig()); return; } if (req.url.startsWith('/__theme/')) { const t = req.url.slice('/__theme/'.length); if (AVAILABLE_THEMES.includes(t)) theme = t; res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('ok'); return; } try { const md = fs.readFileSync(absInput, 'utf8'); const html = buildHtml({ markdown: md, theme, title: path.basename(absInput, '.md'), includePrint: false, includeMermaid: true, }); res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); res.end(html.replace( '', `${banner}${RELOAD_SCRIPT}` )); } catch (e) { res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' }); res.end(String(e)); } }); server.listen(port, () => { console.error(`live preview: http://127.0.0.1:${port}/`); }); ``` ### Technical Analysis `server.listen(port)` omits an explicit hostname. In Node.js this normally binds to the unspecified address, making the service reachable through available IPv4 or IPv6 network interfaces. The status message misleadingly advertises a loopback URL even though the listener is not explicitly restricted to loopback. The server has no authentication or access token. Every request can retrieve the rendered Markdown, and the theme-changing endpoint accepts state-changing GET requests. Because the shared renderer permits raw HTML and remote Mermaid JavaScript, the preview also serves active attacker-controlled content. No defensive response headers, such as Content Security Policy, frame restrictions, or MIME ...[truncated 1043 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/install-to-workspaces.sh:68
Finding

Workspace Installer Destructively Replaces Skill Directories Across Agent Contexts

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
package.json:14
Finding

Dependency Installation Is Not Reproducibly Pinned

Content
View full analysis
/dev/null; then npm install --no-audit --no-fund --loglevel=error fi ``` ### Technical Analysis The package manifest uses caret ranges, allowing dependency versions to change on later installations. No lockfile was present in the audited project structure, so npm cannot reproduce an exact reviewed dependency graph. The installation command also disables npm audit reporting. This does not itself install malicious software, but it removes a standard source of vulnerability information during setup. Puppeteer is especially security-sensitive because its installation can retrieve browser components and its runtime processes attacker-influenced HTML. ### Attack Path 1. A user runs the documented dependency installation script. 2. npm resolves the newest versions permitted by the caret ranges. 3. The resolved dependency tree differs from the versions examined during the Skill audit. 4. A compromised maintainer release, registry account, transitive dependency, or vulnerable update is installed. 5. Dependency installation hooks or runtime code execute with the invoking user's privileges. ### Impact Assessment A dependency supply-chain compromise can obtain all privileges of the user running `npm install` or the ...[truncated 278 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/md-share.sh:193
Finding

Share JSON and Archive YAML Are Constructed with Unescaped User-Controlled Values

Content
View full analysis
", "label": "", "expireHours": $EXPIRE_HOURS } } ], "ai_instruction": "$PREFER_NOTE" } EOF ``` ```bash { echo "---" echo "title: ${LABEL}" echo "slug: ${SLUG}" echo "published_at: ${TODAY}" echo "source: ${ABS_INPUT}" echo "summary: \"${SUMMARY}\"" echo "render_outputs:" echo "$SHARE_JSON" | python3 -c ' import json, sys j = json.load(sys.stdin) for f in j.get("files", []): print(f" - kind: {f[\"kind\"]}") print(f" path: {f[\"path\"]}") print(f" size_kb: {f[\"size_kb\"]}") print(f" theme: {f.get(\"theme\",\"\")}") ' echo "share_urls: []" echo "tags: [review, export]" echo "---" cat "$ABS_INPUT" } > "$KB_ARCHIVE_PATH" ``` ### Technical Analysis Although individual file entries are partially JSON-encoded earlier in `md-share.sh`, the final JSON document interpolates several values directly. These include the absolute input path, output directory, expiration value, preference note, and instruction text. A path containing quotes, backslashes, or control characters can make the JSON invalid or alter its structure. The expiration value is inserted as a raw JSON token without numeric validation. The publication archive similarly interpolates labels, paths, summaries, and rendered-output properties into YAML without using a YAML ...[truncated 1552 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • 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 (82)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared purpose is markdown export/publishing, but the documented file list and behavior reference install/deployment scripts that modify multiple workspaces, create symlinks, delete paths during cleanup, and bootstrap dependencies. This exceeds user expectations for a rendering skill and can lead to unintended filesystem changes or destructive operations if the skill is auto-selected for ordinary export requests.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/md2pdf-puppet.js examples/sample.md # → examples/sample.pdf

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/md2pdf-puppet.js examples/sample.md # → examples/sample.pdf

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/md2pdf-puppet.js examples/sample.md # → examples/sample.pdf

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/md2pdf-puppet.js examples/sample.md # → examples/sample.pdf

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/md2pdf-puppet.js examples/sample.md # → examples/sample.pdf

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/md-preview.js examples/sample.md # 浏览器开 http://127.0.0.1:7777

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
> 1. AI 调 `bash scripts/md-share.sh report.md --mode pdf --label "Q1 复盘报告"`(默认 `--prefer file`)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
> 1. AI 调 `bash scripts/md-share.sh report.md --mode pdf --label "Q1 复盘报告"`(默认 `--prefer file`)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
> 1. AI 调 `bash scripts/md-share.sh report.md --mode pdf --label "Q1 复盘报告"`(默认 `--prefer file`)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
> 1. AI 调 `bash scripts/md-share.sh report.md --mode pdf --label "Q1 复盘报告"`(默认 `--prefer file`)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
> 1. AI 调 `bash scripts/md-share.sh report.md --mode pdf --label "Q1 复盘报告"`(默认 `--prefer file`)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
> 1. AI 调 `bash scripts/md-share.sh report.md --mode pdf --label "Q1 复盘报告"`(默认 `--prefer file`)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
> 1. AI 调 `bash scripts/md-share.sh report.md --mode pdf --label "Q1 复盘报告"`(默认 `--prefer file`)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
> 1. AI 调 `bash scripts/md-share.sh report.md --mode pdf --label "Q1 复盘报告"`(默认 `--prefer file`)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
> 1. AI 调 `bash scripts/md-share.sh report.md --mode pdf --label "Q1 复盘报告"`(默认 `--prefer file`)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
> 1. AI 调 `bash scripts/md-share.sh report.md --mode pdf --label "Q1 复盘报告"`(默认 `--prefer file`)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
> 1. AI 调 `bash scripts/md-share.sh report.md --mode pdf --label "Q1 复盘报告"`(默认 `--prefer file`)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
> 1. AI 调 `bash scripts/md-share.sh report.md --mode pdf --label "Q1 复盘报告"`(默认 `--prefer file`)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
> 1. AI 调 `bash scripts/md-share.sh report.md --mode pdf --label "Q1 复盘报告"`(默认 `--prefer file`)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
> 1. AI 调 `bash scripts/md-share.sh report.md --mode pdf --label "Q1 复盘报告"`(默认 `--prefer file`)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/install-to-workspaces.sh (reported line 72)May include surrounding context.

sh
# 清单层幽灵(workspace/skills/<slug>)
  if [[ -e "$outer/$SLUG" && "$outer/$SLUG" != "$target" ]]; then
    rm -rf "$outer/$SLUG"
    echo "  🗑 cleared stale single-layer: $outer/$SLUG"
  fi

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/install-to-workspaces.sh (reported line 115)May include surrounding context.

sh
# 清单层幽灵(workspace/skills/<slug>)
  if [[ -e "$outer/$SLUG" && "$outer/$SLUG" != "$target" ]]; then
    rm -rf "$outer/$SLUG"
    echo "  🗑 cleared stale single-layer: $outer/$SLUG"
  fi

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README explicitly describes a workflow that exposes rendered documents through public URLs and emphasizes easy delivery to enterprise chat platforms, but it does not prominently warn users that document contents may become externally accessible. In a skill intended for AI-orchestrated sharing, this omission can cause users or agents to publish sensitive internal reports, proposals, or customer materials beyond the intended audience.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The publishing workflow documents automatic archival of source content and later write-back of generated share URLs into a persistent knowledge-base path, but it does not clearly warn that both document data and access links are retained on disk. This creates a confidentiality and retention risk, especially for sensitive business content, because users may not realize the skill leaves durable artifacts that can be discovered, reused, or exfiltrated later.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.