T09 · Insecure Skill Coding Practices
Error
- Location
- generate-chart.js:343
- Finding
- Generated HTML Allows Script Injection Through Untrusted Chart Content<![CDATA[ ## Vulnerability Details **File Location**: `generate-chart.js`, lines 343-451 **Vulnerability Type**: HTML injection and inline-script breakout **Risk Level**: High ### Vulnerable Code ```javascript <title>${title}</title> ``` ```javascript <h1 class="chart-title">${title}</h1> ``` ```javascript <script> const chart = echarts.init(document.getElementById('chart')); const option = ${JSON.stringify(option, null, 2)}; window.addEventListener('resize', () => { chart.resize(); }); chart.setOption(option); </script> ``` ### Technical Analysis The `--title` command-line value is interpolated directly into both the HTML `<title>` element and an `<h1>` element without context-appropriate HTML escaping. A crafted value containing closing tags and executable markup can therefore escape the intended element and insert arbitrary HTML or JavaScript. Chart data is also serialized with `JSON.stringify()` and embedded directly inside an executable `<script>` element. JSON serialization does not make a value safe for an HTML script context. In particular, a user-controlled string containing `</script>` is recognized by the HTML parser as the end of the script element even when that sequence occurs inside a JavaScript string literal. An attacker can follow it with a new `<script>` element containing arbitrary JavaScript. The generated file is explicitly intended to be opened in a browser, so the injected content reaches an executable sink as part of the normal workflow. ### Attack Path 1. An attacker supplies or persuades a user to process crafted financial data or a crafted chart title. 2. The title can contain a payload such as a closing `</title>` or `</h1>` tag followed by a malicious `<script>` element. 3. Alternatively, a chart label can contain an inline-script breakout sequence such as `</script><script>/* attacker code */</script>`. 4. The program inserts the malicious value into the generated HTML without safe encoding. ...[truncated 894 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Escape the title separately for each HTML context. For text content, encode at least `&`, `<`, `>`, `"`, and `'`. 2. Prefer constructing text nodes with `textContent` rather than inserting user-controlled values into an HTML template. 3. Do not embed raw JSON in an executable script context. Encode HTML-significant characters after serialization, for example: ```javascript function serializeForInlineScript(value) { return JSON.stringify(value) .replace(/</g, '\\u003c') .replace(/>/g, '\\u003e') .replace(/&/g, '\\u0026') .replace(/\u2028/g, '\\u2028') .replace(/\u2029/g, '\\u2029'); } ``` 4. Prefer placing serialized data in a non-executable `<script type="application/json">` element and reading it through `textContent`, while still safely encoding closing-tag sequences. 5. Validate the complete input schema, including expected data types and maximum string lengths. 6. Validate custom colors against a strict allowlist of accepted CSS color formats before interpolating them into styles. 7. Add a restrictive Content Security Policy after removing inline executable code, such as one permitting scripts only from a controlled local source. 8. Add automated tests covering payloads containing `</script>`, closing HTML tags, quotes, ampersands, and Unicode line separators. ]]>
