T09 · Insecure Skill Coding Practices
- Location
scripts/render_report.py:38- Finding
Unescaped Report Data Allows Stored HTML Injection
- Content
View full analysis
{item['path']} —— " f"{item['reason']}" ) # Replace placeholders in the HTML template template = template.replace( "{{PROJECT_NAME}}", project["project_name"] ) template = template.replace( "{{TOTAL_FILES}}", str(project["total_files"]) ) template = template.replace( "{{TOTAL_DIRECTORIES}}", str(project["total_directories"]) ) template = template.replace( "{{COMPLEXITY_SCORE}}", str(complexity["score"]) ) template = template.replace( "{{TECH_STACK}}", tech_stack ) template = template.replace( "{{KEY_FILES}}", key_files_text ) ``` ```python output_path.write_text( template, encoding="utf-8" ) ``` ### Technical Analysis The report renderer loads values from a caller-selected JSON file and inserts them directly into an HTML template without HTML escaping or schema validation. Affected values include: - `project["project_name"]` - Entries in `stack["technology_stack"]` - `item["path"]` - `item["reason"]` Because these values are inserted into HTML text and markup contexts verbatim, a crafted value containing elements such as `- Remediation
View remediation
{path} —— {reason}" ``` 2. Prefer an auto-escaping template engine rather than manual `str.replace()` operations. Ensure auto-escaping is enabled for HTML templates. 3. Validate the input JSON against a strict schema: - Require expected objects and arrays. - Enforce primitive field types. - Reject unexpected properties where appropriate. - Set reasonable length limits. 4. Treat all repository-derived values, including directory and file names, as untrusted input. 5. Add a restrictive Content Security Policy to the report template, for example: ```html ``` 6. Add regression tests using payloads containing HTML elements, event-handler attributes, quotes, and encoded markup. Verify that the generated report displays these values as literal text and does not create executable DOM elements. ]]>
