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.
Quick start
To get started, follow our quick start guide .
Next.js security headers can be set using the @nosecone/next
adapter.
This provides defaults to ensure Next.js applications work in production &
development environments and the createMiddleware(options?: NoseconeOptions)
API to create a Next.js middleware that runs on every request.
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 () ;
If the Content-Security-Policy
header is specified via middleware, Next.js
will look for a script-src
that starts with nonce-
and apply it for each
<script>
generated by the framework. This requires that opting-out of static
generation, which requires modifying your Layout
:
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
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
import { unstable_noStore as noStore } from " next/cache " ;
import type { PropsWithChildren } from " react " ;
export default function RootLayout ( props : PropsWithChildren ) {
// Opt-out of static generation for every page so the CSP nonce can be applied
import { unstable_noStore as noStore } from " next/cache " ;
export default function RootLayout ( props ) {
// Opt-out of static generation for every page so the CSP nonce can be applied
Additional resources:
The @nosecone/sveltekit
adapter provides defaults to ensure SvelteKit is
configured correctly.
npm i @nosecone/sveltekit
pnpm add @nosecone/sveltekit
yarn add @nosecone/sveltekit
This also provides the csp(options?: ContentSecurityPolicyConfig)
function
to translate Nosecone configuration to SvelteKit configuration in
svelte.config.js
, and the createHook(options?: NoseconeOptions)
function to
create a SvelteKit hook that runs on every request.
Update your svelte.config.js
to configure csp
:
import adapter from " @sveltejs/adapter-auto " ;
import { vitePreprocess } from " @sveltejs/vite-plugin-svelte " ;
import { csp } from " @nosecone/sveltekit "
/** @ type { import('@sveltejs/kit').Config } */
preprocess : vitePreprocess () ,
// Apply CSP with Nosecone defaults
Create the src/hooks.server.ts
file in your project with the contents:
import { createHook } from " @nosecone/sveltekit " ;
import { sequence } from " @sveltejs/kit/hooks " ;
export const handle = sequence ( createHook ()) ;
Create the src/hooks.server.js
file in your project with the contents:
import { createHook } from " @nosecone/sveltekit " ;
import { sequence } from " @sveltejs/kit/hooks " ;
export const handle = sequence ( createHook ()) ;
Additional resources:
API
The default export is a function that returns a set of Headers
to apply to a
request that help you secure your application. The defaults should work for many
applications, but all can be configured or disabled for specific requirements.
NoseconeOptions
All entries in NoseconeOptions
can be enabled with defaults by specifying
true
or disabled by specifying false
. Additionally, many allow individual
configuration via their own configuration objects, which override any defaults.
You can use object spread, e.g. ...defaults
, to combine the default values
with your overrides.
interface NoseconeOptions {
* Configure the `Content-Security-Policy` header, which helps mitigate a
* large number of attacks, such as cross-site scripting.
contentSecurityPolicy ?: ContentSecurityPolicyConfig | boolean ;
* Configure the `Cross-Origin-Embedder-Policy` header, which helps control
* what resources can be loaded cross-origin.
crossOriginEmbedderPolicy ?: CrossOriginEmbedderPolicyConfig | boolean ;
* Configure the `Cross-Origin-Opener-Policy` header, which helps
* process-isolate your page.
crossOriginOpenerPolicy ?: CrossOriginOpenerPolicyConfig | boolean ;
* Configure the `Cross-Origin-Resource-Policy` header, which blocks others
* from loading your resources cross-origin in some cases.
crossOriginResourcePolicy ?: CrossOriginResourcePolicyConfig | boolean ;
* Configure the `Origin-Agent-Cluster` header, which provides a mechanism to
* allow web applications to isolate their origins from other processes.
originAgentCluster ?: boolean ;
* Configure the `Referrer-Policy` header, which controls what information is
* set in the `Referer` request header.
referrerPolicy ?: ReferrerPolicyConfig | boolean ;
* Configure the `Strict-Transport-Security` header, which tells browsers to
* prefer HTTPS instead of insecure HTTP.
strictTransportSecurity ?: StrictTransportSecurityConfig | boolean ;
* Configure the `X-Content-Type-Options` header, which helps mitigate MIME
* type sniffing that can cause security issues.
xContentTypeOptions ?: boolean ;
* Configure the `X-DNS-Prefetch-Control` header, which helps control DNS
* prefetching to improve user privacy at the expense of performance.
xDnsPrefetchControl ?: DnsPrefetchControlConfig | boolean ;
* Configure the `X-Download-Options` header, which prevents a user from
* opening a file directly in Internet Explorer 8 to avoid prevent script
xDownloadOptions ?: boolean ;
* Configure the `X-Frame-Options` header, which helps mitigate clickjacking
* attacks in legacy browsers. This header is superceded by a directive in the
* `Content-Security-Policy` header.
xFrameOptions ?: FrameOptionsConfig | boolean ;
* Configure the `X-Permitted-Cross-Domain-Policies` header, which tells some
* clients, like Adobe products, your domain's policy for loading cross-domain
xPermittedCrossDomainPolicies ?: PermittedCrossDomainPoliciesConfig | boolean ;
* Disable the `X-XSS-Protection` header, which could introduce a browser
* side-channel if enabled.
xXssProtection ?: boolean ;
Nosecone provides the withVercelToolbar
utility function to augment Nosecone
options so the Vercel
Toolbar is
allowed by the various headers.
This follows the guidelines documented by Vercel under Using a Content Security
Policy ,
but we recommend conditionally adding this based on process.env.VERCEL_ENV
:
import nosecone , { defaults , withVercelToolbar } from " nosecone " ;
import type { NoseconeOptions } from " nosecone " ;
const noseconeConfig : NoseconeOptions = {
// Any customizations needed
const headers = nosecone (
process . env . VERCEL_ENV === " preview "
? withVercelToolbar ( noseconeConfig )
import nosecone , { defaults , withVercelToolbar } from " nosecone " ;
// Any customizations needed
const headers = nosecone (
process . env . VERCEL_ENV === " preview "
? withVercelToolbar ( noseconeConfig )
Content-Security-Policy
The Content-Security-Policy
header is a powerful allow-list of what can happen
on your page which helps mitigate many attacks, such as cross-site scripting.
Types:
type StaticOrDynamic < S > = boolean | readonly ( S | ( () => S ))[] | null ;
| `${ string } . ${ string } : ${ number }`
| `${ string } . ${ string } :* `
| `${ string } :// ${ string } . ${ string }`
| `${ string } :// ${ string } . ${ string } : ${ number }`
| `${ string } :// ${ string } . ${ string } :* `
| `${ string } ://localhost `
| `${ string } ://localhost: ${ number }`
| `${ string } ://localhost:* `
| `${ string } . ${ string } : ${ number }`
| `${ string } . ${ string } :* `
| `${ string } :// ${ string } . ${ string }`
| `${ string } :// ${ string } . ${ string } : ${ number }`
| `${ string } :// ${ string } . ${ string } :* `
| `${ string } ://localhost `
| `${ string } ://localhost: ${ number }`
| `${ string } ://localhost:* ` ;
| `${ string } . ${ string } : ${ number }`
| `${ string } . ${ string } :* `
| `${ string } :// ${ string } . ${ string }`
| `${ string } :// ${ string } . ${ string } : ${ number }`
| `${ string } :// ${ string } . ${ string } :* `
| `${ string } ://localhost `
| `${ string } ://localhost: ${ number }`
| `${ string } ://localhost:* `
type ActionSource = " 'strict-dynamic' " | " 'report-sample' " ;
baseUri ?: StaticOrDynamic < Source | ActionSource > | undefined ;
childSrc ?: StaticOrDynamic < Source > | undefined ;
defaultSrc ?: StaticOrDynamic < Source | ActionSource > | undefined ;
frameSrc ?: StaticOrDynamic < Source > | undefined ;
workerSrc ?: StaticOrDynamic < Source > | undefined ;
connectSrc ?: StaticOrDynamic < Source > | undefined ;
fontSrc ?: StaticOrDynamic < Source > | undefined ;
imgSrc ?: StaticOrDynamic < Source > | undefined ;
manifestSrc ?: StaticOrDynamic < Source > | undefined ;
mediaSrc ?: StaticOrDynamic < Source > | undefined ;
objectSrc ?: StaticOrDynamic < Source > | undefined ;
prefetchSrc ?: StaticOrDynamic < Source > | undefined ;
scriptSrc ?: StaticOrDynamic < Source | ActionSource > | undefined ;
scriptSrcElem ?: StaticOrDynamic < Source > | undefined ;
scriptSrcAttr ?: StaticOrDynamic < Source > | undefined ;
styleSrc ?: StaticOrDynamic < Source | ActionSource > | undefined ;
styleSrcElem ?: StaticOrDynamic < Source > | undefined ;
styleSrcAttr ?: StaticOrDynamic < Source > | undefined ;
| " allow-downloads-without-user-activation "
| " allow-orientation-lock "
| " allow-popups-to-escape-sandbox "
| " allow-storage-access-by-user-activation "
| " allow-top-navigation-by-user-activation "
formAction ?: StaticOrDynamic < Source | ActionSource > | undefined ;
| StaticOrDynamic < HostSource | SchemeSource | FrameSource >
navigateTo ?: StaticOrDynamic < Source | ActionSource > | undefined ;
reportUri ?: string [] | undefined ;
reportTo ?: string [] | undefined ;
requireTrustedTypesFor ?: ReadonlyArray < " script " > | undefined ;
| ReadonlyArray < " none " | " allow-duplicates " | " * " | string >
upgradeInsecureRequests ?: boolean | undefined ;
type ContentSecurityPolicyConfig = {
directives ?: Readonly < CspDirectives > | undefined ;
Defaults:
frameAncestors : [ " 'none' " ] ,
imgSrc : [ " 'self' " , " blob: " , " data: " ] ,
The defaults will produce the following header:
Content-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 'self'; style-src 'self'; worker-src 'self';
Additional resources:
Cross-Origin-Embedder-Policy
The Cross-Origin-Embedder-Policy
header helps control what resources can be
loaded cross-origin.
Types:
type CrossOriginEmbedderPolicyConfig = {
policy ?: " require-corp " | " credentialless " | " unsafe-none " | undefined ;
Defaults:
The defaults will produce the following header:
Cross-Origin-Embedder-Policy: require-corp
Additional resources:
Cross-Origin-Opener-Policy
The Cross-Origin-Opener-Policy
header helps process-isolate your page.
Types:
type CrossOriginOpenerPolicyConfig = {
| " same-origin-allow-popups "
Defaults:
The defaults will produce the following header:
Cross-Origin-Opener-Policy: same-origin
Additional resources:
Cross-Origin-Resource-Policy
The Cross-Origin-Resource-Policy
header blocks others from loading your
resources cross-origin in some cases.
Types:
type CrossOriginResourcePolicyConfig = {
policy ?: " same-origin " | " same-site " | " cross-origin " | undefined ;
Defaults:
The defaults will produce the following header:
Cross-Origin-Resource-Policy: same-origin
Additional resources:
Origin-Agent-Cluster
The Origin-Agent-Cluster
header provides a mechanism to allow web applications
to isolate their origins from other processes.
Types:
type OriginAgentClusterConfig = boolean ;
Defaults:
The defaults will produce the following header:
Additional resources:
Referrer-Policy
The Referrer-Policy
header controls what information is set in the Referer
request header.
Types:
type ReferrerPolicyConfig = {
policy ?: ReadonlyArray < ReferrerPolicyToken > | undefined ;
type ReferrerPolicyToken =
| " no-referrer-when-downgrade "
| " origin-when-cross-origin "
| " strict-origin-when-cross-origin "
Defaults:
The defaults will produce the following header:
Referrer-Policy: no-referrer
Additional resources:
Strict-Transport-Security
The Strict-Transport-Security
header tells browsers to prefer HTTPS instead of
insecure HTTP.
Types:
type StrictTransportSecurityConfig = {
maxAge ?: number | undefined ;
includeSubDomains ?: boolean | undefined ;
preload ?: boolean | undefined ;
Defaults:
maxAge : 31536000 , // 1 year
The defaults will produce the following header:
Strict-Transport-Security: max-age=31536000; includeSubDomains
Additional resources:
X-Content-Type-Options
The X-Content-Type-Options
header helps mitigate MIME type sniffing that can
cause security issues.
Types:
type ContentTypeOptionsConfig = boolean ;
Defaults:
The defaults will produce the following header:
X-Content-Type-Options: nosniff
Additional resources:
X-DNS-Prefetch-Control
The X-DNS-Prefetch-Control
header helps control DNS prefetching to improve
user privacy at the expense of performance.
Types:
type DnsPrefetchControlConfig = {
allow ?: boolean | undefined ;
Defaults:
The defaults will produce the following header:
X-DNS-Prefetch-Control: off
Additional resources:
X-Download-Options
(legacy)
The legacy X-Download-Options
header prevented a user from opening a file
directly in Internet Explorer to avoid prevent script injection.
Types:
type DownloadOptionsCofig = boolean ;
Defaults:
The defaults will produce the following header:
X-Download-Options: noopen
Additional resources:
X-Frame-Options
(legacy)
The legacy X-Frame-Options
header helped mitigate clickjacking attacks in
older browsers.
Types:
type FrameOptionsConfig = {
action ?: " deny " | " sameorigin " | undefined ;
Defaults:
The defaults will produce the following header:
X-Frame-Options: SAMEORIGIN
Additional resources:
X-Permitted-Cross-Domain-Policies
The X-Permitted-Cross-Domain-Policies
header tells some clients, like Adobe
products, your domain’s policy for loading cross-domain content.
Types:
type PermittedCrossDomainPoliciesConfig = {
Defaults:
permittedPolicies : " none " ,
The defaults will produce the following header:
X-Permitted-Cross-Domain-Policies: none
Additional resources:
X-XSS-Protection
(legacy)
The legacy X-XSS-Protection
header tried to mitigate XSS attacks, but
accidentally enabled side-channel attacks in older browsers, so Nosecone
disables it.
Types:
type XssProtectionConfig = boolean ;
Defaults:
The defaults will produce the following header:
Additional resources: