Orientation Arc
Routing Algorithms
Rendering and JSX
Runtime Adapters
Middleware Ecosystem
Developer Helpers
System Utilities
The following files were used as context for generating this wiki page:
The "Security Headers" subsystem in Hono is designed to enforce secure communication policies by automatically injecting standard HTTP security headers into outgoing server responses. It addresses common web vulnerabilities (such as XSS, clickjacking, and content sniffing) by providing a declarative middleware that ensures headers are set consistently across all routes or specific endpoints.
The design relies on a central middleware factory, secureHeaders(), which merges user-provided configuration with internal defaults. By operating within the middleware lifecycle, it guarantees that headers are applied after application logic execution, maintaining consistency regardless of route-specific response variations.
Beyond simple header injection, the system handles dynamic policy generation, including CSP (Content Security Policy) nonce management and Permissions-Policy parsing. It interacts closely with the Hono Context to store and retrieve nonces, facilitating seamless integration with template engines or frontend rendering helpers that need to reference these tokens for inline scripts.
secureHeaders Middleware SurfaceThe secureHeaders middleware serves as the primary entry point, accepting a SecureHeadersOptions object. It initializes by merging user-provided overrides, then filters headers based on the provided configuration. The middleware returns a handler that intercepts the request flow, executes necessary callbacks (such as dynamic CSP directive updates), and applies the finalized headers after the await next() call, ensuring that all headers are present in the response object before it reaches the client.
const app = new Hono()
app.use(secureHeaders())Sources: src/middleware/secure-headers/secure-headers.ts:179-229
The subsystem internally processes secure header configurations by mapping keys from SecureHeadersOptions to their corresponding HTTP header names and default values. During initialization, the middleware checks if a configuration key is present in the SecureHeadersOptions object, using internal mapping logic (getFilteredHeaders) to convert these into a list of [string, string] pairs, which are then applied to the response.
Sources: src/middleware/secure-headers/secure-headers.ts:231-238
The CSP mechanism is significantly more complex than standard headers because directives often require dynamic values (e.g., nonces). The getCSPDirectives function parses the ContentSecurityPolicyOptions object, identifying any directive values that are functions. These function-based values are replaced by placeholders, and their corresponding logic is registered as a callback.
At request time, these callbacks are executed to generate the dynamic part of the directive (like a fresh random nonce), which is then injected into the final CSP string. This allows Hono to maintain the state of the nonces within the Context using the secureHeadersNonce key, ensuring that the same nonce is available to both the CSP header and the application rendering logic.
Sources: src/middleware/secure-headers/secure-headers.ts:240-288
The NONCE export functions as a utility to handle nonce generation for CSP. When invoked, it retrieves or generates a 16-byte random nonce using the Web Crypto API, then stores it in the Context. This ensures that if the middleware is triggered during a template render, the same nonce is consistent throughout the request lifecycle.
export const NONCE = (ctx: Context) => {
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:137-145
Important
The secureHeadersNonce is stored in the Context variables. If developers add multiple custom CSP callbacks that depend on this nonce, they must ensure secureHeaders() is configured early in the middleware chain to ensure the Context is populated before rendering starts.
Permissions-Policy directives are processed through getPermissionsPolicyDirectives, which transforms a camel-cased configuration object into the standard kebab-cased string format.
camelToKebab to ensure compatibility with standard browser specifications.boolean: Converted to * or none.Array: If non-empty, values like self and src are kept literal, while other custom strings are quoted and enclosed in parentheses.Permissions-Policy header.Sources: src/middleware/secure-headers/secure-headers.ts:290-318
The middleware follows a rigid order of operations to ensure correct header application:
await next() allows the rest of the application to run.setHeaders(ctx, headersToSet) is called, finally applying the headers to the response object.removePoweredBy is true, the X-Powered-By header is explicitly deleted from ctx.res.headers.Sources: src/middleware/secure-headers/secure-headers.ts:181-228