T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/html_report.py:148
- Finding
- Unescaped Session Metadata Allows Active HTML Injection in the Chromium Report Renderer<![CDATA[ ## Vulnerability Details **File Locations**: - `scripts/fetch_usage.py:85-90` - `scripts/html_report.py:148-155` - `scripts/generate_report_image.py:67-80` **Vulnerability Type**: HTML injection into a local browser rendering context **Risk Level**: Medium ### Vulnerable Code `scripts/fetch_usage.py:85-90` accepts a model identifier from session logs without validation: ```python # Extract model info model = ( message.get("model") or data.get("model") or data.get("model_alias") or "unknown" ) ``` `scripts/html_report.py:148-155` interpolates that identifier directly into HTML: ```python sorted_period_models = sorted(period_model_tokens.keys(), key=lambda x: -period_model_tokens[x]) for m in sorted_period_models[:6]: tokens = period_model_tokens[m] cost = period_model_cost[m] pct = (tokens / total_tokens * 100) if total_tokens > 0 else 0 u_cost = (cost / tokens * 1000000) if tokens > 0 else 0 html += f"""<div style="margin-bottom:24px"> <div style="display:flex;justify-content:space-between;margin-bottom:8px;font-size:13px"><span style="color:#10b981;font-weight:600">{m[:18]}</span><span>{fmt_tokens(tokens)}</span></div> <div style="height:6px;background:#2a2a2a;border-radius:3px;overflow:hidden;margin-bottom:6px"><div style="height:100%;width:{pct:.1f}%;background:#10b981"></div></div> <div style="font-size:10px;color:#6b7280;display:flex;justify-content:space-between"><span>Unit Cost: ${u_cost:.2f}/M</span><span>Cost: {fmt_cost(cost)}</span></div></div>""" ``` `scripts/generate_report_image.py:67-80` writes and opens the resulting document in Chromium: ```python # Save HTML with open(html_path, "w", encoding="utf-8") as f: f.write(html) print(f"HTML saved to {html_path}") # Generate image with html2image hti = Html2Image() hti.output_path = str(output_dir) # High-resolution PPT viewport (1440p style ratio, increased height for safety) hti.size = (1200, 1000) hti.scree ...[truncated 2781 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Escape every untrusted value before inserting it into HTML: ```python from html import escape safe_model = escape(str(m), quote=True) ``` Use `safe_model` in the generated markup instead of `m` or `m[:18]`. 2. Prefer a template engine with automatic escaping rather than constructing the document through f-strings. 3. Validate model identifiers when parsing logs. If model names are expected to contain only a limited character set, enforce a conservative allowlist such as letters, digits, spaces, periods, underscores, colons, slashes, and hyphens. 4. Apply escaping to every dynamic HTML field, including the report title and all future values derived from logs or command-line arguments. 5. Configure Chromium to disable JavaScript when it is not required for rendering. 6. Block HTTP, HTTPS, WebSocket, and other external resource requests during rendering. A report intended to be fully local should load only the generated local document and bundled local assets. 7. Run Chromium with an isolated temporary profile and retain its sandbox. Avoid flags that weaken same-origin, file-origin, or sandbox protections. 8. Add regression tests using compact payloads, including active markup shorter than 18 characters, and verify that the output contains escaped text and causes no network requests. ]]>
