---
title: "Security Headers"
description: "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 ..."
last_updated: "2026-07-02T09:13:47.315528+00:00"
canonical_url: "https://www.doc0.dev/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/middleware-ecosystem/security-headers"
---

<details>
<summary>Relevant source files</summary>

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

- [src/middleware/secure-headers/secure-headers.ts](https://github.com/blade47/hono/blob/main/src/middleware/secure-headers/secure-headers.ts)
- [package.json](https://github.com/blade47/hono/blob/main/package.json)
- [src/middleware/csrf/index.ts](https://github.com/blade47/hono/blob/main/src/middleware/csrf/index.ts)
- [src/middleware/etag/index.ts](https://github.com/blade47/hono/blob/main/src/middleware/etag/index.ts)
- [src/middleware/cache/index.ts](https://github.com/blade47/hono/blob/main/src/middleware/cache/index.ts)
- [src/middleware/method-override/index.ts](https://github.com/blade47/hono/blob/main/src/middleware/method-override/index.ts)
- [src/adapter/aws-lambda/handler.ts](https://github.com/blade47/hono/blob/main/src/adapter/aws-lambda/handler.ts)
- [src/middleware/cors/index.ts](https://github.com/blade47/hono/blob/main/src/middleware/cors/index.ts)
- [src/middleware/compress/index.ts](https://github.com/blade47/hono/blob/main/src/middleware/compress/index.ts)
- [src/middleware/jwt/jwt.ts](https://github.com/blade47/hono/blob/main/src/middleware/jwt/jwt.ts)
- [src/context.ts](https://github.com/blade47/hono/blob/main/src/context.ts)
- [src/middleware/jwk/jwk.ts](https://github.com/blade47/hono/blob/main/src/middleware/jwk/jwk.ts)
- [src/middleware/etag/digest.ts](https://github.com/blade47/hono/blob/main/src/middleware/etag/digest.ts)
- [src/utils/cookie.ts](https://github.com/blade47/hono/blob/main/src/utils/cookie.ts)
- [jsr.json](https://github.com/blade47/hono/blob/main/jsr.json)
- [src/middleware/timing/timing.ts](https://github.com/blade47/hono/blob/main/src/middleware/timing/timing.ts)
- [src/jsx/intrinsic-element/components.ts](https://github.com/blade47/hono/blob/main/src/jsx/intrinsic-element/components.ts)
- [src/helper/proxy/index.ts](https://github.com/blade47/hono/blob/main/src/helper/proxy/index.ts)
- [src/helper/streaming/sse.ts](https://github.com/blade47/hono/blob/main/src/helper/streaming/sse.ts)
- [src/middleware/secure-headers/index.ts](https://github.com/blade47/hono/blob/main/src/middleware/secure-headers/index.ts)
- [src/utils/headers.ts](https://github.com/blade47/hono/blob/main/src/utils/headers.ts)
- [src/middleware/bearer-auth/index.ts](https://github.com/blade47/hono/blob/main/src/middleware/bearer-auth/index.ts)
- [src/utils/crypto.ts](https://github.com/blade47/hono/blob/main/src/utils/crypto.ts)
- [src/middleware/powered-by/index.ts](https://github.com/blade47/hono/blob/main/src/middleware/powered-by/index.ts)
- [src/middleware/secure-headers/permissions-policy.ts](https://github.com/blade47/hono/blob/main/src/middleware/secure-headers/permissions-policy.ts)
- [src/utils/buffer.ts](https://github.com/blade47/hono/blob/main/src/utils/buffer.ts)
- [src/jsx/dom/intrinsic-element/components.ts](https://github.com/blade47/hono/blob/main/src/jsx/dom/intrinsic-element/components.ts)
</details>

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.

## The `secureHeaders` Middleware Surface
The `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.

```typescript
const app = new Hono()
app.use(secureHeaders())
```
Sources: [src/middleware/secure-headers/secure-headers.ts:179-229](https://github.com/blade47/hono/blob/main/src/middleware/secure-headers/secure-headers.ts#L179-L229)

## Header Mapping and Filtering
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](https://github.com/blade47/hono/blob/main/src/middleware/secure-headers/secure-headers.ts#L231-L238)

## Content Security Policy (CSP) Mechanism
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](https://github.com/blade47/hono/blob/main/src/middleware/secure-headers/secure-headers.ts#L240-L288)

## Nonce Management
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.

```typescript
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](https://github.com/blade47/hono/blob/main/src/middleware/secure-headers/secure-headers.ts#L137-L145)

> [!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 Formatting
Permissions-Policy directives are processed through `getPermissionsPolicyDirectives`, which transforms a camel-cased configuration object into the standard kebab-cased string format. 

1. **Directive Mapping**: Keys are processed via `camelToKebab` to ensure compatibility with standard browser specifications.
2. **Value Handling**:
   - `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.
3. **Serialization**: The entire policy is joined by commas to form a valid HTTP `Permissions-Policy` header.

Sources: [src/middleware/secure-headers/secure-headers.ts:290-318](https://github.com/blade47/hono/blob/main/src/middleware/secure-headers/permissions-policy.ts#L290-L318)

## Execution Lifecycle and Header Application
The middleware follows a rigid order of operations to ensure correct header application:
1. **Header Preparation**: All static headers are filtered by options.
2. **Dynamic Directive Resolution**: CSP and other callbacks are reduced/executed.
3. **Middleware Chain**: `await next()` allows the rest of the application to run.
4. **Injection**: `setHeaders(ctx, headersToSet)` is called, finally applying the headers to the response object.
5. **Clean up**: If `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](https://github.com/blade47/hono/blob/main/src/middleware/secure-headers/secure-headers.ts#L181-L228)

## Related

- [Authentication Middleware](https://www.doc0.dev/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/middleware-ecosystem/authentication-middleware)
- [Traffic Control](https://www.doc0.dev/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/middleware-ecosystem/traffic-control)


## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/llms.txt) for all pages in this wiki.
