T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/gen_html.py:73
- Finding
- Unescaped Presentation Data Allows Stored HTML and JavaScript Injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/gen_html.py`, lines 73–143 **Vulnerability Type**: Stored HTML/JavaScript injection **Risk Level**: High ### Vulnerable Code ```python def make_title_slide(title, subtitle): content = f''' <div style="font-size:5rem;margin-bottom:20px">🦞</div> <h1>{title}</h1> <p class="subtitle">{subtitle}</p>''' return content def make_content_slide(title, items): if isinstance(items, list): items_html = ''.join(f'<li>{item}</li>' for item in items) return f'\n <h2>{title}</h2>\n <ul>{items_html}</ul>\n' return f'\n <h2>{title}</h2>\n <p>{items}</p>\n' def make_cards_slide(title, cards): cards_html = '' for card in cards: cards_html += f'<div class="card"><h4>{card["icon"]} {card["title"]}</h4><p>{card["content"]}</p></div>\n' return f'\n <h2>{title}</h2>\n <div class="cards">{cards_html}</div>\n' def make_chart_slide(title, data): bars = '' for item in data: h = item.get("height", 100) bars += f'''<div class="bar"> <div class="bar-value">{item["value"]}</div> <div class="bar-fill" style="height:{h}px"></div> <div class="bar-label">{item["label"]}</div> </div>\n''' return f'\n <h2>{title}</h2>\n <div class="bar-chart">{bars}</div>\n' def make_swot_slide(title, strengths, weaknesses): s_items = ''.join(f'<li>{s}</li>' for s in strengths) w_items = ''.join(f'<li>{w}</li>' for w in weaknesses) return f''' <h2>{title}</h2> <div class="grid-2"> <div class="swot"><h4>💪 Strengths 优势</h4><ul>{s_items}</ul></div> <div class="swot" style="border-color:rgba(255,149,0,.35);background:rgba(255,149,0,.06)"><h4>⚠️ Weaknesses 劣势</h4><ul>{w_items}</ul></div> </div>\n''' ``` The resulting fragments are subsequently inserted into the final document without escaping: ```python total = len(data.get("slides", [])) + 1 html = HTML_TEMPLATE.format(title=args.title, slides=slides_html, to ...[truncated 2661 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Apply contextual HTML escaping to every untrusted text value before inserting it into the template. At minimum, use `html.escape(value, quote=True)` for titles, subtitles, list entries, card fields, labels, and displayed values. 2. Use a template engine with automatic escaping enabled instead of constructing HTML through f-strings. 3. Treat chart dimensions as data rather than markup: - Parse heights as integers or finite floating-point values. - Reject nonnumeric values. - Enforce a reasonable range such as `0` through `220`. 4. Avoid inserting untrusted content into inline style attributes. Prefer predefined CSS classes or set validated values through safe DOM APIs. 5. If limited formatting must be supported, sanitize it with a strict allowlist that excludes scripts, event-handler attributes, dangerous URL schemes, embedded objects, and unsafe CSS. 6. Add regression tests covering element-breaking payloads, `<script>` elements, event handlers, quoted attribute breakers, CSS-breaking values, and encoded variants. 7. Consider deploying generated presentations with a restrictive Content Security Policy that disallows inline and remote scripts. This should be defense in depth and must not replace output encoding. ]]>
