T09 · Insecure Skill Coding Practices
Note
- Location
- scripts/extract_standup.py:64
- Finding
- Unescaped User-Controlled Data in Markdown Output## Vulnerability Details **File Location**: `scripts/extract_standup.py`, lines 64–79 **Vulnerability Type**: Markdown injection through unescaped title and standup content **Risk Level**: Low ### Vulnerable Code ```python def to_markdown(summary: dict, title: str = "Daily Standup Summary") -> str: lines = [f"# {title}\n"] labels = [("completed", "Completed"), ("planned", "Planned"), ("blockers", "Blockers")] for key, label in labels: lines.append(f"## {label}\n") items = summary.get(key, []) if not items: lines.append("_None to report_\n") else: for item in items: lines.append(f"- **{item['author']}**: {item['content']}") lines.append("") return "\n".join(lines) ``` ### Technical Analysis The Markdown generator directly interpolates the command-line-controlled title and file-controlled standup content into its output without escaping Markdown metacharacters or removing raw HTML. Consequently, input is treated as Markdown syntax rather than exclusively as display text. An attacker who can influence the source chat log can inject headings, links, images, HTML, or other renderer-specific constructs into a generated report. The `--title` argument provides a second injection point when its value comes from an untrusted source. Although author values are constrained by the parser, message content remains attacker-controlled. The practical effect depends on the downstream Markdown renderer. A renderer may sanitize HTML or disable remote images, but permissive renderers can display deceptive links, alter report structure, or request attacker-controlled remote resources. JSON output uses `json.dumps` and is not affected by this Markdown-specific issue. ### Attack Path 1. An attacker submits a chat message or source-log entry containing crafted Markdown, such as a misleading link, remote image, injected heading, or ...[truncated 1460 chars]
- Remediation
- ## Remediation Suggestions 1. Escape Markdown metacharacters in the title, author, and content fields before interpolation. At minimum, handle backslashes, backticks, asterisks, underscores, braces, brackets, parentheses, angle brackets, hash signs, plus signs, minus signs, periods, exclamation marks, pipes, and line-breaking control characters. 2. Remove or encode raw HTML delimiters so untrusted content cannot introduce HTML elements. 3. Normalize embedded carriage returns and newlines to prevent a single message from breaking out of its intended bullet. 4. Consider rendering untrusted values as code spans or plain text when preserving rich formatting is unnecessary. 5. If reports are published automatically, configure the receiving Markdown renderer to disable raw HTML, active extensions, and automatic loading of remote resources. 6. Add regression tests covering injected headings, links, images, raw HTML, nested lists, block quotes, and multiline content. 7. Continue using JSON output for programmatic consumers because JSON serialization correctly escapes structural characters; apply contextual encoding only when that data is later rendered as Markdown or HTML.
