From ab03ee3a4d48a3217b8a8d09e51705c02ef5be21 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 27 Jun 2026 00:55:55 -0400 Subject: [PATCH] fix login --- apps/homepage/src/lib/security/csp.ts | 12 ++++++++++-- apps/homepage/src/proxy.ts | 18 +++++++++++++++++- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/apps/homepage/src/lib/security/csp.ts b/apps/homepage/src/lib/security/csp.ts index 7ea0b27..a1ee362 100644 --- a/apps/homepage/src/lib/security/csp.ts +++ b/apps/homepage/src/lib/security/csp.ts @@ -2,17 +2,25 @@ export function createNonce(): string { return crypto.randomUUID().replaceAll('-', ''); } -export function buildContentSecurityPolicy(nonce: string, development: boolean): string { +export function buildContentSecurityPolicy( + nonce: string, + development: boolean, + apiOrigin?: string, +): string { const scriptSources = ["'self'", `'nonce-${nonce}'`, "'strict-dynamic'"]; if (development) scriptSources.push("'unsafe-eval'"); + const connectSources = ["'self'"]; + if (development) connectSources.push('ws:', 'wss:'); + if (apiOrigin) connectSources.push(apiOrigin); + const directives = [ "default-src 'self'", `script-src ${scriptSources.join(' ')}`, `style-src 'self'${development ? " 'unsafe-inline'" : ` 'nonce-${nonce}'`}`, "img-src 'self' data: blob:", "font-src 'self' data:", - `connect-src 'self'${development ? ' ws: wss:' : ''}`, + `connect-src ${connectSources.join(' ')}`, "media-src 'self'", "object-src 'none'", "base-uri 'self'", diff --git a/apps/homepage/src/proxy.ts b/apps/homepage/src/proxy.ts index 3b75c2e..7135a81 100644 --- a/apps/homepage/src/proxy.ts +++ b/apps/homepage/src/proxy.ts @@ -19,9 +19,25 @@ function applySecurityHeaders(response: NextResponse, contentSecurityPolicy: str return response; } +function resolveApiOrigin(): string | undefined { + const origins = new Set(); + const urls = [process.env.API_INTERNAL_URL, process.env.NEXT_PUBLIC_API_URL]; + for (const url of urls) { + if (!url) continue; + try { + origins.add(new URL(url).origin); + } catch { + // ignore malformed URLs + } + } + return origins.size > 0 ? Array.from(origins).join(' ') : undefined; +} + export function proxy(request: NextRequest): NextResponse { const nonce = createNonce(); - const csp = buildContentSecurityPolicy(nonce, process.env.NODE_ENV !== 'production'); + const isDev = process.env.NODE_ENV !== 'production'; + const apiOrigin = resolveApiOrigin(); + const csp = buildContentSecurityPolicy(nonce, isDev, apiOrigin); const requestHeaders = new Headers(request.headers); requestHeaders.set('x-nonce', nonce); requestHeaders.set('Content-Security-Policy', csp);