Skip to main content
doc0blade47/honodocumentation home
Sign in

Secure Headers and CORS

Last updated Oct 12, 2026100% grounded
Relevant source files

The following files were used as context for generating this wiki page:

Overview

Hono provides robust middleware components for enforcing web security policies and managing cross-origin resource sharing. The secureHeaders middleware injects foundational defense headers such as X-Content-Type-Options, X-Frame-Options, Strict-Transport-Security, and dynamic Content Security Policy rules complete with cryptographic nonce generation. Complementing this, the cors middleware handles complex browser preflight requests, origin validation, and credentials configuration to safely permit cross-origin access.

Sources: src/middleware/secure-headers/secure-headers.ts:69-145, src/middleware/cors/index.ts:9-148

Secure Headers Middleware Architecture

Public Entry Points and Types

The secure headers middleware exports public entry points and type definitions via src/middleware/secure-headers/index.ts and src/middleware/secure-headers/secure-headers.ts. It exposes the secureHeaders middleware handler function, the NONCE content security policy handler constant, ContentSecurityPolicyOptionHandler, and SecureHeadersVariables which augment Hono's ContextVariableMap with secureHeadersNonce.

Sources: src/middleware/secure-headers/index.ts:1-8, src/middleware/secure-headers/secure-headers.ts:6-145

Default Header Mappings and Configuration Lifecycle

The middleware maintains a static mapping of header identifiers to default header names and fallback directive values through HEADERS_MAP and establishes baseline options via DEFAULT_OPTIONS. Each policy header can be toggled via boolean configuration or overridden with custom string values.

Option KeyHTTP Header NameDefault Value / State
crossOriginEmbedderPolicyCross-Origin-Embedder-Policyrequire-corp (Disabled by default: false)
crossOriginResourcePolicyCross-Origin-Resource-Policysame-origin (Enabled: true)
crossOriginOpenerPolicyCross-Origin-Opener-Policysame-origin (Enabled: true)
originAgentClusterOrigin-Agent-Cluster?1 (Enabled: true)
referrerPolicyReferrer-Policyno-referrer (Enabled: true)
strictTransportSecurityStrict-Transport-Securitymax-age=15552000; includeSubDomains (Enabled: true)
xContentTypeOptionsX-Content-Type-Optionsnosniff (Enabled: true)
xDnsPrefetchControlX-DNS-Prefetch-Controloff (Enabled: true)
xDownloadOptionsX-Download-Optionsnoopen (Enabled: true)
xFrameOptionsX-Frame-OptionsSAMEORIGIN (Enabled: true)
xPermittedCrossDomainPoliciesX-Permitted-Cross-Domain-Policiesnone (Enabled: true)
xXssProtectionX-XSS-Protection0 (Enabled: true)

Sources: src/middleware/secure-headers/secure-headers.ts:94-124

Note

The secureHeadersNonce variable checks the current context state for an existing cryptographic nonce before executing generateNonce(), utilizing crypto.getRandomValues() on a 16-byte Uint8Array combined with encodeBase64().

Sources: src/middleware/secure-headers/secure-headers.ts:131-145

Content Security Policy Configuration

CSP Options and Dynamic Nonce Generation

The secureHeaders middleware supports configuring contentSecurityPolicy and contentSecurityPolicyReportOnly options via ContentSecurityPolicyOptions. Each directive accepts an array of string values or ContentSecurityPolicyOptionHandler callbacks. The built-in NONCE handler checks context storage for an existing secureHeadersNonce variable; if absent, it allocates a 16-byte Uint8Array, populates it using crypto.getRandomValues(), encodes the buffer into base64 via encodeBase64(), stores it in the context, and returns the formatted 'nonce-<nonce>' string.

export const NONCE: ContentSecurityPolicyOptionHandler = (ctx) => {
  const key = 'secureHeadersNonce'
  const init = ctx.get(key)
  const nonce = init || generateNonce()
  if (init == null) {
    ctx.set(key, nonce)
  }
  return `'nonce-${nonce}'`
}

Sources: src/middleware/secure-headers/secure-headers.ts:15-44, src/middleware/secure-headers/secure-headers.ts:131-145

Note

Reusing the NONCE handler across multiple directives within the same request lifecycle retrieves the cached nonce from the context rather than generating a new random buffer for each directive.

Sources: src/middleware/secure-headers/secure-headers.ts:137-143

Supported Content Security Policy Directives

