Back to skill

Security audit

Markdown Mobile Export

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does the advertised Markdown-to-image export, but it can automatically install packages and a browser and can render active untrusted HTML in Chromium.

Install only if you are comfortable with the skill modifying the Python environment, downloading browser components when needed, and rendering Markdown in a browser. Prefer using it in an isolated environment with dependencies preinstalled, and avoid processing Markdown from untrusted sources unless raw HTML and remote network requests are disabled or sandboxed.

Vulnerability Patterns
  • 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
  • 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 (2)

T08 · Insecure Dependencies

Warning
Location
scripts/export_long_image.py:14
Finding

Automatic Installation of Unpinned Runtime Dependencies

Content
View full analysis
None: ensure_commands = [ [sys.executable, "-m", "ensurepip", "--upgrade"], ] install_commands = [ [sys.executable, "-m", "pip", "install", package_name], ] uv_path = shutil.which("uv") if uv_path: install_commands.append([uv_path, "pip", "install", "--python", sys.executable, package_name]) for ensure_command in ensure_commands: subprocess.run(ensure_command, check=False) last_error: Exception | None = None for command in install_commands: try: subprocess.run(command, check=True) return except Exception as exc: # noqa: BLE001 last_error = exc if last_error is not None: raise last_error ``` ```python def ensure_playwright_module() -> None: try: importlib.import_module("playwright.sync_api") return except ImportError: pass _run_install("playwright") importlib.import_module("playwright.sync_api") def install_playwright_browser() -> None: subprocess.run( [sys.executable, "-m", "playwright", "install", "chromium"], check=True, ) def ensure_pillow() -> None: try: importlib.import_module("PIL.Image") return except ImportError: pass _run_install("pillow") importlib.import_module("PIL.Image") ``` The renderer contains an equivalent installer in `scripts/render_markdown_mobile_long_image.py`: ```python def _run_install(package_name: str) -> None: ensure_commands = [ [sys.executable, "-m", "ensurepip", "--upgrade"], ] install_commands = [ ...[truncated 3013 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/render_markdown_mobile_long_image.py:667
Finding

Untrusted Markdown Can Execute Active HTML and Initiate Browser Requests

