Skip to content

Improve security headers#16

Merged
pedrordgs merged 1 commit intomasterfrom
fix/security-audit
Jan 12, 2026
Merged

Improve security headers#16
pedrordgs merged 1 commit intomasterfrom
fix/security-audit

Conversation

@pedrordgs
Copy link
Owner

@pedrordgs pedrordgs commented Jan 12, 2026

Description

Type of Change

  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 📝 Documentation update
  • 🎨 Style/UI update (no functional changes)
  • ♻️ Code refactoring (no functional changes)
  • ⚡ Performance improvement
  • ✅ Test update

Related Issues

Fixes #
Related to #

Screenshots

Before

After

Additional Context

Deployment Notes


Summary by CodeRabbit

  • New Features

    • Implemented Content Security Policy with nonce support for enhanced application security.
    • Added security headers configuration to HTTP responses.
  • Chores

    • Updated CI/CD dependency vulnerability scanning with stricter thresholds.
    • Optimized Docker build process to improve deployment efficiency.
    • Migrated security header configuration from deployment platform to application codebase.

✏️ Tip: You can customize this high-level summary in your review settings.

@pedrordgs pedrordgs requested a review from Copilot January 12, 2026 22:56
@pedrordgs pedrordgs self-assigned this Jan 12, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 12, 2026

📝 Walkthrough

Walkthrough

This pull request implements Content Security Policy (CSP) nonce support across the application. It introduces server-side nonce generation via middleware, integrates nonce passing through the layout and theme provider components, adds security headers to the Next.js config, and tightens npm audit requirements in CI/CD pipelines.

Changes

Cohort / File(s) Summary
Security Headers & CSP Configuration
next.config.ts, vercel.json
Added async headers() function in Next.js config to apply security headers (X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy) to all routes. Removed redundant headers block from Vercel configuration.
CSP Nonce Middleware
proxy.ts
New middleware module that generates a base64-encoded nonce per request, constructs CSP header with nonce support, conditionally enables unsafe-eval/unsafe-inline in development, and applies security headers to both request and response.
CSP Nonce Integration
app/layout.tsx, components/theme/theme-provider.tsx
Made RootLayout async to retrieve nonce from request headers and pass it to ThemeProvider. Updated ThemeProvider to accept optional nonce prop and forward it to NextThemesProvider.
Build Configuration
.github/workflows/ci.yml, Dockerfile
Replaced npm audit steps with single high-severity check (removed moderate-level and dry-run variants). Added --ignore-scripts flag to npm install to skip lifecycle script execution.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A nonce flows through the app with care,
From headers down to layouts fair,
Security wrapped in every thread,
CSP keeps our scripts well-fed! 🔐

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Improve security headers' is fully related to the main changes in the changeset. The PR implements multiple security enhancements including CSP headers with nonces, HTTP security headers in next.config.ts, npm audit level changes, and moves headers configuration from vercel.json to Next.js config, all directly addressing security header improvements.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves security headers by migrating from Vercel's header configuration to Next.js middleware with Content Security Policy (CSP) implementation. The changes introduce a nonce-based CSP for script and style protection while maintaining other security headers.

Changes:

  • Moved security header configuration from vercel.json to next.config.ts
  • Added new middleware (proxy.ts) to implement CSP with nonce generation
  • Updated ThemeProvider to support CSP nonces for inline styles

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
vercel.json Removed header configuration and framework declaration (moved to next.config.ts)
proxy.ts New middleware file implementing CSP with nonce-based script/style protection
next.config.ts Added headers configuration for X-Content-Type-Options, X-Frame-Options, Referrer-Policy, and Permissions-Policy
components/theme/theme-provider.tsx Added nonce prop support for CSP compliance
app/layout.tsx Made RootLayout async to retrieve nonce from headers and pass to ThemeProvider
Dockerfile Added --ignore-scripts flag to npm install for improved security
.github/workflows/ci.yml Changed npm audit level from moderate to high and removed continue-on-error

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +2 to +4

