Security Headers
⭐ Interview Importance: HIGH
⏱️ Revision Time: 13 min
Security Headers are HTTP response headers that instruct the client’s browser to enable strict security protocols, neutralizing entire classes of attacks like XSS, Clickjacking, and Protocol Downgrades.
Overview
While the helmet package applies many security headers automatically, it is crucial for a backend engineer to understand what those headers actually do, and how to configure them manually if you are using an API Gateway, Nginx, or a framework that doesn’t support Helmet.
Key Concepts
- HSTS (HTTP Strict Transport Security): Forces the browser to only communicate with your API over HTTPS. If a user accidentally types
http://api.com, the browser internally redirects them tohttpsbefore ever sending the request over the network. - X-Content-Type-Options: Prevents the browser from “sniffing” the MIME type. If you send a
.txtfile that contains Javascript, the browser will refuse to execute it. - Referrer-Policy: Controls how much information the browser includes in the
Refererheader when navigating away from your site.
Code Examples
1. Manual Implementation (Without Helmet)
If you need to set security headers manually in NestJS, you can do so using a global Express middleware.
// security-headers.middleware.ts
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
@Injectable()
export class SecurityHeadersMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
// 1. Enforce HTTPS for the next 1 year (31536000 seconds)
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
// 2. Prevent Clickjacking (disallow this site from being iframed)
res.setHeader('X-Frame-Options', 'DENY');
// 3. Prevent MIME-sniffing
res.setHeader('X-Content-Type-Options', 'nosniff');
// 4. Don't leak the URL path to external sites
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
// 5. Basic XSS Protection (mostly obsolete due to CSP, but good for older browsers)
res.setHeader('X-XSS-Protection', '1; mode=block');
next();
}
}
Apply it globally:
// app.module.ts
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { SecurityHeadersMiddleware } from './security-headers.middleware';
@Module({})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(SecurityHeadersMiddleware).forRoutes('*');
}
}
2. The Content Security Policy (CSP)
The CSP is the most complex and important header. It is a massive string that dictates exactly what resources the browser is allowed to load.
// A strict CSP for an API that serves a basic Swagger UI
const csp = [
"default-src 'self'",
"script-src 'self' 'unsafe-inline'", // Needed for Swagger UI
"style-src 'self' 'unsafe-inline'", // Needed for Swagger UI
"img-src 'self' data:",
"object-src 'none'", // Block Flash / Java plugins
].join('; ');
res.setHeader('Content-Security-Policy', csp);
Best Practices
- Use Helmet: Unless you have a very specific reason not to, you should always use the
helmetpackage instead of writing manual middleware. Helmet is constantly updated to reflect the latest browser security standards. - HSTS Preloading: If you set the
Strict-Transport-Securityheader, you can submit your domain tohstspreload.org. Your domain will be hardcoded into Chrome, Firefox, and Safari source code, ensuring that no user anywhere in the world will ever be able to access your site via insecure HTTP, even on their very first visit.