Back to skill

Security audit

Markdown Toolkit

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent Markdown utility skill, but its HTML examples should be used carefully with untrusted content and remote stylesheets.

Install/use this as a convenience toolkit for your own Markdown, but do not treat its HTML conversion or stripping snippets as sanitizers for untrusted documents. Prefer pandoc or a maintained sanitizer for hostile input, avoid the CDN stylesheet when privacy/offline behavior matters, and run in-place cleanup commands only on files you can restore.

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

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:61
Finding
Markdown-to-HTML Conversion Permits Script Injection<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:61-73` **Vulnerability Type**: Cross-site scripting through unescaped Markdown content and unsafe URLs **Risk Level**: High ### Complete Code Snippet ```python blocks[k] = f'<pre><code class="language-{m.group(1) or ""}">{m.group(2)}</code></pre>' return k md = re.sub(r'```(\w*)\n(.*?)```', save, md, flags=re.DOTALL) md = re.sub(r'`(.+?)`', r'<code>\1</code>', md) for i in range(4, 0, -1): md = re.sub(rf'^{"#"*i}\s+(.+)$', rf'<h{i}>\1</h{i}>', md, flags=re.M) md = re.sub(r'\*\*(.+?)\*\*', r'<strong>\1</strong>', md) md = re.sub(r'\*(.+?)\*', r'<em>\1</em>', md) md = re.sub(r'\[(.+?)\]\((.+?)\)', r'<a href="\2">\1</a>', md) for k, v in blocks.items(): md = md.replace(k, v) print(f'<!DOCTYPE html><html><head><link rel="stylesheet" href="https://cdn.simplecss.org/simple.min.css"></head><body>{md}</body></html>') ``` ### Technical Analysis The converter builds HTML by directly interpolating attacker-controlled Markdown content. It does not HTML-escape code-block contents, headings, link labels, or other text before inserting them into the output document. Existing raw HTML in the Markdown is also left intact. Markdown link destinations are copied directly into `href` attributes without validating their URI scheme or encoding attribute delimiters. A link such as `[open](javascript:alert(document.domain))` therefore produces a dangerous `javascript:` URL. Raw HTML such as `<img src=x onerror=alert(document.domain)>` can remain executable in the generated page. Code-block content is similarly placed inside `<pre><code>` without escaping HTML metacharacters. An attacker can include closing tags and active HTML to escape the intended code element. ### Attack Path 1. An attacker supplies or modifies a Markdown document processed by the documented converter. 2. The document contains an active HTML payload, a `javascript:` Markdown link, or code-block content that closes the generated `<code>` ...[truncated 873 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Replace the regex-based converter with a maintained Markdown library configured to disable raw HTML. - Escape all text and code content with context-appropriate HTML escaping, such as Python's `html.escape`. - Validate link destinations against an explicit allowlist. Permit only necessary schemes such as `https`, `http`, and safe relative URLs. - Reject dangerous schemes, including `javascript:`, `data:`, and `vbscript:`. - Do not construct HTML attributes through direct string interpolation. - Sanitize the final generated document with a maintained HTML allowlist sanitizer as defense in depth. - Add regression tests covering raw `<script>` elements, event attributes, attribute-breaking input, dangerous URI schemes, and code-block escape payloads. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:96
Finding
Regex-Based HTML Stripping Retains Dangerous Attributes and URLs<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:96-97` **Vulnerability Type**: Incomplete HTML sanitization leading to script injection **Risk Level**: High ### Complete Code Snippet ```python safe = 'a|img|br|hr|code|pre|em|strong|b|i' t = re.sub(rf'<(?!/?(?:{safe})\b)[^>]+>', '', t) ``` ### Technical Analysis The routine treats selected HTML tag names as safe but performs no validation of their attributes or URL values. Consequently, allowed elements retain event-handler attributes such as `onerror`, `onload`, and `onclick`. Link and image attributes can also retain dangerous or attacker-controlled URI schemes. For example, `<img src=x onerror=alert(document.domain)>` is preserved because `img` is in the allowlist. Likewise, `<a href="javascript:alert(document.domain)">open</a>` remains present because `a` is allowed. Regular expressions are not a reliable mechanism for parsing and sanitizing hostile HTML. Browser HTML parsing behavior, malformed markup, attribute quoting variations, character references, and namespace handling create additional bypass opportunities. ### Attack Path 1. An attacker places malicious HTML in content presented as a Google Docs paste or another document requiring cleanup. 2. A victim runs the documented “Strip HTML” command on that content. 3. The regular expression preserves the malicious element because its tag name appears in the `safe` list. 4. The dangerous event attribute or URL remains in the output. 5. The sanitized-looking output is converted to HTML, embedded in a page, or rendered by an HTML-capable viewer. 6. The attacker's JavaScript executes automatically through an event handler or after user interaction with a dangerous link. ### Impact Assessment The routine creates a false expectation that unsafe HTML has been removed. If its output is later rendered as HTML, an attacker can execute JavaScript in the rendering document's browser context. This may enable content spoofing, phishing, unautho ...[truncated 226 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Replace regex-based filtering with a maintained HTML sanitizer that parses content according to HTML semantics. - Define allowlists for both elements and attributes rather than allowing every attribute on selected tags. - Remove every event-handler attribute, including all attributes beginning with `on`. - Validate `href`, `src`, and similar URL-bearing attributes against an explicit scheme allowlist. - Remove dangerous schemes such as `javascript:`, `vbscript:`, and unneeded `data:` URLs after canonicalization. - Consider removing `img` and `a` entirely if they are not required for the cleanup operation. - Sanitize at the final rendering boundary as well as during document cleanup. - Add tests for malformed tags, mixed-case attributes, encoded URI schemes, unquoted attributes, and browser parsing edge cases. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
The pandoc example adds a remote stylesheet URL, which causes generated HTML to depend on external network access and leaks viewer metadata when the HTML is opened. For a local Markdown toolkit, that behavior is not necessary to accomplish the stated task and expands the trust boundary to a third-party CDN.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The pure-Python HTML generator hardcodes a CDN stylesheet into the output HTML, so any opened document will attempt a network fetch. This introduces unnecessary external dependency, privacy leakage, and availability risk despite the tool being presented as a local conversion utility.

Missing User Warnings

Low
Confidence
80% confidence
Finding
The skill description provides a `sed -i` command that modifies `doc.md` in place, which affects user data on disk. While the operation is visible in the command itself, the surrounding markdown does not explicitly warn users that the file will be changed directly or suggest making a backup first.

Static analysis

No suspicious patterns detected.