Back to skill

Security audit

Chrome Markdown to PDF

Security checks for vulnerabilities and agentic risk

Overview

This Markdown-to-PDF skill largely does what it advertises, but it renders untrusted Markdown in Chrome without sanitizing active HTML, which can leak document contents during conversion.

Review before installing if you may convert Markdown from emails, downloads, repositories, or other untrusted sources. Use it only on trusted Markdown unless the skill is updated to escape or sanitize HTML and prevent scripts or network requests during rendering.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/md2pdf.py:54
Finding

Unescaped Markdown Allows Active HTML Injection and Data Exfiltration

Content
View full analysis
\1", text) text = re.sub(r"\*(.+?)\*", r"\1", text) text = re.sub(r"`(.+?)`", r"\1", text) return text ``` The unescaped result is inserted into multiple HTML contexts: ```python if line.startswith("# "): close_table() parts.append(f"

{inline_format(line[2:])}

") elif line.startswith("## "): close_table() parts.append(f"

{inline_format(line[3:])}

") elif line.startswith("### "): close_table() parts.append(f"

{inline_format(line[4:])}

") elif line.startswith("#### "): close_table() parts.append(f"

{inline_format(line[5:])}

") elif line.startswith("|"): cells = [c.strip() for c in line.split("|")[1:-1]] # 检测分隔行(如 |---|---|---|) if all(set(c) <= set("-: ") for c in cells): # 分隔行不关闭表格,只跳过 if not in_table: # 没有表头直接遇到分隔行,跳过 pass continue if not in_table: parts.append("") parts.append("" + "".join(f"" for c in cells) + "") in_table = True else: parts.append("" + "".join(f"" for c in cells) + "") elif line.startswith("|-"): # 备用:以 |- 开头的分隔行 if not in_table: pass continue elif line.strip() == "---": close_table() parts.append("
") elif line.strip() == "": # 空行不关闭表格(表格内的空行在 Markdown 中不应断开表格) pass elif line.startswith("> "): parts.append(f"
{inline_format(line[2:])}
") else: close_table() parts.append(f"

{i ...[truncated 3097 chars]

{inline_format(c)}
{inline_format(c)}
Remediation
View remediation
``` - Validate the policy against the deployed Chrome version and retain operating-system-level network restrictions as defense in depth. 5. **Add security regression tests** - Verify that `
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (4)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill documentation invokes a local Python script and explicitly depends on Chrome headless, which implies shell execution and file access, but the skill declares no corresponding tool scope or permissions. This creates a mismatch between advertised behavior and declared capabilities, increasing the risk of over-privileged or unreviewed execution paths and making it harder for a platform to enforce least privilege.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The activation phrases include very generic terms such as '转PDF', '导出PDF', and '生成PDF', which can match many unrelated user requests beyond Markdown-to-PDF conversion. Over-broad triggers can cause unintended activation of a skill that reads files and launches shell commands, increasing the chance of surprising or unsafe execution in the wrong context.

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 strings that enforce a specific language for usage instructions and output messages. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is explicitly justified.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/md2pdf.py (reported line 152)May include surrounding context.

python
f"--print-to-pdf={pdf_path}",
        f"file://{html_path}",
    ]
    result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
    if not Path(pdf_path).exists():
        print(f"错误: PDF 生成失败", file=sys.stderr)
        print(result.stderr, file=sys.stderr)

Static analysis

No suspicious patterns detected.