Importing helmet and never calling app.use(helmet()) means none of its 15 default security headers — X-Content-Type-Options, X-Frame-Options, Strict-Transport-Security, X-XSS-Protection, Referrer-Policy, and others — are actually set on any response. OWASP A05 (Security Misconfiguration) is the exact mapping. Without these headers, browsers don't enforce clickjacking protection, MIME-type sniffing defenses, or HSTS. An attacker who discovers the headers are absent can exploit XSS more easily or frame your app in an iframe for credential harvesting.
High because the absence of security headers removes browser-enforced defenses against XSS, clickjacking, and MIME sniffing on every HTTP response the application returns.
Mount helmet as middleware in your Express or Fastify entry point, before route definitions. The call must be in the application chain reachable from index.ts or server.ts.
// src/server.ts
import express from 'express'
import helmet from 'helmet'
const app = express()
app.use(helmet()) // applies all 15 default headers
app.get('/health', (req, res) => res.json({ ok: true }))
If you need to disable specific directives (e.g., contentSecurityPolicy: false for development), be explicit — don't disable everything. For Next.js, use next.config.js headers() instead; helmet doesn't apply to that framework.
ID: ai-slop-security-theater.unapplied-middleware.helmet-imported-and-applied
Severity: high
What to look for: When helmet is in package.json dependencies, walk source files and count all import helmet or const helmet = require('helmet') — at least 1 import is required for this check to apply. Before evaluating, extract and quote the import statement. For each file that imports helmet, count whether the same file (or a file in the import chain reachable from the app entry point: index.ts, server.ts, app.ts, main.ts) contains a call matching app.use(helmet(, app.use(helmet()), fastify.register(helmet), server.use(helmet. The application call must be present.
Pass criteria: Helmet is imported in at least 1 source file AND a corresponding app.use(helmet( (or framework-specific equivalent like fastify.register(helmet)) call exists somewhere in the application chain reachable from the entry point.
Report even on pass: "Helmet imported in [file] AND applied in [file]."
Fail criteria: Helmet is imported but no .use(helmet( call exists anywhere in source.
Do NOT pass when: Helmet is imported and the .use(helmet({ contentSecurityPolicy: false, hsts: false, crossOriginEmbedderPolicy: false })) configuration disables every protection — that's still "applied" but worth noting in the detail.
Skip (N/A) when: helmet is not in package.json dependencies, OR framework is Next.js / Astro / SvelteKit / Remix (helmet doesn't apply — those frameworks use config-file headers instead).
Cross-reference: For framework-native security header configuration, the Security Headers & Basics audit (security-headers) covers Next.js / Astro / SvelteKit patterns.
Detail on fail: "helmet imported in src/server.ts but no app.use(helmet()) call found anywhere in source. Security headers not actually applied."
Remediation: Importing helmet does nothing on its own — it's middleware that must be wired into the Express app. Add the .use() call:
// Bad: imported but never invoked
import helmet from 'helmet'
const app = express()
app.get('/', handler) // helmet never applied
// Good: applied as middleware
import helmet from 'helmet'
const app = express()
app.use(helmet()) // applies all default headers
app.get('/', handler)