T09 · Insecure Skill Coding Practices
- Location
eval-viewer/generate_review.py:272- Finding
Stored Script Injection Through Unsafe JSON Embedding in Review Pages
- Content
View full analysis
` element in `viewer.html`. JSON string escaping is not sufficient for embedding data inside an HTML script element. In particular, `json.dumps()` does not escape the HTML parser-sensitive sequence ``. If an untrusted prompt, generated output, grading result, previous feedback value, or benchmark field contains this sequence, the browser terminates the surrounding script element regardless of whether the sequence occurs inside a JavaScript string. An attacker-controlled value can therefore inject a new script element, for example: ```html ``` This is especially relevant because the viewer is explicitly intended to process artifacts produced by evaluated Skills and agents. Those artifacts must be treated as untrusted. ### Attack Path 1. An attacker supplies or influences a Skill being evaluated. 2. The Skill writes an output file or grading-related value containing a `` payload. 3. `generate_review.py` reads the malicious content and places it in the `runs` or related embedded data structure. 4. `json.dumps()` preserves the dangerous HTML closing-tag sequence. 5. `generate_html()` inserts the serialized v ...[truncated 1167 chars]- Remediation
View remediation
``` 3. Before embedding JSON in HTML, escape at least the HTML-sensitive characters: ```python data_json = ( json.dumps(embedded) .replace("<", "\\u003c") .replace(">", "\\u003e") .replace("&", "\\u0026") .replace("\u2028", "\\u2028") .replace("\u2029", "\\u2029") ) ``` 4. Add a restrictive Content Security Policy. Prefer a nonce or hash for trusted scripts and disallow arbitrary inline execution. 5. Avoid loading external resources unless necessary. If network access is not required, use a policy such as `connect-src 'self'` and bundle required assets locally. 6. Add regression tests using payloads containing ``, nested tags, Unicode separators, and event-handler markup. 7. Treat every prompt, output file, grading field, benchmark field, and feedback value as attacker-controlled. ]]>
