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. ]]>
