From e676ba68733be602e145ca03cff962243283b895 Mon Sep 17 00:00:00 2001 From: Till JS Date: Thu, 26 Mar 2026 14:23:29 +0100 Subject: [PATCH] fix(web): use JSON.stringify for env var injection in all hooks.server.ts Prevents potential XSS by safely serializing env values instead of using raw string interpolation. Also creates missing hooks.server.ts for context app and standardizes citycorners to use the same injection pattern. Co-Authored-By: Claude Opus 4.6 (1M context) --- apps/calendar/apps/web/src/hooks.server.ts | 12 ++++---- apps/citycorners/apps/web/src/hooks.server.ts | 22 +++++++++++---- apps/clock/apps/web/src/hooks.server.ts | 6 ++-- apps/contacts/apps/web/src/hooks.server.ts | 8 +++--- apps/context/apps/web/src/hooks.server.ts | 28 +++++++++++++++++++ apps/manacore/apps/web/src/hooks.server.ts | 12 ++++---- apps/manadeck/apps/web/src/hooks.server.ts | 6 ++-- apps/mukke/apps/web/src/hooks.server.ts | 6 ++-- apps/nutriphi/apps/web/src/hooks.server.ts | 6 ++-- apps/photos/apps/web/src/hooks.server.ts | 6 ++-- apps/picture/apps/web/src/hooks.server.ts | 6 ++-- apps/planta/apps/web/src/hooks.server.ts | 6 ++-- apps/playground/apps/web/src/hooks.server.ts | 4 +-- apps/presi/apps/web/src/hooks.server.ts | 6 ++-- apps/questions/apps/web/src/hooks.server.ts | 6 ++-- apps/skilltree/apps/web/src/hooks.server.ts | 6 ++-- apps/storage/apps/web/src/hooks.server.ts | 6 ++-- apps/todo/apps/web/src/hooks.server.ts | 6 ++-- apps/zitare/apps/web/src/hooks.server.ts | 6 ++-- 19 files changed, 101 insertions(+), 63 deletions(-) create mode 100644 apps/context/apps/web/src/hooks.server.ts diff --git a/apps/calendar/apps/web/src/hooks.server.ts b/apps/calendar/apps/web/src/hooks.server.ts index 39ea2c952..9bff13ef1 100644 --- a/apps/calendar/apps/web/src/hooks.server.ts +++ b/apps/calendar/apps/web/src/hooks.server.ts @@ -32,12 +32,12 @@ export const handle: Handle = async ({ event, resolve }) => { // Inject runtime environment variables into the HTML // These will be available on window.__PUBLIC_*__ for client-side code const envScript = ``; return injectUmamiAnalytics(html.replace('', `${envScript}`)); }, diff --git a/apps/citycorners/apps/web/src/hooks.server.ts b/apps/citycorners/apps/web/src/hooks.server.ts index 6d8b20ed7..9a8919164 100644 --- a/apps/citycorners/apps/web/src/hooks.server.ts +++ b/apps/citycorners/apps/web/src/hooks.server.ts @@ -1,19 +1,29 @@ import type { Handle } from '@sveltejs/kit'; -const PUBLIC_MANA_CORE_AUTH_URL_CLIENT = process.env.PUBLIC_MANA_CORE_AUTH_URL_CLIENT || ''; +import { injectUmamiAnalytics } from '@manacore/shared-utils/analytics-server'; +import { setSecurityHeaders } from '@manacore/shared-utils/security-headers'; + +const PUBLIC_MANA_CORE_AUTH_URL_CLIENT = + process.env.PUBLIC_MANA_CORE_AUTH_URL_CLIENT || process.env.PUBLIC_MANA_CORE_AUTH_URL || ''; const PUBLIC_BACKEND_URL_CLIENT = process.env.PUBLIC_CITYCORNERS_API_URL_CLIENT || process.env.PUBLIC_BACKEND_URL || ''; +const PUBLIC_GLITCHTIP_DSN = process.env.PUBLIC_GLITCHTIP_DSN || ''; export const handle: Handle = async ({ event, resolve }) => { const response = await resolve(event, { transformPageChunk: ({ html }) => { - return html - .replace('%env:PUBLIC_MANA_CORE_AUTH_URL_CLIENT%', PUBLIC_MANA_CORE_AUTH_URL_CLIENT) - .replace('%env:PUBLIC_MANA_CORE_AUTH_URL%', process.env.PUBLIC_MANA_CORE_AUTH_URL || '') - .replace('%env:PUBLIC_BACKEND_URL_CLIENT%', PUBLIC_BACKEND_URL_CLIENT) - .replace('%env:PUBLIC_BACKEND_URL%', process.env.PUBLIC_BACKEND_URL || ''); + const envScript = ``; + return injectUmamiAnalytics(html.replace('', `${envScript}`)); }, }); + setSecurityHeaders(response, { + connectSrc: [PUBLIC_MANA_CORE_AUTH_URL_CLIENT, PUBLIC_BACKEND_URL_CLIENT], + }); + return response; }; diff --git a/apps/clock/apps/web/src/hooks.server.ts b/apps/clock/apps/web/src/hooks.server.ts index ad00e771f..3f4c150e0 100644 --- a/apps/clock/apps/web/src/hooks.server.ts +++ b/apps/clock/apps/web/src/hooks.server.ts @@ -12,9 +12,9 @@ export const handle: Handle = async ({ event, resolve }) => { const response = await resolve(event, { transformPageChunk: ({ html }) => { const envScript = ``; return injectUmamiAnalytics(html.replace('', `${envScript}`)); }, diff --git a/apps/contacts/apps/web/src/hooks.server.ts b/apps/contacts/apps/web/src/hooks.server.ts index 9c833885f..2a2aeeb52 100644 --- a/apps/contacts/apps/web/src/hooks.server.ts +++ b/apps/contacts/apps/web/src/hooks.server.ts @@ -24,10 +24,10 @@ export const handle: Handle = async ({ event, resolve }) => { // Inject runtime environment variables into the HTML // These will be available on window.__PUBLIC_*__ for client-side code const envScript = ``; return injectUmamiAnalytics(html.replace('', `${envScript}`)); }, diff --git a/apps/context/apps/web/src/hooks.server.ts b/apps/context/apps/web/src/hooks.server.ts new file mode 100644 index 000000000..3f4c150e0 --- /dev/null +++ b/apps/context/apps/web/src/hooks.server.ts @@ -0,0 +1,28 @@ +import type { Handle } from '@sveltejs/kit'; +import { injectUmamiAnalytics } from '@manacore/shared-utils/analytics-server'; +import { setSecurityHeaders } from '@manacore/shared-utils/security-headers'; + +const PUBLIC_MANA_CORE_AUTH_URL_CLIENT = + process.env.PUBLIC_MANA_CORE_AUTH_URL_CLIENT || process.env.PUBLIC_MANA_CORE_AUTH_URL || ''; +const PUBLIC_BACKEND_URL_CLIENT = + process.env.PUBLIC_BACKEND_URL_CLIENT || process.env.PUBLIC_BACKEND_URL || ''; +const PUBLIC_GLITCHTIP_DSN = process.env.PUBLIC_GLITCHTIP_DSN || ''; + +export const handle: Handle = async ({ event, resolve }) => { + const response = await resolve(event, { + transformPageChunk: ({ html }) => { + const envScript = ``; + return injectUmamiAnalytics(html.replace('', `${envScript}`)); + }, + }); + + setSecurityHeaders(response, { + connectSrc: [PUBLIC_MANA_CORE_AUTH_URL_CLIENT, PUBLIC_BACKEND_URL_CLIENT], + }); + + return response; +}; diff --git a/apps/manacore/apps/web/src/hooks.server.ts b/apps/manacore/apps/web/src/hooks.server.ts index e8393e804..a6f08d69f 100644 --- a/apps/manacore/apps/web/src/hooks.server.ts +++ b/apps/manacore/apps/web/src/hooks.server.ts @@ -29,12 +29,12 @@ export const handle: Handle = async ({ event, resolve }) => { const response = await resolve(event, { transformPageChunk: ({ html }) => { const envScript = ``; return injectUmamiAnalytics(html.replace('', `${envScript}`)); }, diff --git a/apps/manadeck/apps/web/src/hooks.server.ts b/apps/manadeck/apps/web/src/hooks.server.ts index ad00e771f..3f4c150e0 100644 --- a/apps/manadeck/apps/web/src/hooks.server.ts +++ b/apps/manadeck/apps/web/src/hooks.server.ts @@ -12,9 +12,9 @@ export const handle: Handle = async ({ event, resolve }) => { const response = await resolve(event, { transformPageChunk: ({ html }) => { const envScript = ``; return injectUmamiAnalytics(html.replace('', `${envScript}`)); }, diff --git a/apps/mukke/apps/web/src/hooks.server.ts b/apps/mukke/apps/web/src/hooks.server.ts index d04eb0a43..487cbb1e9 100644 --- a/apps/mukke/apps/web/src/hooks.server.ts +++ b/apps/mukke/apps/web/src/hooks.server.ts @@ -22,9 +22,9 @@ export const handle: Handle = async ({ event, resolve }) => { // Inject runtime environment variables into the HTML // These will be available on window.__PUBLIC_*__ for client-side code const envScript = ``; return injectUmamiAnalytics(html.replace('', `${envScript}`)); }, diff --git a/apps/nutriphi/apps/web/src/hooks.server.ts b/apps/nutriphi/apps/web/src/hooks.server.ts index 034d07032..389fd5ba5 100644 --- a/apps/nutriphi/apps/web/src/hooks.server.ts +++ b/apps/nutriphi/apps/web/src/hooks.server.ts @@ -21,9 +21,9 @@ export const handle: Handle = async ({ event, resolve }) => { // Inject runtime environment variables into the HTML // These will be available on window.__PUBLIC_*__ for client-side code const envScript = ``; return injectUmamiAnalytics(html.replace('', `${envScript}`)); }, diff --git a/apps/photos/apps/web/src/hooks.server.ts b/apps/photos/apps/web/src/hooks.server.ts index ad00e771f..3f4c150e0 100644 --- a/apps/photos/apps/web/src/hooks.server.ts +++ b/apps/photos/apps/web/src/hooks.server.ts @@ -12,9 +12,9 @@ export const handle: Handle = async ({ event, resolve }) => { const response = await resolve(event, { transformPageChunk: ({ html }) => { const envScript = ``; return injectUmamiAnalytics(html.replace('', `${envScript}`)); }, diff --git a/apps/picture/apps/web/src/hooks.server.ts b/apps/picture/apps/web/src/hooks.server.ts index ad00e771f..3f4c150e0 100644 --- a/apps/picture/apps/web/src/hooks.server.ts +++ b/apps/picture/apps/web/src/hooks.server.ts @@ -12,9 +12,9 @@ export const handle: Handle = async ({ event, resolve }) => { const response = await resolve(event, { transformPageChunk: ({ html }) => { const envScript = ``; return injectUmamiAnalytics(html.replace('', `${envScript}`)); }, diff --git a/apps/planta/apps/web/src/hooks.server.ts b/apps/planta/apps/web/src/hooks.server.ts index ad00e771f..3f4c150e0 100644 --- a/apps/planta/apps/web/src/hooks.server.ts +++ b/apps/planta/apps/web/src/hooks.server.ts @@ -12,9 +12,9 @@ export const handle: Handle = async ({ event, resolve }) => { const response = await resolve(event, { transformPageChunk: ({ html }) => { const envScript = ``; return injectUmamiAnalytics(html.replace('', `${envScript}`)); }, diff --git a/apps/playground/apps/web/src/hooks.server.ts b/apps/playground/apps/web/src/hooks.server.ts index 318f85926..908196b0c 100644 --- a/apps/playground/apps/web/src/hooks.server.ts +++ b/apps/playground/apps/web/src/hooks.server.ts @@ -9,8 +9,8 @@ export const handle: Handle = async ({ event, resolve }) => { return resolve(event, { transformPageChunk: ({ html }) => { const envScript = ``; return html.replace('', `${envScript}`); }, diff --git a/apps/presi/apps/web/src/hooks.server.ts b/apps/presi/apps/web/src/hooks.server.ts index ad00e771f..3f4c150e0 100644 --- a/apps/presi/apps/web/src/hooks.server.ts +++ b/apps/presi/apps/web/src/hooks.server.ts @@ -12,9 +12,9 @@ export const handle: Handle = async ({ event, resolve }) => { const response = await resolve(event, { transformPageChunk: ({ html }) => { const envScript = ``; return injectUmamiAnalytics(html.replace('', `${envScript}`)); }, diff --git a/apps/questions/apps/web/src/hooks.server.ts b/apps/questions/apps/web/src/hooks.server.ts index ad00e771f..3f4c150e0 100644 --- a/apps/questions/apps/web/src/hooks.server.ts +++ b/apps/questions/apps/web/src/hooks.server.ts @@ -12,9 +12,9 @@ export const handle: Handle = async ({ event, resolve }) => { const response = await resolve(event, { transformPageChunk: ({ html }) => { const envScript = ``; return injectUmamiAnalytics(html.replace('', `${envScript}`)); }, diff --git a/apps/skilltree/apps/web/src/hooks.server.ts b/apps/skilltree/apps/web/src/hooks.server.ts index 1a35656ea..8fb5f7e54 100644 --- a/apps/skilltree/apps/web/src/hooks.server.ts +++ b/apps/skilltree/apps/web/src/hooks.server.ts @@ -18,9 +18,9 @@ export const handle: Handle = async ({ event, resolve }) => { const response = await resolve(event, { transformPageChunk: ({ html }) => { const envScript = ``; return injectUmamiAnalytics(html.replace('', `${envScript}`)); }, diff --git a/apps/storage/apps/web/src/hooks.server.ts b/apps/storage/apps/web/src/hooks.server.ts index 0cf53c8e9..66966a6ab 100644 --- a/apps/storage/apps/web/src/hooks.server.ts +++ b/apps/storage/apps/web/src/hooks.server.ts @@ -24,9 +24,9 @@ export const handle: Handle = async ({ event, resolve }) => { const response = await resolve(event, { transformPageChunk: ({ html }) => { const envScript = ``; return injectUmamiAnalytics(html.replace('', `${envScript}`)); }, diff --git a/apps/todo/apps/web/src/hooks.server.ts b/apps/todo/apps/web/src/hooks.server.ts index 034d07032..389fd5ba5 100644 --- a/apps/todo/apps/web/src/hooks.server.ts +++ b/apps/todo/apps/web/src/hooks.server.ts @@ -21,9 +21,9 @@ export const handle: Handle = async ({ event, resolve }) => { // Inject runtime environment variables into the HTML // These will be available on window.__PUBLIC_*__ for client-side code const envScript = ``; return injectUmamiAnalytics(html.replace('', `${envScript}`)); }, diff --git a/apps/zitare/apps/web/src/hooks.server.ts b/apps/zitare/apps/web/src/hooks.server.ts index 6d9ea842a..5cab98b4b 100644 --- a/apps/zitare/apps/web/src/hooks.server.ts +++ b/apps/zitare/apps/web/src/hooks.server.ts @@ -21,9 +21,9 @@ export const handle: Handle = async ({ event, resolve }) => { // Inject runtime environment variables into the HTML // These will be available on window.__PUBLIC_*__ for client-side code const envScript = ``; return injectUmamiAnalytics(html.replace('', `${envScript}`)); },