helmet
semver
>=7.0.0 <9.0.0postconditions30functions9last verified2026-06-18coverage score100%Postconditions — what we check
- helmet · config-validation-errorerrorWhenconfiguration object is invalidThrows
TypeError for malformed configuration (e.g., invalid CSP directives, misspelled options)Required handlingCaller MUST wrap helmet() calls in try-catch to prevent server crash on invalid configuration. Common causes: missing quotes on CSP keywords, invalid directive names, misspelled HSTS options.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - helmet · csp-keyword-quotingerrorWhenCSP directive contains unquoted special keywordsThrows
TypeError for keywords like 'self', 'none', 'unsafe-inline' without quotesRequired handlingCSP keywords MUST be wrapped in single quotes: "'self'", "'none'", "'unsafe-inline'", "'unsafe-eval'". Example: scriptSrc: ["'self'"] not scriptSrc: ['self']costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - helmet · invalid-csp-directiveerrorWhencontentSecurityPolicy contains invalid directive nameThrows
TypeError or silent failure for invalid directive namesRequired handlingOnly use valid CSP directive names: defaultSrc, scriptSrc, styleSrc, imgSrc, connectSrc, fontSrc, objectSrc, mediaSrc, frameSrc, baseUri, formAction, frameAncestors, etc.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - helmet · hsts-option-misspellingerrorWhenstrictTransportSecurity contains misspelled 'includeSubDomains' optionThrows
TypeError for 'includeSubdomains' (lowercase d), 'include_sub_domains' (snake_case), etc.Required handlingHSTS option MUST be spelled exactly as 'includeSubDomains' (camelCase with capital D). Common typos: includeSubdomains, include_sub_domains, includesubdomainscostmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - helmet · module-import-errorerrorWhenhelmet is imported incorrectly (CommonJS/ESM mismatch)Throws
TypeError: helmet is not a functionRequired handlingUse correct import syntax: ESM: import helmet from 'helmet' CommonJS: const helmet = require('helmet') or require('helmet').default Incorrect: import * as helmet from 'helmet'costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - helmet · helmet-passed-as-middleware-not-factoryerrorWhenhelmet is passed directly to app.use without invoking itThrows
Error: It appears you have done something like `app.use(helmet)`, but it should be `app.use(helmet())`.Required handlingThe helmet() factory MUST be invoked to produce the middleware function. The factory detects when its first argument is an IncomingMessage (i.e., when Express called it as middleware) and throws synchronously on the FIRST request, which crashes the request-handling pipeline. Correct: app.use(helmet()) Wrong: app.use(helmet)costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - helmet · helmet-duplicate-option-pairerrorWhenhelmet options object specifies both a modern and a legacy alias for the same headerThrows
Error: <Header-Name> option was specified twice. Remove the `<legacy-alias>` option to fix this error. Affected pairs: strictTransportSecurity/hsts, xContentTypeOptions/noSniff, xDnsPrefetchControl/dnsPrefetchControl, xDownloadOptions/ieNoOpen, xFrameOptions/frameguard, xPermittedCrossDomainPolicies/permittedCrossDomainPolicies, xPoweredBy/hidePoweredBy, xXssProtection/xssFilter.Required handlingEach helmet option has a modern name (e.g. strictTransportSecurity) and a legacy alias (e.g. hsts). Passing both throws synchronously at helmet() factory invocation time, crashing app startup. Pick exactly one alias per header. The modern names are preferred; legacy aliases are kept for backward compatibility with helmet@4.x and earlier. Wrong: helmet({ strictTransportSecurity: true, hsts: false }) Correct: helmet({ strictTransportSecurity: true })costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - contentSecurityPolicy · csp-invalid-directive-nameerrorWhencontentSecurityPolicy directives contain an invalid directive nameThrows
Error: Content-Security-Policy received an invalid directive nameRequired handlingOnly use valid CSP directive names (camelCase or kebab-case both accepted): default-src (defaultSrc), script-src (scriptSrc), style-src (styleSrc), img-src (imgSrc), connect-src (connectSrc), font-src (fontSrc), object-src (objectSrc), media-src (mediaSrc), frame-src (frameSrc), base-uri (baseUri), form-action (formAction), frame-ancestors (frameAncestors). Invalid directive names throw synchronously before the server starts.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - contentSecurityPolicy · csp-duplicate-directiveerrorWhencontentSecurityPolicy directives contain the same directive name twiceThrows
Error: Content-Security-Policy received a duplicate directiveRequired handlingEach CSP directive name may appear only once in the directives object. If using both camelCase and kebab-case aliases for the same directive, only one will be used — the other is a duplicate. Deduplication must be done by the caller before passing to contentSecurityPolicy().costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - contentSecurityPolicy · csp-missing-default-srcerrorWhencontentSecurityPolicy directives omit default-src entirely when useDefaults is falseThrows
Error: Content-Security-Policy needs a default-src but none was providedRequired handlingWhen useDefaults is false, the directives object MUST include a defaultSrc (or default-src) key. If intentionally omitting it, set it to contentSecurityPolicy.dangerouslyDisableDefaultSrc symbol. Example: { defaultSrc: contentSecurityPolicy.dangerouslyDisableDefaultSrc }costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - contentSecurityPolicy · csp-null-default-srcerrorWhencontentSecurityPolicy sets defaultSrc to nullThrows
Error: Content-Security-Policy needs a default-src but it was set to nullRequired handlingSetting defaultSrc: null is not valid. To disable default-src, use the special dangerouslyDisableDefaultSrc symbol: { defaultSrc: contentSecurityPolicy.dangerouslyDisableDefaultSrc }costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - contentSecurityPolicy · csp-no-directiveserrorWhencontentSecurityPolicy called with empty directives object and useDefaults falseThrows
Error: Content-Security-Policy has no directivesRequired handlingWhen contentSecurityPolicy is called with useDefaults: false and an empty directives object, it throws because a CSP header with no directives is invalid. Either enable useDefaults (the default) or provide at least a defaultSrc directive.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - contentSecurityPolicy · csp-invalid-directive-value-charserrorWhencontentSecurityPolicy directive value contains a semicolon or comma characterThrows
Error: Content-Security-Policy received an invalid directive value for <directive-name>Required handlingCSP directive values MUST NOT contain `;` or `,` because those characters are structural separators in the header. Helmet rejects them to prevent header injection vulnerabilities. Wrong: scriptSrc: ["'self' https://cdn.example.com;"] (trailing semicolon) Wrong: styleSrc: ["https://a.com, https://b.com"] (comma-separated) Correct: scriptSrc: ["'self'", "https://cdn.example.com"] Correct: styleSrc: ["https://a.com", "https://b.com"] Note: this check ALSO runs at request time for function-typed directive values (e.g. `(req, res) => generateNonce()`). A function returning a value with `;` or `,` will throw on every request, breaking response delivery silently from the perspective of the caller (the error goes to Express error middleware).costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - contentSecurityPolicy · csp-unquoted-special-keyworderrorWhencontentSecurityPolicy directive value contains an unquoted CSP special keyword or hash/nonce prefixThrows
Error: Content-Security-Policy received an invalid directive value for <directive-name>. <value> should be quotedRequired handlingCSP special keywords MUST be wrapped in single quotes inside the array string: 'none', 'self', 'strict-dynamic', 'report-sample', 'inline-speculation-rules', 'unsafe-inline', 'unsafe-eval', 'unsafe-hashes', 'wasm-unsafe-eval' Hash/nonce prefixes also need quoting: 'nonce-...', 'sha256-...', 'sha384-...', 'sha512-...' Helmet 8.x throws synchronously when an unquoted form is detected, catching the most common CSP misconfiguration that silently weakens security. Wrong: scriptSrc: ["self", "unsafe-inline"] Correct: scriptSrc: ["'self'", "'unsafe-inline'"] Wrong: scriptSrc: ["nonce-abc123"] Correct: scriptSrc: ["'nonce-abc123'"]costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - contentSecurityPolicy · csp-dangerously-disable-on-non-default-srcerrorWhencontentSecurityPolicy.dangerouslyDisableDefaultSrc symbol passed as the value of a directive other than default-srcThrows
Error: Content-Security-Policy: tried to disable <directive-name> as if it were default-src; simply omit the keyRequired handlingThe dangerouslyDisableDefaultSrc symbol is meant ONLY for the defaultSrc key to opt out of the default-src requirement. Passing it to any other directive (e.g. scriptSrc, styleSrc) is a misuse and throws synchronously. Wrong: { scriptSrc: contentSecurityPolicy.dangerouslyDisableDefaultSrc } Correct: { defaultSrc: contentSecurityPolicy.dangerouslyDisableDefaultSrc } (or simply omit scriptSrc — defaults fill it in if useDefaults is true)costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - contentSecurityPolicy · csp-falsy-directive-valueerrorWhencontentSecurityPolicy directive value is falsy but not null, string, or the dangerouslyDisableDefaultSrc symbol (e.g. undefined, 0, empty string '')Throws
Error: Content-Security-Policy received an invalid directive value for <directive-name>Required handlingEach directive value MUST be one of: - a string (single value) - an iterable of strings/functions (multiple values) - `null` (treats as "explicitly disabled") - the contentSecurityPolicy.dangerouslyDisableDefaultSrc symbol (default-src only) Passing `undefined`, `0`, `''`, `false`, or any other falsy value throws. A common cause is constructing CSP directives from environment variables without checking for absence: Wrong: { scriptSrc: process.env.CSP_SCRIPT_SRC || undefined } Correct: process.env.CSP_SCRIPT_SRC ? { scriptSrc: process.env.CSP_SCRIPT_SRC.split(' ') } : { /* omit scriptSrc; defaults fill in */ }costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - strictTransportSecurity · hsts-invalid-maxageerrorWhenstrictTransportSecurity maxAge is negative, Infinity, NaN, or non-finiteThrows
Error: Strict-Transport-Security: <value> is not a valid value for maxAge. Please choose a positive integer.Required handlingmaxAge MUST be a non-negative finite integer (in seconds). Common mistakes: - Passing Infinity (valid in math, invalid for HSTS) - Passing a negative number - Passing NaN or undefined from an environment variable without parsing Valid minimum: 0 (disables HSTS for the browsing session) Recommended minimum: 31536000 (1 year, required for HSTS preload list)costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - strictTransportSecurity · hsts-maxage-typoerrorWhenstrictTransportSecurity options contain 'maxage' (lowercase a) instead of 'maxAge'Throws
Error: Strict-Transport-Security received an unsupported property, maxage. Did you mean to pass maxAge?Required handlingThe option key is 'maxAge' (camelCase with capital A), not 'maxage'. Helmet detects this common typo and throws a descriptive error. Correct: { maxAge: 31536000 } Wrong: { maxage: 31536000 }costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - strictTransportSecurity · hsts-includesubdomains-typoerrorWhenstrictTransportSecurity options contain 'includeSubdomains' (lowercase d)Throws
Error: Strict-Transport-Security middleware should use includeSubDomains instead of includeSubdomainsRequired handlingThe option key is 'includeSubDomains' (capital D), not 'includeSubdomains'. Helmet detects this common case error and throws a descriptive error. Correct: { includeSubDomains: true } Wrong: { includeSubdomains: true }costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - crossOriginEmbedderPolicy · coep-invalid-policyerrorWhencrossOriginEmbedderPolicy called with an unsupported policy valueThrows
Error: Cross-Origin-Embedder-Policy does not support the <policy> policyRequired handlingThe policy option MUST be one of: "require-corp", "credentialless", "unsafe-none". Any other string throws synchronously. Default (if omitted): "require-corp" Note: Enabling require-corp blocks cross-origin resources that don't include CORP headers, which can break CDN-hosted assets, iframes, and third-party scripts.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - crossOriginEmbedderPolicy · coep-breaks-cross-origin-resourceswarningWhencrossOriginEmbedderPolicy is enabled with require-corp when the app embeds cross-origin resources without CORP headersThrows
No exception — but cross-origin resources (images, scripts, iframes) silently fail to loadRequired handlingEnabling COEP require-corp blocks all cross-origin resources that do not include a Cross-Origin-Resource-Policy response header. This breaks: - CDN-hosted images (e.g., Cloudinary, S3) without explicit CORP headers - Third-party iframes (Google Maps, Stripe Checkout) - External scripts without CORP headers Use "unsafe-none" for apps with cross-origin dependencies, or ensure all external resources include Cross-Origin-Resource-Policy: cross-origin.costmediumin prodsilent failureusers seedegraded performancevisibilityvisible - crossOriginOpenerPolicy · coop-invalid-policyerrorWhencrossOriginOpenerPolicy called with an unsupported policy valueThrows
Error: Cross-Origin-Opener-Policy does not support the <policy> policyRequired handlingThe policy option MUST be one of: "same-origin", "same-origin-allow-popups", "noopener-allow-popups" (added helmet 8.x), or "unsafe-none". Any other string throws synchronously. Default (if omitted): "same-origin" Note: "same-origin" breaks popup-based OAuth flows and payment windows. Use "same-origin-allow-popups" if the app uses window.open() for auth flows. Use "noopener-allow-popups" if the app needs popups without window.opener access.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - crossOriginOpenerPolicy · coop-breaks-popup-authwarningWhencrossOriginOpenerPolicy is 'same-origin' and the app uses popup-based OAuth (e.g., Google Sign-In, GitHub OAuth via window.open)Throws
No exception — but window.opener is null, breaking postMessage-based auth callbacksRequired handlingWhen COOP is "same-origin", popup windows opened from the page lose access to window.opener, breaking OAuth flows that rely on postMessage from the popup back to the opener. Use "same-origin-allow-popups" if the app uses OAuth popups.costmediumin prodsilent failureusers seeauthentication failurevisibilityvisible - crossOriginResourcePolicy · corp-invalid-policyerrorWhencrossOriginResourcePolicy called with an unsupported policy valueThrows
Error: Cross-Origin-Resource-Policy does not support the <policy> policyRequired handlingThe policy option MUST be one of: "same-origin", "same-site", "cross-origin". Any other string throws synchronously. Default (if omitted): "same-origin" Note: "same-origin" prevents cross-origin no-cors requests from loading resources. Use "cross-origin" for APIs or CDN assets that must be accessible cross-origin.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - crossOriginResourcePolicy · corp-blocks-public-apiwarningWhencrossOriginResourcePolicy is 'same-origin' on a public API server that expects cross-origin no-cors requestsThrows
No exception — but cross-origin no-cors fetch requests are blocked by the browserRequired handlinghelmet()'s default CORP "same-origin" blocks cross-origin no-cors requests. Public REST APIs consumed by browsers MUST override to "cross-origin": helmet({ crossOriginResourcePolicy: { policy: 'cross-origin' } }) This is one of the most common helmet misconfiguration issues for public APIs.costmediumin prodsilent failureusers seedegraded performancevisibilityvisible - referrerPolicy · referrer-invalid-policy-tokenerrorWhenreferrerPolicy called with an unrecognized policy stringThrows
Error: Referrer-Policy received an unexpected policy token <token>Required handlingThe policy option MUST be one of (or an array of): "no-referrer", "no-referrer-when-downgrade", "same-origin", "origin", "strict-origin", "origin-when-cross-origin", "strict-origin-when-cross-origin", "unsafe-url", or "" (empty string for no policy). Any unrecognized string throws synchronously.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - referrerPolicy · referrer-empty-policy-arrayerrorWhenreferrerPolicy called with an empty array []Throws
Error: Referrer-Policy received no policy tokensRequired handlingThe policy option MUST NOT be an empty array. Either pass a string, a non-empty array, or omit the option entirely (defaults to "no-referrer"). Incorrect: helmet.referrerPolicy({ policy: [] }) Correct: helmet.referrerPolicy({ policy: "no-referrer" })costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - referrerPolicy · referrer-duplicate-policy-tokenerrorWhenreferrerPolicy called with an array containing duplicate policy tokensThrows
Error: Referrer-Policy received a duplicate policy token <token>Required handlingWhen passing an array of policy tokens for fallback ordering, each token must appear at most once. Remove duplicates before passing to referrerPolicy().costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - xFrameOptions · xfo-invalid-actionerrorWhenxFrameOptions called with an unsupported action valueThrows
Error: X-Frame-Options received an invalid action <action>Required handlingThe action option MUST be one of: "deny", "sameorigin" (case-insensitive). "ALLOW-FROM" is NOT supported in modern helmet (removed in v5+). Any other string throws synchronously. Valid: { action: "deny" } or { action: "sameorigin" } Invalid: { action: "allow-from" } (removed), { action: "allowfrom" }costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - xPermittedCrossDomainPolicies · xpcdp-invalid-policyerrorWhenxPermittedCrossDomainPolicies called with an unsupported permittedPolicies valueThrows
Error: X-Permitted-Cross-Domain-Policies does not support <permittedPolicies>Required handlingThe permittedPolicies option MUST be one of: "none", "master-only", "by-content-type", "all". Any other string throws synchronously. Default (if omitted): "none" "none" is the recommended value for most apps (denies all cross-domain policies).costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
Sources
Every postcondition cites at least one of these. Numbered to match the footnotes above.
- [1]helmetjs.github.iohttps://helmetjs.github.io/
- [2]github.com/helmetjs/helmethttps://github.com/helmetjs/helmet/blob/main/middlewares/content-security-policy/README.md
- [3]github.com/helmetjs/helmethttps://github.com/helmetjs/helmet/issues/415
- [4]github.com/helmetjs/helmethttps://github.com/helmetjs/helmet/blob/main/index.ts
- [5]github.com/helmetjs/helmethttps://github.com/helmetjs/helmet/blob/main/middlewares/content-security-policy/index.ts
- [6]github.com/helmetjs/helmethttps://github.com/helmetjs/helmet/blob/main/middlewares/strict-transport-security/index.ts
- [7]github.com/helmetjs/helmethttps://github.com/helmetjs/helmet/blob/main/middlewares/cross-origin-embedder-policy/index.ts
- [8]developer.mozilla.org/en-US/docshttps://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy
- [9]github.com/helmetjs/helmethttps://github.com/helmetjs/helmet/blob/main/middlewares/cross-origin-opener-policy/index.ts
- [10]developer.mozilla.org/en-US/docshttps://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy
- [11]github.com/helmetjs/helmethttps://github.com/helmetjs/helmet/blob/main/middlewares/cross-origin-resource-policy/index.ts
- [12]developer.mozilla.org/en-US/docshttps://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy
- [13]github.com/helmetjs/helmethttps://github.com/helmetjs/helmet/blob/main/middlewares/referrer-policy/index.ts
- [14]github.com/helmetjs/helmethttps://github.com/helmetjs/helmet/blob/main/middlewares/x-frame-options/index.ts
- [15]github.com/helmetjs/helmethttps://github.com/helmetjs/helmet/blob/main/middlewares/x-permitted-cross-domain-policies/index.ts
Need a different package?
Request a profile