T09 · Insecure Skill Coding Practices
- Location
scripts/generate_report.py:40- Finding
Stored HTML and JavaScript Injection Through Unescaped Report Content
- Content
View full analysis
{kpi.get('label', '')}{kpi.get('value', '')}{kpi.get('sub', '')}""") ``` The same unsafe interpolation pattern is used in other report sections: ```python cards_html.append(f"""""") ``` ```python header_cells = "".join([f"{col}" for col in columns]) ``` ```python value = row.get(col, "") cell_html = f"{value}" ``` ```python {title} ``` ```python{title}
📊 {title}
{subtitle}
``` ```python {footer} ``` ### Technical Analysis Report content is inserted directly into HTML through Python formatted strings without context-appropriate escaping. Affected inputs include: - Report title, subtitle, and footer - KPI labels, values, and subtitles - Chart and table titles - Table column names and cell values These values may originate from command-line arguments, JSON input, database query results, CSV files, or direct calls to `build_report`. Consequently, imported data cannot safely be treated as trusted markup. An attacker can supply an HTML element with an event handler, such as an image whose error handler executes JavaScript. The payload is preserved in the generated report and runs when a user opens that report in a browser. This is a stored injection issue because the payload is written into the output HTML before execution. ### Attack Path 1. An attacker places mal ...[truncated 1263 chars]- Remediation
View remediation
str: return escape(str(value), quote=True) ``` 2. Apply the helper to all report title, subtitle, footer, KPI, chart title, table title, column, and cell values: ```python label = _html_text(kpi.get("label", "")) value = _html_text(kpi.get("value", "")) sub = _html_text(kpi.get("sub", "")) ``` 3. Do not use one generic transformation for every output context. Use: - HTML escaping for element text. - Attribute escaping for attribute values. - JSON serialization for JavaScript values. - Strict validation for enumerated configuration values. 4. Treat CSV, SQL, JSON, and query-derived values as untrusted, even when the report is generated locally. 5. Consider adding a restrictive Content Security Policy. If scripts remain inline, migrate them to a separately generated trusted script or use hashes/nonces rather than enabling unrestricted inline script execution. 6. Add regression tests covering payloads in every supported text field, including tags, quotes, event handlers, closing elements, and Unicode edge cases. ]]>
