T09 · Insecure Skill Coding Practices
- Location
references/main.js:175- Finding
Stored HTML and Script Injection in Generated Course Content
- Content
View full analysis
{ const selected = $('.quiz-option.selected', q); const feedback = $('.quiz-feedback', q); const correct = q.dataset.correct; const rightExp = q.dataset.explanationRight || ''; const wrongExp = q.dataset.explanationWrong || ''; if (!selected) { feedback.textContent = 'Pick an answer first!'; feedback.className = 'quiz-feedback show warning'; return; } $$('.quiz-option', q).forEach(o => o.disabled = true); if (selected.dataset.value === correct) { selected.classList.add('correct'); feedback.innerHTML = '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 bug-challenge engine contains equivalent unsafe sinks: ```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', challenge).forEach(l => l.style.pointerEvents = 'none'); } else { el.classList.add('incorrect'); feedback.inner ...[truncated 3013 chars]- Remediation
View remediation
` in text nodes and code blocks. - Escape both quotation marks when inserting values into attributes. - Serialize `data-steps` through a JSON encoder rather than manually constructing attributes. - Validate and allowlist URL schemes before generating links. - Never copy repository text directly into raw HTML. 5. Treat repository source, comments, documentation, filenames, commit metadata, and configuration as untrusted input, including repositories explicitly selected by the user. 6. Add adversarial regression tests using payloads containing: - Closing tags such as `` and ``. - Single and double quotation marks. - Event-handler attributes. - `javascript:` URLs. - SVG and image-based script-capable markup. - Malformed JSON and HTML attribute boundaries. 7. Consider adding a restrictive Content Security Policy to generated courses. To make that effective, first replace inline `onclick` handlers with `addEventListener`, then disallow inline script execution and unnecessary network destinations. ]]>
