T09 · Insecure Skill Coding Practices
Warning
- Location
- templates/html-template.html:179
- Finding
- Unescaped Dynamic Content in Generated HTML Reports<![CDATA[ ## Vulnerability Details **File Location**: `templates/html-template.html`, lines 179–207 **Vulnerability Type**: HTML injection and potential cross-site scripting through unescaped template placeholders **Risk Level**: Medium ### Vulnerable Code ```html <h1>{{TITLE}}</h1> <div class="subtitle">{{SUBTITLE}}</div> <div class="source-badge"> <span class="badge">📊 Data Source: <span class="wikidata-logo">Wikidata</span></span> </div> <div class="stats"> {{STATS}} </div> <div class="table-wrapper"> <table> <thead> <tr> {{TABLE_HEADERS}} </tr> </thead> <tbody> {{TABLE_ROWS}} </tbody> </table> </div> <div class="sparql-section"> <strong>SPARQL Query Executed</strong><br> Endpoint: <a href="https://query.wikidata.org/sparql" target="_blank">https://query.wikidata.org/sparql</a><br><br> <code>{{SPARQL_QUERY}}</code> </div> ``` The same issue also affects the document title at line 5: ```html <title>{{TITLE}} - Wikidata Query Results</title> ``` ### Technical Analysis The template places dynamic placeholders directly into HTML markup without specifying HTML encoding or sanitization. The affected values include: - `TITLE` and `SUBTITLE`, which can be derived from a user's natural-language request. - `STATS`, `TABLE_HEADERS`, and `TABLE_ROWS`, which can contain values returned from the community-editable Wikidata service. - `SPARQL_QUERY`, which can contain text derived from user input. The Skill documentation does not require context-sensitive output encoding, sanitization, or validation when replacing these placeholders. If an untrusted value contains HTML syntax, the browser may interpret it as markup rather than plain text. For example, an unsafe replacement for `SPARQL_QUERY` could terminate the existing element and introduce an event-handler payload: ```html </code><img src="x" onerror="alert(document.domain)"><code> ``` Escaping re ...[truncated 2087 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Encode all text values before insertion** - HTML-escape `&`, `<`, `>`, `"`, and `'` in titles, subtitles, labels, statistics, query text, and other plain-text fields. - Ensure `SPARQL_QUERY` is rendered exclusively as encoded text inside `<code>`. 2. **Use an auto-escaping template engine** - Replace unrestricted string substitution with a template system that escapes output by default. - Require an explicit, reviewed operation before any value can be rendered as trusted HTML. 3. **Construct tables from typed data** - Generate each table element using safe DOM APIs such as `textContent`, or use auto-escaped template expressions. - Do not accept complete HTML fragments for `TABLE_HEADERS`, `TABLE_ROWS`, or `STATS`. 4. **Validate generated links** - Parse URLs before rendering them. - Permit only expected HTTPS destinations, such as Wikidata entity URLs with validated `Q` identifiers. - Reject dangerous schemes including `javascript:`, `data:`, and `file:`. 5. **Add a restrictive Content Security Policy** - Add a policy such as: ```html <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src https: data:; connect-src 'none'; base-uri 'none'; form-action 'none';"> ``` - Adjust the policy only for resources that the report genuinely requires. - Avoid allowing inline scripts or remote scripts. 6. **Harden external links** - Add `rel="noopener noreferrer"` to links using `target="_blank"`. 7. **Document mandatory safe rendering** - Update `SKILL.md` to explicitly require context-sensitive encoding and URL validation for every generated HTML report. - State that Wikidata results and user prompts must always be treated as untrusted input. 8. **Add security tests** - Test titles, labels, and query text containing closing tags, quotation marks, event handlers, encoded payloads, and malicious URL schemes. - Verify that ...[truncated 95 chars]
