T09 · Insecure Skill Coding Practices
Error
- Location
- SKILL.md:262
- Finding
- DOM-based cross-site scripting through unsafe modal content rendering<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 262-274 **Vulnerability Type**: DOM-based cross-site scripting (DOM XSS) **Risk Level**: High ### Vulnerable Code ```javascript function openModal(title, content) { if (isModalOpen) return; isModalOpen = true; // Save scroll position const scrollY = window.scrollY; document.body.style.top = -scrollY + 'px'; document.body.classList.add('modal-open'); document.getElementById('modalTitle').textContent = title; document.getElementById('modalBody').innerHTML = content; document.getElementById('modal').classList.add('show'); } ``` ### Technical Analysis The `openModal()` function assigns its `content` argument directly to the `innerHTML` property. Unlike the title, which is safely assigned through `textContent`, modal content is interpreted as HTML without sanitization or an allowlist. If monitored data, API responses, database records, filenames, task descriptions, or other attacker-controlled values are passed to `openModal()`, an attacker can inject executable markup. Payloads can use event-handler attributes or other browser-supported HTML execution mechanisms. The template also does not define a restrictive Content Security Policy that could mitigate inline script execution. This creates a reusable unsafe rendering primitive that is likely to become exploitable when users customize the dashboard to display real data. ### Attack Path 1. A user customizes the dashboard to display task descriptions or records obtained from an API, database, or monitored file. 2. An attacker gains control over one of the values displayed in a modal. 3. The application passes the attacker-controlled value to `openModal()` as `content`. 4. The function assigns the value to `modalBody.innerHTML`. 5. The browser parses the supplied value as markup and executes an injected event handler or equivalent active content. 6. The payload runs with the dashboard origin's b ...[truncated 810 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Use `textContent` when modal content is intended to be plain text: ```javascript document.getElementById('modalBody').textContent = content; ``` - If formatted HTML is a requirement, sanitize it with a maintained, allowlist-based HTML sanitizer before inserting it. - Do not construct HTML by concatenating API or user-controlled strings. Build DOM nodes and assign untrusted values through `textContent`. - Add a restrictive Content Security Policy, such as one that disallows inline scripts and event handlers. - Trace every call to `openModal()` and validate whether its content can originate from an API, database, file, URL parameter, or user-controlled record. - Add automated tests containing HTML event-handler payloads to verify that input is rendered as inert text. ]]>
