T09 · Insecure Skill Coding Practices
- Location
eval-viewer/generate_review.py:257- Finding
Stored script injection in generated evaluation review pages
- Content
View full analysis
str: """Generate the complete standalone HTML page with embedded data.""" template_path = Path(__file__).parent / "viewer.html" template = template_path.read_text() # Build previous_feedback and previous_outputs maps for the template previous_feedback: dict[str, str] = {} previous_outputs: dict[str, list[dict]] = {} if previous: for run_id, data in previous.items(): if data.get("feedback"): previous_feedback[run_id] = data["feedback"] if data.get("outputs"): previous_outputs[run_id] = data["outputs"] embedded = { "skill_name": skill_name, "runs": runs, "previous_feedback": previous_feedback, "previous_outputs": previous_outputs, } if benchmark: embedded["benchmark"] = benchmark data_json = json.dumps(embedded) return template.replace("/*__EMBEDDED_DATA__*/", f"const EMBEDDED_DATA = {data_json};") ``` The serialized value is inserted directly into an executable script element: ```html- Remediation
View remediation
``` 3. Serialize the JSON while escaping characters significant to the HTML parser, including `<`, `>`, `&`, U+2028, and U+2029. At minimum, replace `<` with `\u003c` before insertion. 4. Retrieve and parse the value using: ```javascript const EMBEDDED_DATA = JSON.parse( document.getElementById("embedded-data").textContent ); ``` 5. Add a restrictive Content Security Policy that prevents inline and arbitrary third-party scripts. 6. Add regression tests using payloads containing ``, HTML tags, Unicode separators, and malicious values in prompts, filenames, grading evidence, and text outputs. 7. Treat every field originating from an evaluated skill or workspace as untrusted, even when it is serialized as JSON. ]]>