Content
View full analysis
{title} {css}
{content}
""" ``` Raw HTML is explicitly enabled: ```python def build_markdown_renderer() -> MarkdownIt: ensure_markdown_it() from markdown_it import MarkdownIt return ( MarkdownIt("commonmark", {"html": True, "linkify": True, "breaks": True}) .enable("table") .enable("strikethrough") ) ``` The rendered content and inferred title are inserted without an HTML sanitizer. The inferred title is also not escaped: ```python def render_markdown_text(markdown_text: str, title_hint: str = "") -> str: renderer = build_markdown_renderer() rendered = renderer.render(markdown_text) title = infer_title(markdown_text, title_hint=title_hint) content_html = enhance_rendered_html(rendered) return HTML_TEMPLATE.format(title=title, css=CSS, content=content_html) def infer_title(markdown_text: str, title_hint: str = "") -> str: for line in markdown_text.splitlines(): stripped = line.strip() if stripped.startswith("# "): return stripped[2:].strip() return title_hint or "Markdown Long Image" ``` The resulting local document is loaded in a browser without request interception or network isolation: ```python ...[truncated 4003 chars]
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
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (19)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The documented behavior does not match the detected implementation behavior, including undeclared package installation and subprocess execution. Behavior mismatch is security-relevant because operators may approve a seemingly simple markdown export skill while it actually performs additional execution and environment modification that can expand attack surface or enable supply-chain abuse.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script can install Python packages at runtime using pip and uv, a powerful capability not necessary for the core task and not clearly disclosed. In this skill context, that makes the behavior more dangerous because users expect local content conversion, not arbitrary dependency bootstrap with network retrieval and execution of third-party package code.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

Installing a browser binary at runtime materially expands the skill's operational footprint and trust boundary. For a local export tool, downloading executable browser components without prior disclosure creates unnecessary supply-chain, persistence, and policy-compliance risks.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script silently installs Python packages at runtime by invoking pip/uv, which introduces uncontrolled code execution from external package sources during a content-rendering task. In the context of a local Markdown conversion skill, this is unnecessarily dangerous because execution now depends on network, package index trust, environment state, and PATH resolution, expanding the attack surface well beyond rendering user content.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill advertises operational behavior that implies file read, file write, and shell execution, but it does not declare any explicit tool scope or permissions boundary. This increases the chance an agent will invoke it with broader-than-expected capabilities, making unintended filesystem access or command execution harder to review and constrain.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill retains generated HTML sidecar files and normalized markdown on disk without a clear warning to the user. If the markdown contains sensitive notes, reports, credentials, or proprietary content, those residual files can persist in locations users do not expect and may later be exposed through local access, backups, or other processes.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Automatic pip/uv installation without user-facing warning is unsafe because it performs networked environment changes under the guise of a simple export action. The lack of confirmation or disclosure prevents informed consent and can violate least-privilege expectations for local content-processing tools.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
88% confidence
Finding

This subprocess call invokes ensurepip automatically, altering the Python environment without prompting the user. In the context of a local Markdown/image export skill, unexpected package-management behavior is dangerous because it expands execution beyond file conversion into environment mutation and can enable downstream unreviewed package installation.

Content

Scanner excerpt · scripts/export_long_image.py (reported line 26)May include surrounding context.

python
install_commands.append([uv_path, "pip", "install", "--python", sys.executable, package_name])

    for ensure_command in ensure_commands:
        subprocess.run(ensure_command, check=False)

    last_error: Exception | None = None
    for command in install_commands:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
91% confidence
Finding

This subprocess call performs automatic package installation via pip or uv during normal execution. Even without command injection, runtime installation introduces supply-chain risk, network access, and unanticipated system changes that are not justified by the stated purpose of a simple export utility.

Content

Scanner excerpt · scripts/export_long_image.py (reported line 31)May include surrounding context.

python
last_error: Exception | None = None
    for command in install_commands:
        try:
            subprocess.run(command, check=True)
            return
        except Exception as exc:  # noqa: BLE001
            last_error = exc

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Silently installing Playwright browser binaries creates hidden network and software installation side effects. In a skill advertised as a local Markdown export helper, undisclosed installation behavior is especially risky because it exceeds user expectations and broadens the executable surface.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
90% confidence
Finding

This subprocess invocation installs a Playwright-managed Chromium browser at runtime, which causes unexpected network access and modification of the local environment during a document export task. While the command is not shell-injected, silently downloading and installing executable browser binaries expands the skill's capabilities and increases supply-chain and trust risks.

Content

Scanner excerpt · scripts/export_long_image.py (reported line 100)May include surrounding context.

python
def install_playwright_browser() -> None:
    subprocess.run(
        [sys.executable, "-m", "playwright", "install", "chromium"],
        check=True,
    )

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest describes converting a local Markdown path or pasted Markdown text into a mobile-friendly image while keeping HTML beside it for inspection. This file does not process Markdown at all; it consumes an HTML file and, if needed, installs Playwright and a Chromium browser before rendering and capturing screenshots, which is materially broader than the stated conversion behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Automatically performing package installation without any user-facing warning or confirmation is unsafe because it triggers privileged environmental changes and remote code retrieval as a side effect of a simple rendering operation. In a skill expected to process local Markdown, this hidden behavior is especially risky and surprising, making compromise or policy violations more likely in restricted or production environments.

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/render_markdown_mobile_long_image.py (reported line 643)May include surrounding context.

python
install_commands.append([uv_path, "pip", "install", "--python", sys.executable, package_name])

    for ensure_command in ensure_commands:
        subprocess.run(ensure_command, check=False)

    last_error: Exception | None = None
    for command in install_commands:

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/render_markdown_mobile_long_image.py (reported line 648)May include surrounding context.

python
last_error: Exception | None = None
    for command in install_commands:
        try:
            subprocess.run(command, check=True)
            return
        except Exception as exc:  # noqa: BLE001
            last_error = exc

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The manifest describes converting Markdown into a mobile-friendly PNG/JPG long image while keeping HTML beside it, but this file's CLI only accepts an input Markdown path and an output HTML path, then writes HTML. No image rendering, screenshotting, or PNG/JPG generation occurs anywhere in the code, so the implemented behavior is materially narrower than the advertised skill behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The natural-language description sets zh-CN typography as the default style, which imposes a specific locale preference in the skill behavior. The file does not indicate user opt-in, configurability, or a region-specific justification for that locale choice.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

This markdown file describes that the entry script produces a normalized markdown path, rendered HTML file, and exported image file, which means it writes files to disk. The workflow does not include any warning or disclosure about these local artifacts being created or overwritten, which is relevant user-impacting behavior for a markdown skill description.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The generated HTML always sets lang="zh-CN", which forces a specific language/locale regardless of the input content or user preference. This is a natural-language locale policy concern because the file does not provide opt-in, configurability, or justification for restricting output to Chinese locale metadata.

Content

No source excerpt is available for this finding.