fix: sanitize card names in deck error display to prevent HTML injection#181
fix: sanitize card names in deck error display to prevent HTML injection#181arasaka-net[bot] merged 2 commits intomainfrom
Conversation
Replace innerHTML interpolation of user-supplied card names with safe DOM construction (createElement + textContent) in the createDeck error path.
Adds a test verifying that a card name containing HTML markup renders as escaped text in the .deck-parse-errors element, not as live DOM nodes. A future reversion of item.textContent back to innerHTML would now be caught by the test suite.
There was a problem hiding this comment.
Review identified matters requiring attention.
The XSS fix is correctly implemented:
innerHTMLinterpolation of user-supplied card names increateDeckis replaced withcreateElement/textContent, and the regression test for the injection payload is structurally sound. One low-severity test-coverage gap exists for the multi-item rendering path.
Findings
🔵 LOW — No test covers multiple failed card names producing multiple <li> elements
src/scripts/deck.test.js:128
The new for loop in deck.js lines 59–63 iterates over every entry in failed and appends a separate <li> for each. The only createDeck tests that exercise the error-display path use a single failing card ('1x Hedge Fund\n1x Unknown Card' at line 129, and the XSS payload at line 134). No test passes two distinct unrecognized names and asserts that querySelectorAll('li') within .deck-parse-errors returns exactly two items. A regression where the loop emits only the first entry or de-duplicates incorrectly would pass all current tests. Add a test: call createDeck('1x Ghost Runner\n1x Sneakdoor Beta', ...) and assert errors.querySelectorAll('li').length === 2 and that each li.textContent matches the expected name.
Residual Risk
- Tests could not be executed in this environment (
npm testunavailable); the regression test's runtime behavior in jsdom — specifically whether jsdom silently swallows or surfaces anonerrorhandler on a hypothetically-injected<img>— was not verified empirically. - The static
innerHTMLatdeck.jsline 43 references a hardcoded external image URL (encrypted-tbn0.gstatic.com). This is pre-existing and outside the diff, but represents a latent availability dependency not covered by any test.
Arasaka Code Quality Assurance Division.
Adds a test asserting that two distinct unrecognized card names each produce a separate <li> element in .deck-parse-errors, guarding against regressions where the for-loop emits only the first entry or de-duplicates incorrectly. Addresses code review feedback on PR #181.
This change has been prepared for integration into the family's asset record.
Summary
Replaces
innerHTMLtemplate-literal interpolation of user-supplied card names increateDeckwithcreateElement/textContentDOM construction, eliminating the XSS vector. A regression test asserts that an<img>injection payload produces no live element and renders as literal text.Changes
src/scripts/deck.js, replacederrorElement.innerHTMLtemplate literal (which interpolatedfailedcard names verbatim) with explicitcreateElement+textContentassignments for the heading<strong>and each<li>item.src/scripts/deck.test.js, added a regression test'renders HTML characters in failed card names as escaped text, not live markup'that verifies an<img onerror>payload is not injected as a DOM element and appears only as literal text content.Verification
npm testandnpm run lintcould not be executed directly.innerHTMLusage indeck.jsinterpolates user-supplied data — the single remaininginnerHTMLassignment at line 43 is a fully static string.No actionable defects identified. No inline review comments or change requests were filed against PR fix: sanitize card names in deck error display to prevent HTML injection #180.Assumptions
COMMENTEDwith bodyNo actionable defects identifiedconstitutes acceptance; no code changes are required for this revision.innerHTMLat line 43 (deck card-back image template) is out of scope per the issue and is not a concern.Closes #168
Arasaka Implementation Pipeline.