[object Object]

← back to Crazy News Channel

Escape quotes in escapeHTML: close admin-headline attribute injection

87e501c2ab9645ff9782a24eca1452059c32d8ad · 2026-09-23 19:11:16 -0700 · Steve Abrams

CTA gate (c69818e) reproduced in Chrome and WebKit that escapeHTML(), built on
textContent->innerHTML, never encoded quotes, so an admin headline containing "
broke out of title/aria-label (admin list) and alt (article photo) and could add
event handlers. escapeHTML now encodes & < > " ' so it is safe in text and
quoted attributes alike. Negative test: injected attributes 2 -> 0 in both
engines. Quoted/apostrophe/ampersand headlines render exactly as typed; arc,
frame-sweep, hash, Cody-fix and WebKit regressions still pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011iuURMrsPBwAqMc5LgvFLH

Files touched

Diff

commit 87e501c2ab9645ff9782a24eca1452059c32d8ad
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Sep 23 19:11:16 2026 -0700

    Escape quotes in escapeHTML: close admin-headline attribute injection
    
    CTA gate (c69818e) reproduced in Chrome and WebKit that escapeHTML(), built on
    textContent->innerHTML, never encoded quotes, so an admin headline containing "
    broke out of title/aria-label (admin list) and alt (article photo) and could add
    event handlers. escapeHTML now encodes & < > " ' so it is safe in text and
    quoted attributes alike. Negative test: injected attributes 2 -> 0 in both
    engines. Quoted/apostrophe/ampersand headlines render exactly as typed; arc,
    frame-sweep, hash, Cody-fix and WebKit regressions still pass.
    
    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_011iuURMrsPBwAqMc5LgvFLH
---
 index.html | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/index.html b/index.html
index fb34dfa..0cac330 100644
--- a/index.html
+++ b/index.html
@@ -1253,10 +1253,17 @@ function storyCardHTML(story, isLead) {
   `;
 }
 
+// Safe for both text content AND quoted attributes. The old textContent ->
+// innerHTML trick never encoded quotes, so an admin headline containing "
+// broke out of title/aria-label/alt attributes and could add event handlers
+// (CTA-verified in Chrome + WebKit).
 function escapeHTML(str) {
-  const div = document.createElement("div");
-  div.textContent = str;
-  return div.innerHTML;
+  return String(str == null ? "" : str)
+    .replace(/&/g, "&amp;")
+    .replace(/</g, "&lt;")
+    .replace(/>/g, "&gt;")
+    .replace(/"/g, "&quot;")
+    .replace(/'/g, "&#39;");
 }
 
 // Keyed in-place reconcile for the story grid. tick() re-renders roughly once

← c69818e CTA pass: escalation-arc feature (e4c7519) + regression — fi  ·  back to Crazy News Channel  ·  Add CHAOS INDEX: a global escalation gauge that degrades the 0e2f7d8 →