T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/render_report.py:6
- Finding
- Unescaped Markdown and HTML Content Injection in Report Rendering<![CDATA[ ## Vulnerability Details **File Location**: `scripts/render_report.py`, lines 6-29 **Vulnerability Type**: Unescaped attacker-controlled content in Markdown output **Risk Level**: Medium ### Vulnerable Code ```python def render(result: dict) -> str: lines = ["# Financial Report Analysis", ""] comp = result.get("company") or {} period = result.get("period") or {} lines.append(f"**Company:** {comp.get('name','?')} ") lines.append(f"**Period:** FY{period.get('fiscal_year','?')} ({period.get('reporting_basis','?')})") lines.append("") if "executive_summary" in result: lines.append("## Executive Summary"); lines.append(""); lines.append(result["executive_summary"]); lines.append("") if "ratios" in result: lines.append("## Key Ratios"); lines.append("") for group, vals in result["ratios"].items(): lines.append(f"### {group}") for k, v in vals.items(): pct = f"{v*100:.2f}%" if isinstance(v, float) and -10 < v < 10 else str(v) lines.append(f"- **{k}**: {pct}") lines.append("") if "red_flags" in result: lines.append("## Red Flags"); lines.append("") if not result["red_flags"]: lines.append("_None detected._") for f in result["red_flags"]: lines.append(f"- {f['severity']} **{f['code']}** {f['title']} — {f['evidence']}") return "\n".join(lines) ``` ### Technical Analysis The renderer directly interpolates fields from an input JSON document into Markdown without validating their types or escaping Markdown and raw HTML syntax. Affected fields include the company name, reporting period, executive summary, ratio group and key names, and every red-flag property. Markdown supports structural directives, links, images, and, depending on the downstream renderer, raw HTML. Consequently, an attacker can place Markdown or HTML markup and newline characters in one of these fields to alter ...[truncated 1834 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Define and enforce a strict schema for input documents before rendering: - Require objects and arrays at the expected locations. - Require numeric ratio values. - Require bounded strings for textual fields. - Reject unexpected nested structures and malformed red-flag records. 2. Escape Markdown metacharacters in all data-derived fields, including backslashes, backticks, asterisks, underscores, braces, brackets, parentheses, angle brackets, hash symbols, plus signs, hyphens, periods, exclamation marks, pipes, and newline characters where structural formatting is not intended. 3. Strip or encode raw HTML before generating Markdown. If reports are converted to HTML, configure the Markdown engine to disable raw HTML and sanitize the resulting HTML with an allowlist-based sanitizer. 4. Restrict rendered links and media to approved URL schemes. Disable remote images where possible to prevent tracking requests and unintended data disclosure. 5. Keep trusted formatting templates separate from untrusted report values rather than accepting preformatted Markdown from input data. 6. Add regression tests using fields containing: - Newline-based heading injection - Markdown links and images - Raw HTML tags - `javascript:` and other unsafe URL schemes - Embedded emphasis, lists, and code fences ]]>