Option PropertyDirective Name / PurposeValue Type
defaultSrcdefault-src fallback fetch directiveContentSecurityPolicyOptionValue
baseUribase-uri restriction for <base> elementsContentSecurityPolicyOptionValue
childSrcchild-src for web workers and nested browsing contextsContentSecurityPolicyOptionValue
connectSrcconnect-src targets for fetch, XHR, and WebSocketsContentSecurityPolicyOptionValue
fontSrcfont-src valid sources for loading fontsContentSecurityPolicyOptionValue
formActionform-action valid endpoints for form submissionsContentSecurityPolicyOptionValue
frameAncestorsframe-ancestors embedding restriction for framesContentSecurityPolicyOptionValue
frameSrcframe-src sources for nested browsing contextsContentSecurityPolicyOptionValue
imgSrcimg-src valid sources for imagesContentSecurityPolicyOptionValue
manifestSrcmanifest-src sources for application manifestsContentSecurityPolicyOptionValue
mediaSrcmedia-src sources for audio and video elementsContentSecurityPolicyOptionValue
objectSrcobject-src sources for <object>, <embed>, and <applet>ContentSecurityPolicyOptionValue
reportToreport-to group destination identifierstring
reportUrireport-uri endpoint URL or array of URLs`string
sandboxsandbox applied sandbox restrictionsContentSecurityPolicyOptionValue
scriptSrcscript-src valid sources for JavaScriptContentSecurityPolicyOptionValue
scriptSrcAttrscript-src-attr valid sources for inline script event handlersContentSecurityPolicyOptionValue
scriptSrcElemscript-src-elem valid sources for script elementsContentSecurityPolicyOptionValue
styleSrcstyle-src valid sources for stylesheetsContentSecurityPolicyOptionValue
styleSrcAttrstyle-src-attr valid sources for inline style attributesContentSecurityPolicyOptionValue
styleSrcElemstyle-src-elem valid sources for style elementsContentSecurityPolicyOptionValue
upgradeInsecureRequestsupgrade-insecure-requests flag directiveContentSecurityPolicyOptionValue
workerSrcworker-src valid sources for worker scriptsContentSecurityPolicyOptionValue
requireTrustedTypesForrequire-trusted-types-for policy enforcementContentSecurityPolicyOptionValue
trustedTypestrusted-types policy namesContentSecurityPolicyOptionValue

Sources: src/middleware/secure-headers/secure-headers.ts:18-44

Permissions Policy Directives

Directive Mappings and Allowlist Formatting

The permissions-policy configuration handles W3C feature controls through PermissionsPolicyOptions, mapping directive keys to either an array of allowed origin strings or a boolean flag. The allowlist accepts standard keyword identifiers including '*', 'self', 'src', and 'none', or custom origin strings.

type PermissionsPolicyValue = '*' | 'self' | 'src' | 'none' | string
 
type PermissionsPolicyOptions = Partial<
  Record<PermissionsPolicyDirective, PermissionsPolicyValue[] | boolean>
>

Sources: src/middleware/secure-headers/secure-headers.ts:61-65

Note

Setting a permissions policy directive to true compiles to the allowlist keyword 'self', while false restricts the feature completely via 'none'.

Sources: src/middleware/secure-headers/secure-headers.ts:63-65

Standardized, Proposed, and Experimental Features

The PermissionsPolicyDirective union type incorporates standardized specifications, proposed features still undergoing standardization, and experimental features available for developer testing.

export type PermissionsPolicyDirective =
  | StandardizedFeatures
  | ProposedFeatures
  | ExperimentalFeatures

Sources: src/middleware/secure-headers/permissions-policy.ts:3-7

Feature CategoryDirective Identifiers
Standardized Featuresaccelerometer, ambientLightSensor, attributionReporting, autoplay, battery, bluetooth, camera, chUa, chUaArch, chUaBitness, chUaFullVersion, chUaFullVersionList, chUaMobile, chUaModel, chUaPlatform, chUaPlatformVersion, chUaWow64, computePressure, crossOriginIsolated, directSockets, displayCapture, encryptedMedia, executionWhileNotRendered, executionWhileOutOfViewport, fullscreen, geolocation, gyroscope, hid, identityCredentialsGet, idleDetection, keyboardMap, magnetometer, microphone, midi, navigationOverride, payment, pictureInPicture, publickeyCredentialsGet, screenWakeLock, serial, storageAccess, syncXhr, usb, webShare, windowManagement, xrSpatialTracking
Proposed FeaturesclipboardRead, clipboardWrite, gamepad, sharedAutofill, speakerSelection
Experimental FeaturesallScreensCapture, browsingTopics, capturedSurfaceControl, conversionMeasurement, digitalCredentialsGet, focusWithoutUserActivation, joinAdInterestGroup, localFonts, runAdAuction, smartCard, syncScript, trustTokenRedemption, unload, verticalScroll

Sources: src/middleware/secure-headers/permissions-policy.ts:11-86

Reporting Endpoints and Transport Security

Transport Security and Referrer Protection

The secure headers middleware manages transport encryption enforcement and information leakage prevention through dedicated configuration options. Strict-Transport-Security (HSTS) and Referrer-Policy headers leverage overridable header definitions that accept either boolean flags or explicit custom strings. When enabled via default options, HSTS defaults to a max-age of 15,552,000 seconds with subdomain inclusion, while referrer policy restricts leakage via no-referrer.

Option NameDefault Header ValueTypePurpose
strictTransportSecurityStrict-Transport-Security: max-age=15552000; includeSubDomainsoverridableHeaderEnforces secure HTTPS connections and subdomain protection
referrerPolicyReferrer-Policy: no-referreroverridableHeaderControls how referrer information is included with requests

Sources: src/middleware/secure-headers/secure-headers.ts:67-79, src/middleware/secure-headers/secure-headers.ts:99-100, src/middleware/secure-headers/secure-headers.ts:114-115

Note

An overridableHeader type resolves as either a boolean toggle controlling default behavior or an explicit string value overriding the header completely.

Sources: src/middleware/secure-headers/secure-headers.ts:67-67

Report-To and Reporting-Endpoints Configuration

The middleware supports modern browser error reporting and diagnostic infrastructure through ReportToOptions and ReportingEndpointOptions interfaces. These options configure destination groups and endpoint URLs for reporting API violations, CSP breaches, and deprecation warnings.

interface ReportToOptions {
  group: string
  max_age: number
  endpoints: ReportToEndpoint[]
}
 
interface ReportToEndpoint {
  url: string
}
 
interface ReportingEndpointOptions {
  name: string
  url: string
}

Sources: src/middleware/secure-headers/secure-headers.ts:46-59

Cross Origin Resource Sharing Architecture

CORS Options and Initialization

The CORS middleware entry point cors() accepts a configuration object defining origin, allowMethods, allowHeaders, maxAge, credentials, and exposeHeaders. When omitted, default options initialize origin to *, allowMethods to ['GET', 'HEAD', 'PUT', 'POST', 'DELETE', 'PATCH'], while allowHeaders and exposeHeaders default to empty arrays.

Option NameDefault ValueTypePurpose
origin*string | string[] | ((origin: string, c: Context) => Promise<string | undefined | null> | string | undefined | null)Sets Access-Control-Allow-Origin
allowMethods['GET', 'HEAD', 'PUT', 'POST', 'DELETE', 'PATCH']string[] | ((origin: string, c: Context) => Promise<string[]> | string[])Sets Access-Control-Allow-Methods
allowHeaders[]string[]Sets Access-Control-Allow-Headers
maxAgeundefinednumberSets Access-Control-Max-Age
credentialsundefinedbooleanSets Access-Control-Allow-Credentials
exposeHeaders[]string[]Sets Access-Control-Expose-Headers

Sources: src/middleware/cors/index.ts:9-35, src/middleware/cors/index.ts:63-70

Note

The origin resolver handles three input types: wildcard strings (*), literal matching strings, arrays of allowed origins, and custom async or sync callback functions.

Sources: src/middleware/cors/index.ts:72-84

Preflight and Response Header Execution

During a request execution lifecycle, the middleware extracts the incoming Origin header and queries findAllowOrigin. If an allowed origin is returned, it sets Access-Control-Allow-Origin. When credentials is enabled, Access-Control-Allow-Credentials is set to true. If exposeHeaders contains items, they are joined by commas and assigned to Access-Control-Expose-Headers.

if (c.req.method === 'OPTIONS') {
  if (opts.origin !== '*') {
    set('Vary', 'Origin')
  }
 
  if (opts.maxAge != null) {
    set('Access-Control-Max-Age', opts.maxAge.toString())
  }
 
  const allowMethods = await findAllowMethods(c.req.header('origin') || '', c)
  if (allowMethods.length) {
    set('Access-Control-Allow-Methods', allowMethods.join(','))
  }
 
  let headers = opts.allowHeaders
  if (!headers?.length) {
    const requestHeaders = c.req.header('Access-Control-Request-Headers')
    if (requestHeaders) {
      headers = requestHeaders.split(/\s*,\s*/)
    }
  }
  if (headers?.length) {
    set('Access-Control-Allow-Headers', headers.join(','))
    c.res.headers.append('Vary', 'Access-Control-Request-Headers')
  }
 
  c.res.headers.delete('Content-Length')
  c.res.headers.delete('Content-Type')
 
  return new Response(null, {
    headers: c.res.headers,
    status: 204,
    statusText: 'No Content',
  })
}

Sources: src/middleware/cors/index.ts:114-148

For OPTIONS preflight requests, the middleware appends Vary: Origin if origin is not *, populates Access-Control-Max-Age if maxAge is defined, and resolves allowed methods via findAllowMethods. If allowHeaders is empty, it falls back to parsing the Access-Control-Request-Headers request header. Finally, it deletes Content-Length and Content-Type headers and returns an HTTP 204 No Content response with the assembled headers. For standard requests, it invokes next() and appends Vary: Origin post-invocation if the origin option is restrictive.

Sources: src/middleware/cors/index.ts:114-156

Was this page helpful?