T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/password_auditor.py:589
- Finding
- Stored HTML Injection Through Unescaped Vault Entry Titles<![CDATA[ ## Vulnerability Details **File Location**: `scripts/password_auditor.py`, lines 589–603 **Vulnerability Type**: Stored HTML injection / cross-site scripting in generated reports **Risk Level**: High ### Vulnerable Code ```python frows = [] for kind, items in res["findings"].items(): for f in items: sev = {"breach": "P0", "reuse": "P1", "weakness": "P1", "staleness": "P3", "twofa": "P3"}[kind] sevcls = "p0" if sev == "P0" else "" tag = f.get("tier", "") tagcls = tag if tag in ("critical", "sensitive") else "standard" frows.append(f"<tr><td>{f['entry']}</td><td class='{sevcls}'>{sev}</td>" f"<td>{kind}</td><td>{f['title']} " f"<span class='tag {tagcls}'>{tagcls}</span></td>" f"<td>{f['action']}</td></tr>") prows = "".join( f"<tr><td>{p['priority']}</td><td>#{p['entry']} {p['title']}</td>" f"<td>{p['dimension']}</td><td>{p['action']}</td></tr>" for p in res["plan"][:15]) ``` ### Technical Analysis Vault entry titles originate from imported CSV or JSON content. These values are copied into finding and remediation-plan objects and then interpolated directly into HTML without contextual output encoding. Because `f['title']` and `p['title']` are not processed with `html.escape()`, HTML elements and event-handler attributes in a crafted title become active browser content. For example, an entry title containing an image element with an `onerror` handler could execute JavaScript when the generated dashboard is opened. The vulnerability is stored rather than reflected: the malicious value is first stored in or supplied through a vault export, incorporated into the generated dashboard through `--html`, and executed later when a user opens that file. ### Attack Path 1. An attacker introduces a crafted title into a password-vault entry, shared vault item, impor ...[truncated 1472 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Escape every dynamic value before inserting it into HTML: ```python import html safe_title = html.escape(str(f["title"]), quote=True) safe_action = html.escape(str(f["action"]), quote=True) safe_kind = html.escape(str(kind), quote=True) ``` 2. Apply equivalent escaping to remediation-plan fields, including titles, dimensions, actions, labels, and any future vault-derived values. 3. Prefer a template engine with automatic HTML escaping instead of constructing markup through f-strings. 4. Add a restrictive Content Security Policy to the generated document, for example: ```html <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:"> ``` This should be defense in depth and must not replace output encoding. 5. Add regression tests with titles containing: - `<script>` elements - Event handlers such as `onerror` - Quotes and angle brackets - Encoded HTML entities - SVG-based script payloads 6. Verify that generated reports contain encoded text such as `<script>` rather than executable elements. ]]>
