fastify-helmet

Adds essential security HTTP headers to Fastify apps via a thin, Fastify-native wrapper around the helmet middleware.

Library
npm
v7.1.0
463stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
72/100Good
Development Activity68
Maintenance64
Community76
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
77/100Good
Architecture78
Code Quality88
Innovation85
Learning Curve55

@fastify/helmet is the official Fastify integration for the helmet security-headers library, adding hooks and decorators so header configuration works the same way as any other Fastify plugin. It ships as a small, fully test-covered wrapper: registering it once applies helmet’s defaults (CSP, HSTS, X-Frame-Options, and more) to every route, while a per-route helmet shorthand option lets individual routes opt out or override the global configuration.

Beyond the standard helmet passthrough, the plugin adds CSP nonce generation for apps that need inline scripts or styles under a strict Content-Security-Policy, exposing per-request nonces through reply.cspNonce and folding them into the CSP directives automatically. An imperative reply.helmet() decorator is also available for handlers that need to apply headers conditionally rather than declaratively.

What You Get

  • Drop-in Fastify plugin adding CSP, HSTS, X-Frame-Options, and other security headers via a thin helmet wrapper
  • Global or per-route enable/disable/override control through the helmet route shorthand option
  • Built-in CSP nonce generation via enableCSPNonces, exposed as reply.cspNonce.script/reply.cspNonce.style
  • Imperative reply.helmet() decorator for applying headers conditionally inside a route handler
  • TypeScript ambient types that extend Fastify’s own route option interfaces for autocomplete

Common Use Cases

  • Adding baseline security headers to a new Fastify API with a single fastify.register(helmet) call
  • Enforcing a strict Content-Security-Policy with per-request nonces for inline scripts/styles
  • Disabling helmet globally but re-enabling a stricter config on specific sensitive routes
  • Migrating an Express app that already used helmet middleware onto Fastify with minimal config changes

Under The Hood

Architecture All logic lives in a single index.js wrapped as a fastify-plugin (pinned to fastify: '5.x'), which idempotently decorates the reply with helmet and cspNonce (checking hasReplyDecorator first so it composes safely alongside other plugins), registers an onRoute hook that lifts a route’s helmet shorthand option into routeOptions.config.helmet, and adds two onRequest hooks — one to attach the reply decorators, one (buildHelmetOnRoutes) to actually apply headers by merging route-level config over the global config and re-injecting CSP nonces into the merged contentSecurityPolicy directives before invoking the connect-style helmet(...) call against request.raw/reply.raw. There is no internal service layering or DI; it is a thin adapter between Fastify’s hook/decorator system and helmet’s middleware shape, so a change to helmet’s call signature would require touching both the decorator and route-application code paths that share the merged-configuration format.

Tech Stack Dependencies are fastify-plugin and helmet at the runtime layer, with fastify itself only as a devDependency for testing against the current major version. Type declarations are hand-authored (types/index.d.ts) and checked with tstyche rather than compiled from TypeScript source, so the package ships plain CommonJS. Testing runs on Node’s built-in node:test runner with c8 enforcing full coverage, linting uses ESLint 9 with the neostandard config, and CI runs through a shared reusable workflow (fastify/workflows/plugins-ci.yml) that adds a license-check step alongside lint and test.

Code Quality Two test files (global.test.js, routes.test.js) total roughly 1,500 lines and are run under c8 --100, meaning the build fails on any coverage gap; they exercise global vs per-route helmet configuration, CSP nonce generation, and explicit error paths (e.g. throwing on an unrecognized route helmet option value). Error handling favors explicit checks over silent coercion, hook names are descriptive (helmetConfigureReply, helmetApplyHeaders), and the ambient TypeScript types are verified by dedicated tstyche type-assertion tests rather than left unchecked. Combined with enforced linting and CI, this is a strong quality bar for a small plugin.

API Design fastify.register(helmet, options) mirrors any other Fastify plugin, and the full native helmet option surface passes straight through, so existing helmet knowledge transfers directly. The plugin’s only new surface area is global/enableCSPNonces plus a per-route { helmet: {...} | false } shorthand that only needs to specify deltas from the global config rather than a full restatement, and an imperative reply.helmet()/reply.cspNonce pair for handler-level use. TypeScript types extend Fastify’s own RouteShorthandOptions/RouteOptions interfaces directly, so the route option gets editor autocomplete without extra generics, and the README documents each mode (global, per-route override, CSP nonce via options, CSP nonce via manual helmet directive functions) with a runnable example.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search