T09 · Insecure Skill Coding Practices
Error
- Location
- charts/map-compare.html:275
- Finding
- Stored HTML and JavaScript Injection in Chart Templates<![CDATA[ ## Vulnerability Details **File Location**: `charts/map-compare.html:275-287`; related unsafe substitutions also occur in `charts/map-compare.html:106-114, 199-205`, `charts/map-radar.html:62-66`, and `charts/simulate-timeline.html:52-60` **Vulnerability Type**: Stored HTML/JavaScript injection **Risk Level**: High ### Vulnerable Code ```javascript // 渲染方向说明列表 const list = document.getElementById('directionList'); const directions = [ { name: dirAName, reason: "{{direction_a_reason}}", step: "{{direction_a_step}}" }, { name: dirBName, reason: "{{direction_b_reason}}", step: "{{direction_b_step}}" } ]; if (dirCName && dirCName !== "{{direction_c_name}}") { directions.push({ name: dirCName, reason: "{{direction_c_reason}}", step: "{{direction_c_step}}" }); } directions.forEach(d => { const item = document.createElement('div'); item.className = 'direction-item'; item.innerHTML = `<span class="direction-name">${d.name}</span>:${d.reason} · <span class="first-step">第一步:${d.step}</span>`; list.appendChild(item); }); ``` Additional substitutions are placed directly into executable JavaScript contexts: ```javascript const mode = "{{mode}}"; const ganttLabels = {{gantt_labels}}; const ganttStart = {{gantt_start}}; const ganttDuration = {{gantt_duration}}; const ganttTasks = {{gantt_tasks}}; ``` ```javascript const pathName = "{{path_name}}"; const dataPathA = {{data_path_a}}; const dataStatusQuo = {{data_status_quo}}; const milestoneIndex = {{milestone_index}}; const milestoneLabel = "{{milestone_label}}"; const turningPointIndex = {{turning_point_index}}; const hoverLabelsPathA = {{hover_labels_path_a}}; const hoverLabelsStatusQuo = {{hover_labels_status_quo}}; ``` ### Technical Analysis The chart workflow reads career information from user input and persistent memory, substitutes it into complete HTML documents, and renders those documents in an iframe. The templates do not define contextual escaping or strict schema validation. String ...[truncated 2222 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove `innerHTML` and construct each element with `createElement` and `textContent`. 2. Serialize every value used in JavaScript with a trusted JSON serializer. Do not concatenate values into quoted JavaScript strings. 3. Validate substituted data against strict schemas: - Scores, percentages, dates, and indexes must have bounded numeric types. - Arrays must have fixed maximum lengths and typed elements. - Status values and modes must use explicit allowlists. - Text values must have reasonable length limits. 4. Prefer placing serialized data in an `application/json` element and parsing it rather than generating executable source code. 5. Render generated charts in a sandboxed iframe. Avoid `allow-same-origin`, top-level navigation, popups, and other privileges unless strictly required. 6. Apply a restrictive Content Security Policy that limits scripts to approved sources and restricts outbound connections. 7. Add tests using quotation marks, closing script tags, event-handler markup, template literals, and malformed JSON to verify that all values remain inert text. ]]>
