T09 · Insecure Skill Coding Practices
- Location
references/main.js:193- Finding
Stored Cross-Site Scripting in Generated Course Content
- Content
View full analysis
Exactly! ' + rightExp; feedback.className = 'quiz-feedback show success'; } else { selected.classList.add('incorrect'); const correctBtn = $(`.quiz-option[data-value="${correct}"]`, q); if (correctBtn) correctBtn.classList.add('correct'); feedback.innerHTML = 'Not quite. ' + wrongExp; feedback.className = 'quiz-feedback show error'; } ``` The `rightExp` and `wrongExp` values originate from generated `data-*` attributes and are inserted as executable HTML. `references/main.js:468-480`: ```javascript window.checkBugLine = function (el, isCorrect) { const challenge = el.closest('.bug-challenge'); const feedback = $('.bug-feedback', challenge); if (isCorrect) { el.classList.add('correct'); feedback.innerHTML = 'Found it! ' + (el.dataset.explanation || ''); feedback.className = 'bug-feedback show success'; $$('.bug-line', chal ...[truncated 5123 chars]- Remediation
View remediation
` in text contexts. - Encode quotation marks as well when content is placed in an attribute. - Clarify that “exact copy” means the browser must display the exact source text, not that raw source bytes should be inserted as HTML. 2. **Remove unsafe `innerHTML` assignments** - Render untrusted explanations and hints using `textContent`. - Create trusted formatting elements separately rather than concatenating markup with untrusted strings. A safer quiz implementation is: ```javascript feedback.replaceChildren(); const prefix = document.createElement('strong'); prefix.textContent = selected.dataset.value === correct ? 'Exactly! ' : 'Not quite.'; const explanation = document.createTextNode( selected.dataset.value === correct ? rightExp : wrongExp ); feedback.append(prefix, explanation); ``` A safer bug-feedback implementation is: ```javascript feedback.replaceChildren(); if (isCorrect) { const prefix = document.createElement('strong'); prefix.textContent = 'Found it! '; feedback.append(prefix, document.createTextNode(el.dataset.explanation || '')); } else { feedback.textContent = el.dataset.hint || 'Not this line — keep looking...'; } ``` 3. **Sanitize any intentionally supported formatting** - If explanation fields must support limited HTML, process them through a well-maintained sanitizer. - Use a strict allowlist of harmless formatting elements. - Prohibit scripts, event-handler attributes, forms, embedded frames, dangerous URLs, and style-based execution paths. 4. **Validate generated modules before assembly** - Add a validation step that rejects unexpected `