export function proxy(request: NextRequest) {
const nonce = Buffer.from(crypto.randomUUID()).toString("base64");
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The nonce generation is not cryptographically secure. Using Buffer.from(crypto.randomUUID()).toString("base64") generates a nonce by encoding a UUID, but crypto.randomUUID() generates a UUID v4 which is intended for unique identifiers, not cryptographic nonces.

For CSP nonces, use crypto.getRandomValues() or crypto.randomBytes() to generate truly random bytes. For example: Buffer.from(crypto.getRandomValues(new Uint8Array(16))).toString("base64") or in Node.js: crypto.randomBytes(16).toString("base64").

Suggested change
export function proxy(request: NextRequest) {
const nonce = Buffer.from(crypto.randomUUID()).toString("base64");
import { randomBytes } from "crypto";
export function proxy(request: NextRequest) {
const nonce = randomBytes(16).toString("base64");

Copilot uses AI. Check for mistakes.
object-src 'none';
base-uri 'self';
form-action 'self';
frame-ancestors 'none';
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CSP header does not include connect-src directive, which defaults to default-src 'self'. This might be too restrictive if the application needs to make API calls to external services. Consider explicitly setting connect-src to match your application's requirements.

Additionally, consider adding other security directives like worker-src, manifest-src, and media-src if the application uses service workers, web manifests, or media resources.

Suggested change
frame-ancestors 'none';
frame-ancestors 'none';
connect-src 'self';
worker-src 'self';
manifest-src 'self';
media-src 'self';

Copilot uses AI. Check for mistakes.

# Install all dependencies (including dev) for build
RUN npm install
RUN npm install --ignore-scripts
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding --ignore-scripts to npm install in the build stage may prevent necessary build scripts from running. While this flag improves security by preventing arbitrary script execution, it can break packages that rely on postinstall scripts for compilation or setup.

Ensure that all dependencies work correctly without their install scripts, or consider using a more targeted approach like npm config set ignore-scripts true for specific packages only. Test the build thoroughly to verify no functionality is broken.

Suggested change
RUN npm install --ignore-scripts
RUN npm install

Copilot uses AI. Check for mistakes.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
next.config.ts (1)

6-30: Good security header configuration.

The headers cover essential protections: MIME sniffing prevention, clickjacking defense, referrer control, and permissions restrictions.

Consider adding Strict-Transport-Security (HSTS) if the application is served exclusively over HTTPS:

{
  key: 'Strict-Transport-Security',
  value: 'max-age=31536000; includeSubDomains',
},

Note: X-XSS-Protection was previously in vercel.json but is omitted here—this is acceptable since the header is deprecated in modern browsers in favor of CSP.

proxy.ts (1)

4-4: Consider using crypto.getRandomValues() for nonce generation.

While crypto.randomUUID() provides sufficient entropy (122 bits), a more direct approach for CSP nonces uses crypto.getRandomValues():

Alternative nonce generation
-  const nonce = Buffer.from(crypto.randomUUID()).toString("base64");
+  const nonce = Buffer.from(crypto.getRandomValues(new Uint8Array(16))).toString("base64");

This generates 128 bits of cryptographically secure randomness directly.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e7943b7 and bd90f04.

📒 Files selected for processing (7)
  • .github/workflows/ci.yml
  • Dockerfile
  • app/layout.tsx
  • components/theme/theme-provider.tsx
  • next.config.ts
  • proxy.ts
  • vercel.json
🧰 Additional context used
🧬 Code graph analysis (1)
app/layout.tsx (2)
next.config.ts (1)
  • headers (6-30)
components/theme/theme-provider.tsx (1)
  • ThemeProvider (9-22)
🔇 Additional comments (8)
Dockerfile (1)

24-24: Good security hardening with --ignore-scripts.

Disabling lifecycle scripts during install mitigates supply-chain attacks from malicious postinstall scripts.

Verify the build completes successfully—some packages (e.g., sharp, esbuild, native bindings) rely on postinstall scripts to download platform-specific binaries. If the build fails with missing binaries, you may need to selectively allow scripts or use pre-built alternatives.

vercel.json (1)

1-7: LGTM!

Consolidating security headers in next.config.ts ensures consistent behavior across deployment environments (Vercel and self-hosted via Docker). The migration is complete—X-XSS-Protection is correctly omitted as it's deprecated.

.github/workflows/ci.yml (1)

67-68: LGTM!

Removing continue-on-error ensures the pipeline fails on high/critical vulnerabilities, enforcing a stricter security posture. The --audit-level=high threshold is a reasonable balance—consider periodic reviews of moderate vulnerabilities to prevent accumulation.

app/layout.tsx (2)

61-61: LGTM!

The nonce is correctly propagated to ThemeProvider, which forwards it to NextThemesProvider for nonce-based inline style injection. This enables strict CSP without 'unsafe-inline' for theme styles.


5-5: CSP nonce integration correctly implemented.

The async conversion and nonce retrieval follow the recommended Next.js 15 server component pattern. The x-nonce header is properly generated in proxy.ts (line 23) using a cryptographically secure UUID, applied to CSP directives for both scripts and styles in production, and safely retrieved in the layout with a fallback to undefined. The implementation enables inline style support for theme switching without requiring unsafe-inline in the CSP policy.

Also applies to: 49-54

components/theme/theme-provider.tsx (1)

5-9: Consider simplifying the Props interface.

The Omit<ThemeProviderProps, "nonce"> followed by re-declaring nonce?: string may be unnecessary if ThemeProviderProps already defines nonce as string | undefined. However, if you're intentionally narrowing or documenting the type, this is fine.

The nonce forwarding logic is correct and integrates well with the CSP implementation.

proxy.ts (2)

35-40: Matcher configuration looks good.

The matcher correctly excludes static assets and image files from middleware processing, which is the recommended pattern for CSP middleware.


7-20: No connect-src directive needed.

The codebase does not contain any external API calls (no fetch, axios, or external URLs detected). The CSP correctly falls back to default-src 'self' for the connect-src directive, which is the appropriate configuration for an application that only makes same-origin requests.

Likely an incorrect or invalid review comment.

@pedrordgs pedrordgs merged commit cda16c0 into master Jan 12, 2026
11 checks passed
@pedrordgs pedrordgs deleted the fix/security-audit branch January 12, 2026 23:06
@coderabbitai coderabbitai bot mentioned this pull request Jan 12, 2026
8 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants