Review finding
The titleSlam template escapes the visible word content but interpolates the raw word into a data-text attribute in an innerHTML string.
Evidence
src/system/templates/title-slam.ts:35 builds <span class="..." data-text="${w}">${markedTextHtml(w)}</span>.
markedTextHtml(w) protects the element body, but data-text="${w}" is not attribute-escaped.
- A title token containing a quote can break out of the
data-text attribute and create additional attributes on the generated span.
Impact
Scene modules are trusted today, but L2 templates are content-facing APIs. If generated, imported, or otherwise user-authored deck content reaches this template, a title word can mutate the DOM structure or attach executable attributes.
Recommended fix
Stop constructing these spans with string HTML. Build each span with DOM APIs and assign textContent plus dataset.text / setAttribute() so the browser performs attribute escaping.
Acceptance checks
titleSlam creates word spans with ownerDoc.createElement('span'), className / classList, textContent, and an escaped data-text assignment.
- A test covers a title word containing
", <, and > and proves no additional attributes or elements are created.
.pulsar-glitch behavior still has the expected data-text value for CSS rendering.
Review finding
The
titleSlamtemplate escapes the visible word content but interpolates the raw word into adata-textattribute in aninnerHTMLstring.Evidence
src/system/templates/title-slam.ts:35builds<span class="..." data-text="${w}">${markedTextHtml(w)}</span>.markedTextHtml(w)protects the element body, butdata-text="${w}"is not attribute-escaped.data-textattribute and create additional attributes on the generated span.Impact
Scene modules are trusted today, but L2 templates are content-facing APIs. If generated, imported, or otherwise user-authored deck content reaches this template, a title word can mutate the DOM structure or attach executable attributes.
Recommended fix
Stop constructing these spans with string HTML. Build each span with DOM APIs and assign
textContentplusdataset.text/setAttribute()so the browser performs attribute escaping.Acceptance checks
titleSlamcreates word spans withownerDoc.createElement('span'),className/classList,textContent, and an escapeddata-textassignment.",<, and>and proves no additional attributes or elements are created..pulsar-glitchbehavior still has the expecteddata-textvalue for CSS rendering.