Skip to main content

Import

import { secureHeaders, NONCE } from 'hono/secure-headers'

Usage

const app = new Hono()

app.use(secureHeaders())

app.get('/', (c) => c.text('Hello Hono!'))

Options

The secureHeaders middleware accepts an optional SecureHeadersOptions object:
contentSecurityPolicy
ContentSecurityPolicyOptions
Settings for the Content-Security-Policy header. Configure directives like defaultSrc, scriptSrc, styleSrc, etc.
contentSecurityPolicyReportOnly
ContentSecurityPolicyOptions
Settings for the Content-Security-Policy-Report-Only header. Same structure as contentSecurityPolicy but for report-only mode.
crossOriginEmbedderPolicy
boolean | string
default:false
Settings for the Cross-Origin-Embedder-Policy header. Default value: "require-corp"
crossOriginResourcePolicy
boolean | string
default:true
Settings for the Cross-Origin-Resource-Policy header. Default value: "same-origin"
crossOriginOpenerPolicy
boolean | string
default:true
Settings for the Cross-Origin-Opener-Policy header. Default value: "same-origin"
originAgentCluster
boolean | string
default:true
Settings for the Origin-Agent-Cluster header. Default value: "?1"
referrerPolicy
boolean | string
default:true
Settings for the Referrer-Policy header. Default value: "no-referrer"
reportingEndpoints
ReportingEndpointOptions[]
Settings for the Reporting-Endpoints header. Array of objects with name and url properties.
reportTo
ReportToOptions[]
Settings for the Report-To header. Array of objects with group, max_age, and endpoints properties.
strictTransportSecurity
boolean | string
default:true
Settings for the Strict-Transport-Security header. Default value: "max-age=15552000; includeSubDomains"
xContentTypeOptions
boolean | string
default:true
Settings for the X-Content-Type-Options header. Default value: "nosniff"
xDnsPrefetchControl
boolean | string
default:true
Settings for the X-DNS-Prefetch-Control header. Default value: "off"
xDownloadOptions
boolean | string
default:true
Settings for the X-Download-Options header. Default value: "noopen"
xFrameOptions
boolean | string
default:true
Settings for the X-Frame-Options header. Default value: "SAMEORIGIN"
xPermittedCrossDomainPolicies
boolean | string
default:true
Settings for the X-Permitted-Cross-Domain-Policies header. Default value: "none"
xXssProtection
boolean | string
default:true
Settings for the X-XSS-Protection header. Default value: "0"
removePoweredBy
boolean
default:true
Whether to remove the X-Powered-By header.
permissionsPolicy
PermissionsPolicyOptions
Settings for the Permissions-Policy header. Object mapping permission directives to their values.

Signature

secureHeaders(customOptions?: SecureHeadersOptions): MiddlewareHandler

NONCE Helper

The NONCE helper generates a cryptographically secure nonce for CSP:
import { secureHeaders, NONCE } from 'hono/secure-headers'

app.use(secureHeaders({
  contentSecurityPolicy: {
    scriptSrc: [NONCE, 'https://allowed-cdn.com'],
  },
}))

app.get('/', (c) => {
  const nonce = c.get('secureHeadersNonce')
  return c.html(`<script nonce="${nonce}">alert('hello')</script>`)
})

Examples

Basic usage with defaults

const app = new Hono()

app.use(secureHeaders())

Custom Content Security Policy

app.use(secureHeaders({
  contentSecurityPolicy: {
    defaultSrc: ["'self'"],
    scriptSrc: ["'self'", "'unsafe-inline'", 'https://cdn.example.com'],
    styleSrc: ["'self'", 'https://fonts.googleapis.com'],
    imgSrc: ["'self'", 'data:', 'https:'],
    fontSrc: ["'self'", 'https://fonts.gstatic.com'],
    connectSrc: ["'self'", 'https://api.example.com'],
  },
}))

Using NONCE for scripts

app.use(secureHeaders({
  contentSecurityPolicy: {
    scriptSrc: [NONCE],
  },
}))

app.get('/', (c) => {
  const nonce = c.get('secureHeadersNonce')
  return c.html(`
    <html>
      <head>
        <script nonce="${nonce}">
          console.log('This script is allowed')
        </script>
      </head>
    </html>
  `)
})

Custom Strict Transport Security

app.use(secureHeaders({
  strictTransportSecurity: 'max-age=63072000; includeSubDomains; preload',
}))

Disable specific headers

app.use(secureHeaders({
  xFrameOptions: false,
  xXssProtection: false,
}))

Permissions Policy

app.use(secureHeaders({
  permissionsPolicy: {
    camera: false,
    microphone: false,
    geolocation: ['self', 'https://trusted.example.com'],
    payment: true,
  },
}))

Report-Only CSP

app.use(secureHeaders({
  contentSecurityPolicyReportOnly: {
    defaultSrc: ["'self'"],
    reportUri: '/csp-report',
  },
}))

With Reporting Endpoints

app.use(secureHeaders({
  reportingEndpoints: [
    { name: 'csp-endpoint', url: 'https://example.com/csp-reports' },
  ],
  contentSecurityPolicy: {
    defaultSrc: ["'self'"],
    reportTo: 'csp-endpoint',
  },
}))

Default Values

When called without options, secureHeaders() sets these headers:
  • Cross-Origin-Resource-Policy: same-origin
  • Cross-Origin-Opener-Policy: same-origin
  • Origin-Agent-Cluster: ?1
  • Referrer-Policy: no-referrer
  • Strict-Transport-Security: max-age=15552000; includeSubDomains
  • X-Content-Type-Options: nosniff
  • X-DNS-Prefetch-Control: off
  • X-Download-Options: noopen
  • X-Frame-Options: SAMEORIGIN
  • X-Permitted-Cross-Domain-Policies: none
  • X-XSS-Protection: 0
  • Removes X-Powered-By header

CSP Directives

Available Content Security Policy directives:
  • defaultSrc
  • baseUri
  • childSrc
  • connectSrc
  • fontSrc
  • formAction
  • frameAncestors
  • frameSrc
  • imgSrc
  • manifestSrc
  • mediaSrc
  • objectSrc
  • reportTo
  • reportUri
  • sandbox
  • scriptSrc
  • scriptSrcAttr
  • scriptSrcElem
  • styleSrc
  • styleSrcAttr
  • styleSrcElem
  • upgradeInsecureRequests
  • workerSrc
  • requireTrustedTypesFor
  • trustedTypes

Behavior

  • Sets security headers after handler execution
  • Headers can be overridden by providing string values
  • Headers can be disabled by setting to false
  • CSP directives support dynamic values via callback functions
  • NONCE helper generates unique nonce per request and stores in context
  • Removes X-Powered-By header by default
  • Supports both Content-Security-Policy and Content-Security-Policy-Report-Only

Build docs developers (and LLMs) love