Security Headers (Helmet)
The helmet() middleware sets security-related HTTP headers with sensible defaults for API servers. Zero external dependencies.
Usage
import { helmet } from '@forinda/kickjs'
bootstrap({
middlewares: [helmet(), requestId(), express.json()],
})Default Headers
| Header | Default Value | Purpose |
|---|---|---|
X-Content-Type-Options | nosniff | Prevents MIME type sniffing |
X-Frame-Options | DENY | Prevents clickjacking |
X-XSS-Protection | 0 | Disables legacy XSS auditor (causes more harm than good) |
Referrer-Policy | no-referrer | Controls referrer information |
X-DNS-Prefetch-Control | off | Disables DNS prefetching |
Strict-Transport-Security | max-age=31536000; includeSubDomains | Enforces HTTPS |
X-Powered-By | (removed) | Hides server technology |
Options
helmet({
// Disable individual headers
frameguard: false,
hsts: false,
referrerPolicy: false,
// Change values
frameguard: 'SAMEORIGIN',
referrerPolicy: 'strict-origin-when-cross-origin',
// HSTS with preload
hsts: { maxAge: 63072000, includeSubDomains: true, preload: true },
// Content Security Policy
contentSecurityPolicy: {
'default-src': ["'self'"],
'script-src': ["'self'", 'https://cdn.example.com'],
'style-src': ["'self'", "'unsafe-inline'"],
},
})Sub-path Import
import { helmet } from '@forinda/kickjs/middleware/helmet'CORS
The cors() middleware handles Cross-Origin Resource Sharing with correct spec behavior.
Usage
import { cors } from '@forinda/kickjs'
// Allow all origins (default)
bootstrap({
middlewares: [cors(), helmet(), express.json()],
})
// Allowlist specific origins
bootstrap({
middlewares: [
cors({
origin: ['https://app.example.com', /\.example\.com$/],
credentials: true,
}),
helmet(),
express.json(),
],
})Options
interface CorsOptions {
origin?: boolean | string | RegExp | (string | RegExp)[]
methods?: string[] // default: GET, HEAD, PUT, PATCH, POST, DELETE
allowedHeaders?: string[] // default: reflects request headers
exposedHeaders?: string[] // default: none
credentials?: boolean // default: false
maxAge?: number // default: 86400 (24h)
preflight?: boolean // default: true
}Origin Matching
| Value | Behavior |
|---|---|
'*' | Allow all origins (default) |
true | Reflect the request's Origin header |
'https://app.example.com' | Exact match |
/\.example\.com$/ | Regex match |
['https://a.com', /\.b\.com$/] | Array of string/regex |
When reflecting origins (not '*'), the middleware sets Vary: Origin for correct CDN/proxy caching.
Credentials
When credentials: true, the browser sends cookies and authorization headers cross-origin. This requires a specific origin (not '*'):
cors({
origin: ['https://app.example.com'],
credentials: true,
})Preflight
OPTIONS requests are handled with 204 No Content, Access-Control-Allow-Methods, Access-Control-Allow-Headers, and Access-Control-Max-Age.
Sub-path Import
import { cors } from '@forinda/kickjs/middleware/cors'Allowed Hosts
Host is chosen by the client. Code that builds absolute URLs from it — password-reset and verification links, redirects, Location headers — hands an attacker a link to their own domain, and a shared cache can store a response built for the wrong host. Name the hosts your app serves, and every other request answers 400 problem details:
bootstrap({
modules,
security: { allowedHosts: ['example.com', '.example.com'] },
})| Pattern | Matches |
|---|---|
'example.com' | exactly example.com |
'.example.com' | example.com and every subdomain |
'*' | anything — turns the check off |
Ports are ignored, and names compare case-insensitively.
Health probes are exempt. Kubernetes and most platforms probe the instance's IP, so
GET/HEADon/health/liveand/health/readyanswer whatever the host. The check runs before anything else is mounted, including routes adapters register.Behind a proxy that rewrites
Host, read the original fromX-Forwarded-Host— only when your proxy sets it, since clients can send it too. Every value in the header must be allowed, since frameworks disagree about which one to read. Without this option the header is removed from the request, so nothing reads a host the check didn't see:tssecurity: { allowedHosts: { hosts: ['example.com'], trustForwardedHost: true } }As middleware,
allowedHosts()takes the same options plusignorePaths(exempt forGETandHEADonly), for apps that mount their own chain:tsimport { allowedHosts } from '@forinda/kickjs' bootstrap({ middlewares: [allowedHosts(['example.com']) /* , … */] })