T09 · Insecure Skill Coding Practices
- Location
scripts/generate_visual.py:383- Finding
Stored HTML Attribute Injection Through Unvalidated Checklist Status
- Content
View full analysis
{_h(c.get('text', ''))} {_h(status)}\n" ``` ### Technical Analysis The `checklist[].status` field originates from summary JSON produced from conversation content. Although the intended values are `ready`, `pending`, and `blocked`, the renderer does not validate the field against that set. The status is escaped with `_h()` when inserted as visible text, but it is inserted without escaping into the quoted `class` attribute: ```html ``` An attacker who can influence the generated summary could supply a value such as: ```text pending" onmouseover="alert(document.domain) ``` This produces an element resembling: ```html ``` The injected event handler executes when the event is triggered. Because the payload is written into the exported HTML file, this is a stored client-side injection vulnerability. The absence of a restrictive Content Security Policy increases the likelihood that an injected inline handler can execute. ### Attack Path 1. An attacker places specially crafted instructions or content in a conversation that the Skill is asked to summarize. 2. The local summarization model incorporates attacker-controlled content into `checklist[].status` instead of returning one of the documented status values. 3. The resulting JSON is passed to `scripts/generate_visual.py`. 4. The renderer inserts the status directly into the HTML `class` attribute without validation or attribute encoding. 5. The user opens the generated HTML export. 6. When the injected event is triggered, attacker-controlled JavaScript execute ...[truncated 856 chars]- Remediation
View remediation
{_h(c.get("text", ""))} ' f'{safe_status}\n' ) ``` 3. Validate the complete summary object against a JSON schema before rendering. Define `checklist[].status` as an enum containing only `ready`, `pending`, and `blocked`, and reject malformed structures. 4. Add a restrictive Content Security Policy to the generated HTML. Prefer moving the inline script to a separately hashed script or using an appropriate CSP hash. At minimum, prohibit inline event handlers and unnecessary network destinations. 5. Add regression tests using status values containing quotes, angle brackets, event-handler text, and JavaScript URLs. Verify that generated elements cannot acquire attacker-defined attributes. 6. Treat model-generated JSON as untrusted input regardless of whether inference is performed locally. ]]>
