Arcjet Nosecone: security headers for Next.js
Arcjet Nosecone is an open source library
that helps set security headers such as Content-Security-Policy (CSP),
Strict-Transport-Security (HSTS), and X-Content-Type-Options in JS
applications built with Bun, Deno, Next.js, Node.js, or SvelteKit.
What are Arcjet utilities?
Arcjet utilities are independent libraries that do not require the use of the main Arcjet SDK - they can be used with or without other Arcjet rules.
We take the pain out of implementing security tasks through these utilities to provide a security as code approach to developer-first security.
Supported headers
Section titled “Supported headers”Nosecone helps you add and configure these headers:
Content-Security-Policy(CSP)Cross-Origin-Embedder-Policy(COEP)Cross-Origin-Opener-PolicyCross-Origin-Resource-PolicyOrigin-Agent-ClusterReferrer-PolicyStrict-Transport-Security(HSTS)X-Content-Type-OptionsX-DNS-Prefetch-ControlX-Download-OptionsX-Frame-OptionsX-Permitted-Cross-Domain-PoliciesX-XSS-Protection
For full details on each option, see the reference guide.
Quick start
Section titled “Quick start”This guide shows you how to add our recommended
1. Install Nosecone
Section titled “1. Install Nosecone”In your project root, install the Arcjet Nosecone library for your framework:
npm i @nosecone/nextpnpm add @nosecone/nextyarn add @nosecone/next2. Configure your application
Section titled “2. Configure your application”Nosecone applies headers to all your routes with middleware in your Next.js application.
import { createMiddleware } from "@nosecone/next";
// Remove your middleware matcher so Nosecone runs on every route.
export default createMiddleware();import { createMiddleware } from "@nosecone/next";
// Remove your middleware matcher so Nosecone runs on every route.
export default createMiddleware();We recommend you remove any export const config = ... from your middleware so
Nosecone runs on every route. This ensures the headers are applied to all
requests.
You also need to opt-out of static generation in your application. See the
@nosecone/next reference guide for more details
about this requirement.
To opt-out of static generation, modify your layout file with the following:
import { connection } from "next/server";import type { PropsWithChildren } from "react";
export default async function RootLayout(props: PropsWithChildren) { // Opt-out of static generation for every page so the CSP nonce can be applied await connection();
// ...}import { connection } from "next/server";
export default async function RootLayout(props) { // Opt-out of static generation for every page so the CSP nonce can be applied await connection();
// ...}We recommend you remove any export const config = ... from your middleware so
Nosecone runs on every route. This ensures the headers are applied to all
requests.
3. Run your application
Section titled “3. Run your application”npm run devpnpm run devyarn run dev4. Inspect the headers
Section titled “4. Inspect the headers”The default headers apply a pragmatic set of security headers to your application, but may break things (particularly the CSP header).
We recommend you test your application thoroughly and tweak the settings to ensure it continues to work as expected.
Inspect the headers with the curl command:
curl -I -X GET localhost:3000The printed headers look something like this:
HTTP/1.1 200 OKcontent-security-policy: base-uri 'none'; child-src 'none'; connect-src 'self'; default-src 'self'; font-src 'self'; form-action 'self'; frame-ancestors 'none'; frame-src 'none'; img-src 'self' blob: data:; manifest-src 'self'; media-src 'self'; object-src 'none'; script-src 'nonce-YWUwNGIwMTMtOTgwYi00MWNiLWI3M2QtMjBkYWQwODMxZTNi' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; worker-src 'self';cross-origin-embedder-policy: require-corpcross-origin-opener-policy: same-origincross-origin-resource-policy: same-originorigin-agent-cluster: ?1referrer-policy: no-referrerstrict-transport-security: max-age=31536000; includeSubDomainsx-content-type-options: nosniffx-dns-prefetch-control: offx-download-options: noopenx-frame-options: SAMEORIGINx-permitted-cross-domain-policies: nonex-xss-protection: 0Vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Router-Segment-Prefetch, Accept-Encodinglink: </_next/static/media/a34f9d1faa5f3315-s.p.woff2>; rel=preload; as="font"; crossorigin=""; nonce="YWUwNGIwMTMtOTgwYi00MWNiLWI3M2QtMjBkYWQwODMxZTNi"; type="font/woff2", </vercel.svg>; rel=preload; as="image", </next.svg>; rel=preload; as="image", </_next/static/css/app/layout.css?v=1732741292630>; rel=preload; as="style"; nonce="YWUwNGIwMTMtOTgwYi00MWNiLWI3M2QtMjBkYWQwODMxZTNi"Cache-Control: no-store, must-revalidateX-Powered-By: Next.jsContent-Type: text/html; charset=utf-8Date: Wed, 27 Nov 2024 21:01:32 GMTConnection: keep-aliveKeep-Alive: timeout=5Transfer-Encoding: chunkedWhat next?
Section titled “What next?”Explore
Section titled “Explore”Arcjet can protect your entire app or individual routes with a few lines of code. Using the main Arcjet SDK you can set up bot protection, rate limiting for your API, minimize fraudulent registrations with the signup form protection and more.
Get help
Section titled “Get help”Need help with anything? Email support@arcjet.com to get support from our engineering team, join our Discord, or open an issue on GitHub.