[object Object]

← back to Crazy News Channel Shadowman

Fix malformed hash crash: wrap decodeURIComponent in try/catch, start tick before renderRoute

63ec4a9df83c4d95d43cd6db26043baa33bcdae2 · 2026-09-23 17:47:26 -0700 · Steve Abrams

Hole #1 from Cody red-team: a malformed URI fragment (e.g., #/article/%) caused
decodeURIComponent() to throw an uncaught URIError in getRouteId(), which aborted
init() before setInterval(tick, 1000) could register. This froze the clock and
escalation forever. Now: (1) getRouteId wraps decode in try/catch, returning null
on malformed URIs just like unknown ids; (2) setInterval(tick) fires BEFORE
renderRoute() so clock starts even if routing fails. Reproduced + verified fixed
on malformed hash — clock now ticks with zero errors.

Files touched

Diff

commit 63ec4a9df83c4d95d43cd6db26043baa33bcdae2
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Sep 23 17:47:26 2026 -0700

    Fix malformed hash crash: wrap decodeURIComponent in try/catch, start tick before renderRoute
    
    Hole #1 from Cody red-team: a malformed URI fragment (e.g., #/article/%) caused
    decodeURIComponent() to throw an uncaught URIError in getRouteId(), which aborted
    init() before setInterval(tick, 1000) could register. This froze the clock and
    escalation forever. Now: (1) getRouteId wraps decode in try/catch, returning null
    on malformed URIs just like unknown ids; (2) setInterval(tick) fires BEFORE
    renderRoute() so clock starts even if routing fails. Reproduced + verified fixed
    on malformed hash — clock now ticks with zero errors.
---
 index.html | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/index.html b/index.html
index b5cce6f..996871c 100644
--- a/index.html
+++ b/index.html
@@ -1723,7 +1723,13 @@ function findArticleSource(id) {
 
 function getRouteId() {
   const m = location.hash.match(/^#\/article\/(.+)$/);
-  return m ? decodeURIComponent(m[1]) : null;
+  if (!m) return null;
+  try {
+    return decodeURIComponent(m[1]);
+  } catch (e) {
+    // Malformed URI (e.g., %XX with no valid hex) — treat as "not found"
+    return null;
+  }
 }
 
 function buildRelatedLinks(currentId) {
@@ -1939,11 +1945,13 @@ function init() {
   updateMoodUI();
   setTickerMode(state.reducedMotion);
   refreshTicker();
+  // Start the 1000ms tick loop BEFORE rendering route, so malformed hashes
+  // can't abort init() and freeze the clock/escalation forever
+  setInterval(tick, 1000);
   renderStories();
   renderFeatures();
   renderRoute({ moveFocus: false }); // honor a deep link on initial load, without stealing focus from the page load itself
   updateClock();
-  setInterval(tick, 1000);
 }
 
 document.addEventListener("DOMContentLoaded", init);

← 744e857 Add remaining SDXL story photos (all 40 stories now have an  ·  back to Crazy News Channel Shadowman  ·  auto-data-snapshot: 2026-09-23T17:59:00 (5 data files) — cta 213738e →