Content Security Policy

İçerik Güvenliği Politikası (CSP) Next.js uygulamanızı siteler arası komut dosyası oluşturma (XSS), clickjacking ve diğer kod enjeksiyon saldırıları gibi çeşitli güvenlik tehditlerine karşı korumak için önemlidir.

Geliştiriciler CSP'yi kullanarak içerik kaynakları, komut dosyaları, stil sayfaları, görüntüler, yazı tipleri, nesneler, medya (ses, video), iframe'ler ve daha fazlası için hangi kökenlere izin verileceğini belirleyebilirler.

Examples

Nonces

Nonce tek seferlik kullanım için oluşturulmuş benzersiz, rastgele bir karakter dizisidir. CSP ile birlikte, katı CSP yönergelerini atlayarak belirli satır içi komut dosyalarının veya stillerin yürütülmesine seçici olarak izin vermek için kullanılır.

Why use a nonce?

CSP'ler kötü amaçlı komut dosyalarını engellemek için tasarlanmış olsa da, satır içi komut dosyalarının gerekli olduğu meşru senaryolar vardır. Bu gibi durumlarda nonce'lar, doğru nonce'a sahip olmaları halinde bu komut dosyalarının çalışmasına izin vermenin bir yolunu sunar.

Adding a nonce with Middleware

Ara yazılım, sayfa oluşturulmadan önce başlıklar eklemenize ve nonces oluşturmanıza olanak tanır.

Bir sayfa her görüntülendiğinde, yeni bir nonce oluşturulmalıdır. Bu, nonce eklemek için dinamik işleme kullanmanız gerektiği anlamına gelir.

Örneğin:

middleware.ts
import { NextRequest, NextResponse } from 'next/server'
 
export function middleware(request: NextRequest) {
  const nonce = Buffer.from(crypto.randomUUID()).toString('base64')
  const cspHeader = `
    default-src 'self';
    script-src 'self' 'nonce-${nonce}' 'strict-dynamic';
    style-src 'self' 'nonce-${nonce}';
    img-src 'self' blob: data:;
    font-src 'self';
    object-src 'none';
    base-uri 'self';
    form-action 'self';
    frame-ancestors 'none';
    block-all-mixed-content;
    upgrade-insecure-requests;
`
  // Replace newline characters and spaces
  const contentSecurityPolicyHeaderValue = cspHeader
    .replace(/\s{2,}/g, ' ')
    .trim()
 
  const requestHeaders = new Headers(request.headers)
  requestHeaders.set('x-nonce', nonce)
 
  requestHeaders.set(
    'Content-Security-Policy',
    contentSecurityPolicyHeaderValue
  )
 
  const response = NextResponse.next({
    request: {
      headers: requestHeaders,
    },
  })
  response.headers.set(
    'Content-Security-Policy',
    contentSecurityPolicyHeaderValue
  )
 
  return response
}

Varsayılan olarak, Middleware tüm isteklerde çalışır. Middleware'i belirli yollarda çalışacak şekilde filtreleyebilirsiniz. matcher.

Eşleşen prefetch'leri ( next/link adresinden) ve CSP başlığına ihtiyaç duymayan statik varlıkları göz ardı etmenizi öneririz.

middleware.ts
export const config = {
  matcher: [
    /*
     * Match all request paths except for the ones starting with:
     * - api (API routes)
     * - _next/static (static files)
     * - _next/image (image optimization files)
     * - favicon.ico (favicon file)
     */
    {
      source: '/((?!api|_next/static|_next/image|favicon.ico).*)',
      missing: [
        { type: 'header', key: 'next-router-prefetch' },
        { type: 'header', key: 'purpose', value: 'prefetch' },
      ],
    },
  ],
}

Reading the nonce

Artık nonce'u bir Sunucu Bileşeninden şu şekilde okuyabilirsiniz headers:

app/page.tsx
import { headers } from 'next/headers'
import Script from 'next/script'
 
export default function Page() {
  const nonce = headers().get('x-nonce')
 
  return (
    <Script
      src="https://www.googletagmanager.com/gtag/js"
      strategy="afterInteractive"
      nonce={nonce}
    />
  )
}

Without Nonces

Nonces gerektirmeyen uygulamalar için CSP başlığını doğrudan next.config.js Dosya:

next.config.js
const cspHeader = `
    default-src 'self';
    script-src 'self' 'unsafe-eval' 'unsafe-inline';
    style-src 'self' 'unsafe-inline';
    img-src 'self' blob: data:;
    font-src 'self';
    object-src 'none';
    base-uri 'self';
    form-action 'self';
    frame-ancestors 'none';
    block-all-mixed-content;
    upgrade-insecure-requests;
`
 
module.exports = {
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: [
          {
            key: 'Content-Security-Policy',
            value: cspHeader.replace(/\n/g, ''),
          },
        ],
      },
    ]
  },
}

Version History

Nonce'ları düzgün bir şekilde işlemek ve uygulamak için Next.js'nin v13.4.20+ adresini kullanmanızı öneririz.