T09 · Insecure Skill Coding Practices
- Location
src/ouracli/format_html.py:122- Finding
Unescaped Oura Data Permits Script Injection in Generated HTML Reports
- Content
View full analysis
{sub_human_key}{subvalue}" ) ``` ```python # Render simple KVs as table if simple_kvs: html.append("") for k, v in simple_kvs: html.append(f"{k}{v}") html.append("") ``` ```python html_parts.append(f'{title or "Oura Data"}') ``` ```python if isinstance(item, dict) and "day" in item: html_parts.append(f'{item["day"]}
') ``` ```python if isinstance(item, dict) and "day" in item: html_parts.append(f'{item["day"]}
') html_parts.append(format_html_item(item, level=3)) ``` ### Technical Analysis The HTML formatter inserts API-derived values directly into HTML elements without context-appropriate escaping. This includes simple values, nested dictionary values, report titles, and day headings. Oura records can include textual metadata such as user-created tags. If a field contains HTML markup or an event-handler attribute, the formatter emits it as active markup rather than text. For example: ```html``` When the report is opened, the browser parses the injected element and executes its event handler. The formatter does not use `html.escape`, an automatically escaping template engine, a sanitizer, or a Content Security Policy that would prevent inline script execution. ### Attack Path 1. Malicious HTML is introduced into a textual Oura record, such as a user-added tag or other API-returned metadata. 2. The vict ...[truncated 1275 chars]
- Remediation
View remediation
str: return escape(str(value), quote=True) ``` Apply this function to table keys, table values, titles, headings, interval values, and all other API-derived strings. 2. Prefer a template engine with automatic escaping enabled rather than assembling HTML through f-strings. 3. Treat HTML text and HTML attribute contexts separately. Attribute values must be quoted and escaped with quote escaping enabled. 4. Add a restrictive Content Security Policy, such as one that blocks inline scripts and unauthorized outbound connections. If inline chart initialization remains necessary, move it into a bundled script or authorize it with a nonce or hash. 5. Add regression tests covering at least: ```html"> & < > " ' ``` 6. Verify that generated output contains escaped text such as `<script>` rather than executable elements. ]]>
