From f953167e599d9f8bb0a7476fc0e98182acb4a71a Mon Sep 17 00:00:00 2001 From: David Mytton Date: Wed, 11 Dec 2024 07:55:19 +0000 Subject: [PATCH] Add security headers docs --- docs/features/security/headers.mdx | 85 +++++++++++++++++++++++++----- 1 file changed, 72 insertions(+), 13 deletions(-) diff --git a/docs/features/security/headers.mdx b/docs/features/security/headers.mdx index b6346479..02355115 100644 --- a/docs/features/security/headers.mdx +++ b/docs/features/security/headers.mdx @@ -3,25 +3,84 @@ title: Security Headers description: Security headers used to protect your application. --- -next-forge uses [next-secure-headers](https://github.com/jagaapple/next-secure-headers) to set HTTP response headers related to security. +next-forge uses [Nosecone](https://docs.arcjet.com/nosecone/quick-start) to set HTTP response headers related to security. ## Configuration Here are the headers we have enabled: -| Property | Header | Description | Value | -| --- | --- | --- | --- | -| `forceHTTPSRedirect` | `Strict-Transport-Security` | Prevents browsers from connecting to your site over HTTP. | `[true, { maxAge: 63_072_000, includeSubDomains: true, preload: true }]` | -| `frameGuard` | `X-Frame-Options` | Prevents browsers from rendering your site in an iframe. | `deny` | -| `noopen` | `X-Download-Options` | Prevents browsers from automatically opening downloaded files in the same origin as the page. | `noopen` | -| `nosniff` | `X-Content-Type-Options` | Prevents browsers from MIME-sniffing a response away from the declared content type. | `nosniff` | -| `xssProtection` | `X-XSS-Protection` | Prevents browsers from executing inline scripts if a cross-site scripting attack is detected. | `sanitize` | -| `contentSecurityPolicy` | `Content-Security-Policy` | Sets a policy to prevent a wide range of different types of attacks, including Cross Site Scripting (XSS) and data injection attacks. | `false` | -| `expectCT` | `Expect-CT` | Enables a mechanism to mitigate the risk of fraudulent certificates being used in connections to your site. | `false` | -| `referrerPolicy` | `Referrer-Policy` | Controls how much of the full URL is included in the `Referer` header. | `false` | +- `Cross-Origin-Embedder-Policy` (COEP) +- `Cross-Origin-Opener-Policy` +- `Cross-Origin-Resource-Policy` +- `Origin-Agent-Cluster` +- `Referrer-Policy` +- `Strict-Transport-Security` (HSTS) +- `X-Content-Type-Options` +- `X-DNS-Prefetch-Control` +- `X-Download-Options` +- `X-Frame-Options` +- `X-Permitted-Cross-Domain-Policies` +- `X-XSS-Protection` -The `forceHTTPSRedirect` property has been customized from the default to include subdomains and preload the HSTS policy. This should allow you to submit your site at [hstspreload.org](https://hstspreload.org/) without any issues. +See the [Nosecone reference](https://docs.arcjet.com/nosecone/reference) for details on each header and configuration options. ## Usage -The headers are enabled by default when using the `next-config` package. If you are customizing your `next.config.ts` file, you can extend the headers manually. +Recommended headers are set by default and configured in `@repo/security/middleware`. Changing the configuration here will affect all apps. + +They are then attached to the response within the middleware in `apps/app/middleware` and `apps/web/middleware.ts`. Adjusting the configuration in these files will only affect the specific app. + +## Content Security Policy (CSP) + +The CSP header is not set by default because it requires specific configuration based on the Next Forge features you have enabled. We hope to change this in the future once [#332](https://github.com/haydenbleasel/next-forge/pull/332) is resolved. + +In the meantime, you can set the CSP header using the Nosecone configuration. For example, the following CSP configuration will work with the default Next Forge features: + +```ts +import type { NoseconeOptions } from '@nosecone/next'; +import { defaults as noseconeDefaults } from '@nosecone/next'; + +const noseconeOptions: NoseconeOptions = { + ...noseconeDefaults, + contentSecurityPolicy: { + ...noseconeDefaults.contentSecurityPolicy, + directives: { + ...noseconeDefaults.contentSecurityPolicy.directives, + scriptSrc: [ + // We have to use unsafe-inline because next-themes and Vercel Analytics + // do not support nonce + // https://github.com/pacocoursey/next-themes/issues/106 + // https://github.com/vercel/analytics/issues/122 + //...noseconeDefaults.contentSecurityPolicy.directives.scriptSrc, + "'self'", + "'unsafe-inline'", + "https://www.googletagmanager.com", + "https://*.clerk.accounts.dev", + "https://va.vercel-scripts.com", + ], + connectSrc: [ + ...noseconeDefaults.contentSecurityPolicy.directives.connectSrc, + "https://*.clerk.accounts.dev", + "https://*.google-analytics.com", + "https://clerk-telemetry.com", + ], + workerSrc: [ + ...noseconeDefaults.contentSecurityPolicy.directives.workerSrc, + "blob:", + "https://*.clerk.accounts.dev" + ], + imgSrc: [ + ...noseconeDefaults.contentSecurityPolicy.directives.imgSrc, + "https://img.clerk.com" + ], + objectSrc: [ + ...noseconeDefaults.contentSecurityPolicy.directives.objectSrc, + ], + // We only set this in production because the server may be started + // without HTTPS + upgradeInsecureRequests: process.env.NODE_ENV === "production", + }, + }, +} +``` +