When an AI coding assistant is prompted to "add security" or "rate-limit this API" it will reliably install helmet, express-rate-limit, csurf, csrf-csrf, or a CORS package, import the module at the top of a file, and then forget to actually register the middleware with the app. The package shows up in package.json, the import statement satisfies the grep-for-safety review instinct, and the code LOOKS defended — but without an app.use(helmet()), app.use(limiter), fastify.register(cors), or equivalent registration, none of the middleware runs on any request. Every response ships with no security headers, every endpoint accepts unbounded traffic, every state-changing POST is vulnerable to CSRF. OWASP A05 (Security Misconfiguration) is the exact mapping. This pattern is especially insidious because it passes visual code review — a human glance sees "imports helmet, imports rate-limit, looks fine" — and only deep inspection of the app-initialization code reveals that none of the middleware chain fired.
High because every unapplied middleware represents a missing control that the code pretends to have — attackers get XSS-prone responses, unlimited request rates, and unprotected state mutations while reviewers believe the app is hardened.
For every security middleware in package.json, register it in the app's initialization chain before route definitions:
// src/server.ts
import express from 'express';
import helmet from 'helmet';
import rateLimit from 'express-rate-limit';
import { doubleCsrf } from 'csrf-csrf';
const app = express();
app.use(helmet());
app.use(rateLimit({ windowMs: 60_000, max: 100 }));
const { doubleCsrfProtection } = doubleCsrf({ getSecret: () => process.env.CSRF_SECRET! });
app.use(doubleCsrfProtection);
// ... routes below
For Fastify use fastify.register(...); for Hono use app.use('*', ...). If the project is Next.js, helmet does not apply — configure headers in next.config.ts via the headers() export or in middleware.ts. Run security-hardening and api-security for deeper coverage including per-route rate limits, CSRF-token rotation policies, and CORS origin allowlists.
project-snapshot.security.security-middleware-appliedhighpackage.json for: helmet, express-rate-limit, csurf, csrf-csrf, next-csrf, cors (as middleware, not just response headers), express-session, passport, rate-limiter-flexible, @fastify/helmet, @fastify/rate-limit, @fastify/csrf-protection, hono/csrf, hono/secure-headers. For each present, grep for imports. For each imported middleware, confirm registration via .use(...) (Express/Hono/Koa) or .register(...) (Fastify) somewhere reachable from the app entry (src/server.ts, src/index.ts, src/app.ts, src/main.ts, or a router-setup file).// or if (false) / if (NODE_ENV==='never')) does NOT count. Registration that disables the protection — rateLimit({ max: Infinity }), helmet({ contentSecurityPolicy: false, hsts: false, xssFilter: false, noSniff: false }) — does NOT count.package.json deps + each middleware import (file:line) + the entry-point file."helmet: src/server.ts:3 imported, :12 registered via app.use(helmet())"."helmet imported in src/server.ts:2, no app.use(helmet()) call anywhere — responses ship with no headers. express-rate-limit imported in src/routes/auth.ts:4, no .use(limiter)".// src/server.ts
import express from 'express';
import helmet from 'helmet';
import rateLimit from 'express-rate-limit';
const app = express();
app.use(helmet());
app.use(rateLimit({ windowMs: 60_000, max: 100 }));
// ...routes below
For Fastify: fastify.register(...); Hono: app.use('*', ...). Next.js: configure headers in next.config.ts via headers() or middleware.ts. If a middleware is intentionally disabled, delete the import.