Skip to content

Commit 47b230c

Browse files
authored
Merge pull request #6 from Sparths/Dev
CSP Fix
2 parents ea39cf9 + a75cdd4 commit 47b230c

File tree

3 files changed

+40
-20
lines changed

3 files changed

+40
-20
lines changed

app/layout.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// app/layout.tsx - Updated version
12
import "./globals.css";
23
import type { Metadata } from "next";
34
import { SavedProvider } from "./saved/SavedContext";
@@ -9,6 +10,7 @@ import { Toaster } from "@/components/ui/toaster";
910
import { SpeedInsights } from "@vercel/speed-insights/next";
1011
import DiscordPromo from "@/components/DiscordPromo";
1112
import ProjectUpdaterWorker from "@/components/ProjectUpdaterWorker";
13+
import { headers } from "next/headers";
1214

1315
export const metadata: Metadata = {
1416
title: "Code Gems - Discover Remarkable GitHub Projects",
@@ -70,15 +72,27 @@ export const metadata: Metadata = {
7072
},
7173
};
7274

73-
export default function RootLayout({
75+
export default async function RootLayout({
7476
children,
7577
}: {
7678
children: React.ReactNode;
7779
}) {
80+
// Get the CSP nonce from headers
81+
const headersList = await headers();
82+
const nonce = headersList.get('X-CSP-Nonce') || undefined;
83+
7884
return (
7985
<html lang="en">
8086
<head>
8187
<link rel="canonical" href="https://codegems.xyz" />
88+
{nonce && (
89+
<script
90+
nonce={nonce}
91+
dangerouslySetInnerHTML={{
92+
__html: `window.__CSP_NONCE__ = '${nonce}';`
93+
}}
94+
/>
95+
)}
8296
</head>
8397
<body>
8498
<AuthProvider>

lib/security/security-headers.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// lib/security-headers.ts
1+
// lib/security/security-headers.ts - Updated version
22
import { NextRequest, NextResponse } from 'next/server';
33
import React from 'react';
44

@@ -18,23 +18,27 @@ export function applySecurityHeaders(
1818
// Generate CSP nonce if not provided
1919
const cspNonce = nonce || generateNonce();
2020

21-
// Content Security Policy - Strict
21+
// Content Security Policy - More lenient for development
22+
const isDevelopment = process.env.NODE_ENV === 'development';
23+
2224
const csp = [
2325
"default-src 'self'",
24-
`script-src 'self' 'nonce-${cspNonce}' https://cdnjs.cloudflare.com https://va.vercel-scripts.com`,
25-
"style-src 'self' 'unsafe-inline'", // Unfortunately needed for Tailwind
26+
isDevelopment
27+
? `script-src 'self' 'unsafe-inline' 'unsafe-eval' 'nonce-${cspNonce}' https://cdnjs.cloudflare.com https://va.vercel-scripts.com https://vercel.live`
28+
: `script-src 'self' 'nonce-${cspNonce}' https://cdnjs.cloudflare.com https://va.vercel-scripts.com`,
29+
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
2630
"img-src 'self' data: https: blob:",
27-
"font-src 'self' data:",
28-
"connect-src 'self' https://api.github.com https://*.supabase.co wss://*.supabase.co https://vitals.vercel-insights.com",
31+
"font-src 'self' data: https://fonts.gstatic.com",
32+
"connect-src 'self' https://api.github.com https://*.supabase.co wss://*.supabase.co https://vitals.vercel-insights.com https://vercel.live",
2933
"frame-src 'none'",
3034
"object-src 'none'",
3135
"base-uri 'self'",
3236
"form-action 'self'",
3337
"frame-ancestors 'none'",
34-
"upgrade-insecure-requests",
38+
isDevelopment ? "" : "upgrade-insecure-requests",
3539
"block-all-mixed-content",
3640
"manifest-src 'self'"
37-
].join('; ');
41+
].filter(Boolean).join('; ');
3842

3943
response.headers.set('Content-Security-Policy', csp);
4044

@@ -47,8 +51,8 @@ export function applySecurityHeaders(
4751
response.headers.set('X-Download-Options', 'noopen');
4852
response.headers.set('X-Permitted-Cross-Domain-Policies', 'none');
4953

50-
// Strict Transport Security (HSTS)
51-
if (process.env.NODE_ENV === 'production') {
54+
// Strict Transport Security (HSTS) - only in production
55+
if (!isDevelopment) {
5256
response.headers.set(
5357
'Strict-Transport-Security',
5458
'max-age=31536000; includeSubDomains; preload'
@@ -102,7 +106,7 @@ export function getSecurityHeadersForRoute(pathname: string): Record<string, str
102106
return baseHeaders;
103107
}
104108

105-
// React component to inject CSP nonce
109+
// React component to inject CSP nonce - Updated
106110
export function SecurityHeaders({ nonce }: { nonce: string }): React.ReactElement {
107111
return React.createElement('script', {
108112
nonce: nonce,

middleware.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1-
// middleware.ts
1+
// middleware.ts - Updated version
22
import { NextResponse } from 'next/server';
33
import type { NextRequest } from 'next/server';
4-
import { securityMiddleware } from './lib/security/security-headers';
4+
import { generateNonce, applySecurityHeaders } from './lib/security/security-headers';
55
import { rateLimit, createRateLimitHeaders } from './lib/security/rate-limiter-config';
66

77
export async function middleware(request: NextRequest) {
8-
// Apply security headers first
9-
let response = securityMiddleware(request);
8+
// Generate a nonce for this request
9+
const nonce = generateNonce();
10+
11+
// Create response with security headers and nonce
12+
let response = NextResponse.next();
13+
response = applySecurityHeaders(response, request, nonce);
1014

1115
// Apply rate limiting to API routes
1216
if (request.nextUrl.pathname.startsWith('/api/')) {
@@ -106,10 +110,8 @@ export async function middleware(request: NextRequest) {
106110
response.headers.set('X-Robots-Tag', 'noindex, nofollow, noarchive, nosnippet');
107111
}
108112

109-
// Add security headers for all responses
110-
response.headers.set('X-Content-Type-Options', 'nosniff');
111-
response.headers.set('X-Frame-Options', 'DENY');
112-
response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin');
113+
// Ensure the nonce is available for the layout
114+
response.headers.set('X-CSP-Nonce', nonce);
113115

114116
return response;
115117
}

0 commit comments

Comments
 (0)