From a4c3ac9781c3081e36f554c077cb879b3be65fa3 Mon Sep 17 00:00:00 2001 From: Roomote Date: Fri, 17 Jul 2026 03:55:12 +0000 Subject: [PATCH] fix: escape theme boot storage key for script-context embedding Apply CodeQL-recommended post-JSON.stringify escapes so the inline FOUC theme boot script cannot break out of a JavaScript/HTML script context. --- apps/web/src/lib/shared/theme-boot.test.ts | 30 +++++++++++++++++++--- apps/web/src/lib/shared/theme-boot.ts | 28 +++++++++++++++++--- 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/apps/web/src/lib/shared/theme-boot.test.ts b/apps/web/src/lib/shared/theme-boot.test.ts index dda5ed571..c386af099 100644 --- a/apps/web/src/lib/shared/theme-boot.test.ts +++ b/apps/web/src/lib/shared/theme-boot.test.ts @@ -1,4 +1,9 @@ -import { getThemeBootScript, resolveBootColorTheme } from './theme-boot'; +import { + escapeJsonForJsCode, + getThemeBootScript, + resolveBootColorTheme, +} from './theme-boot'; +import { PERSONAL_THEME_STORAGE_KEY } from '@/types/preferences'; describe('theme boot helpers', () => { it('resolves explicit light and dark values directly', () => { @@ -11,7 +16,26 @@ describe('theme boot helpers', () => { expect(resolveBootColorTheme('sepia', false)).toBe('light'); }); - it('includes the Roomote storage key in the bootstrap script', () => { - expect(getThemeBootScript()).toContain('roomote-color-theme'); + it('escapes script-breakout characters after JSON.stringify', () => { + const breakout = JSON.stringify('