Package Exports
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (nestjs-security-module) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
NestJS Security Module π
A plug-and-play security module for NestJS, bundling best-practice HTTP headers, CORS, rate-limiting, audit logging, CSP, XSS sanitization and more.
Table of Contents
- Features
- Installation
- Basic Usage
- Async / Env-Based Configuration
- Options Reference
- CORS Configuration
- Example
.env - Troubleshooting
Features
- π Helmet integration for standard security headers
- π Enhanced CORS support with preflight request handling and case-sensitive headers
- π‘οΈ Rate Limiting (per-IP)
- π Audit Logging (to console + file)
- π Content-Security-Policy (CSP)
- π§Ή XSS Sanitization (deep sanitize middleware)
- βοΈ Additional headers: Referrer-Policy, HSTS, Expect-CT, Permissions-Policy, COEP β¦and more
Installation
npm install nestjs-security-module
# or
yarn add nestjs-security-moduleBasic Usage
Import and configure the module in your AppModule:
// app.module.ts
import { Module } from '@nestjs/common';
import { SecurityModule } from 'nestjs-security-module';
@Module({
imports: [
SecurityModule.forRoot({
helmet: true,
cors: {
origin: 'http://localhost:3000',
methods: ['GET', 'HEAD', 'POST'],
allowedHeaders: ['Content-Type', 'content-type', 'Authorization', 'Accept', 'Origin', 'X-Requested-With'],
credentials: true,
},
rateLimit: { windowMs: 60_000, max: 10 },
auditLog: true,
csp: true,
sanitize: true,
referrerPolicy: true,
xFrameOptions: 'SAMEORIGIN',
hsts: true,
expectCt: true,
permissionsPolicy: { geolocation: ['self'] },
crossOriginEmbedderPolicy: true,
}),
// β¦ your other modules
],
})
export class AppModule {}Async / Env-Based Configuration
If you prefer loading options from environment variables via @nestjs/config, use the async API:
// app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { SecurityModule } from 'nestjs-security-module';
@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true }),
SecurityModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (cfg: ConfigService) => ({
helmet: cfg.get<boolean>('SECURITY_HELMET'),
cors: cfg.get<boolean>('SECURITY_CORS')
? {
origin: cfg.get<string>('CORS_ORIGIN'),
methods: cfg.get<string>('CORS_METHODS').split(','),
allowedHeaders: ['Content-Type', 'content-type', 'Authorization', 'Accept', 'Origin', 'X-Requested-With'],
credentials: true,
}
: undefined,
rateLimit: cfg.get<boolean>('SECURITY_RATE_LIMIT')
? {
windowMs: cfg.get<number>('RATE_LIMIT_WINDOW'),
max: cfg.get<number>('RATE_LIMIT_MAX'),
}
: undefined,
auditLog: cfg.get<boolean>('SECURITY_AUDIT_LOG'),
csp: cfg.get<boolean>('SECURITY_CSP') ? { directives: { defaultSrc: ["'self'"] } } : undefined,
sanitize: cfg.get<boolean>('SECURITY_SANITIZE'),
referrerPolicy: cfg.get<boolean>('SECURITY_REFERRER'),
xFrameOptions: cfg.get<boolean>('SECURITY_XFRAME') ? 'SAMEORIGIN' : undefined,
hsts: cfg.get<boolean>('SECURITY_HSTS') ? { maxAge: parseInt(cfg.get<string>('SECURITY_HSTS_MAX_AGE')) } : undefined,
xContentTypeOptions: cfg.get<boolean>('SECURITY_XCONTENT_TYPE_OPTIONS'),
expectCt: cfg.get<boolean>('SECURITY_EXPECT_CT') ? { maxAge: parseInt(cfg.get<string>('SECURITY_EXPECT_CT_MAX_AGE')) } : undefined,
permissionsPolicy: cfg.get<boolean>('SECURITY_PERMISSIONS') ? { geolocation: ['self'] } : undefined,
crossOriginEmbedderPolicy: cfg.get<boolean>('SECURITY_COEP'),
}),
}),
],
})
export class AppModule {}Options Reference
| Option | Type | Description |
|---|---|---|
helmet |
boolean |
Enable Helmet middleware |
cors |
boolean | CORSConfig |
Enable/customize CORS with enhanced support |
rateLimit |
{ windowMs: number; max: number } |
IP-based rate limiting |
auditLog |
boolean |
Log requests to console + file |
csp |
boolean | object |
Enable CSP (Content Security Policy) |
sanitize |
boolean |
Deep sanitize incoming payloads |
referrerPolicy |
boolean | object |
Set Referrer-Policy header |
xFrameOptions |
boolean | 'DENY' | 'SAMEORIGIN' |
Set X-Frame-Options header |
hsts |
boolean | object |
Enforce HTTPS via Strict-Transport-Security |
xContentTypeOptions |
boolean |
Prevent MIME sniffing |
expectCt |
boolean | object |
Set Expect-CT header |
permissionsPolicy |
boolean | Record<string, string[]> |
Set Permissions-Policy header |
crossOriginEmbedderPolicy |
boolean | object |
Enable COEP header |
CORS Configuration
The CORS configuration has been enhanced with the following improvements:
Enhanced CORS Options
interface CORSConfig {
origin: string;
methods: string[] | string;
allowedHeaders?: string[];
credentials?: boolean;
}Key Improvements
- β Preflight Request Handling: Automatic OPTIONS request handling
- β
Case-Sensitive Headers: Support for both
Content-Typeandcontent-type - β Array/String Methods: Support for both array and string method definitions
- β Credentials Support: Proper handling of credentials in CORS requests
- β Max-Age Caching: 24-hour preflight response caching
Example CORS Configuration
cors: {
origin: 'http://localhost:3000',
methods: ['GET', 'HEAD', 'POST'], // Array format
// or methods: 'GET,HEAD,POST', // String format
allowedHeaders: ['Content-Type', 'content-type', 'Authorization', 'Accept', 'Origin', 'X-Requested-With'],
credentials: true,
}Manual OPTIONS Endpoint (Optional)
For additional control, you can add a manual OPTIONS endpoint:
// app.controller.ts
import { Controller, Options, Res } from '@nestjs/common';
import { Response } from 'express';
@Controller()
export class AppController {
@Options()
handleOptions(@Res() res: Response): void {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
res.setHeader('Access-Control-Allow-Methods', 'GET,HEAD,POST,OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type,content-type,Authorization,Accept,Origin,X-Requested-With');
res.setHeader('Access-Control-Allow-Credentials', 'true');
res.setHeader('Access-Control-Max-Age', '86400');
res.status(200).end();
}
}Example .env
SECURITY_HELMET=true
SECURITY_CORS=true
CORS_ORIGIN=http://localhost:3000
CORS_METHODS=GET,HEAD,POST
SECURITY_RATE_LIMIT=true
RATE_LIMIT_WINDOW=60000
RATE_LIMIT_MAX=10
SECURITY_AUDIT_LOG=true
SECURITY_CSP=true
SECURITY_SANITIZE=true
SECURITY_REFERRER=true
SECURITY_XFRAME=true
SECURITY_HSTS=true
SECURITY_HSTS_MAX_AGE=31536000
SECURITY_XCONTENT_TYPE_OPTIONS=true
SECURITY_EXPECT_CT=true
SECURITY_EXPECT_CT_MAX_AGE=30
SECURITY_PERMISSIONS=true
SECURITY_COEP=trueTroubleshooting
CORS Issues
If you encounter CORS errors, ensure:
- Origin is correctly set: Use specific origin instead of wildcard
* - Headers are case-sensitive: Include both
Content-Typeandcontent-type - Methods are properly formatted: Use array format for better compatibility
- Credentials are enabled: Set
credentials: truefor authenticated requests
Rate Limiting
- Rate limiting is per-IP address
- Default: 10 requests per 60 seconds
- Configure via
RATE_LIMIT_WINDOWandRATE_LIMIT_MAXenvironment variables
Security Headers
All security headers are automatically applied when enabled:
Content-Security-PolicyStrict-Transport-SecurityX-Frame-OptionsX-Content-Type-OptionsReferrer-PolicyPermissions-PolicyCross-Origin-Embedder-Policy
Testing
Test your CORS configuration:
# Test preflight request
curl -v -H "Origin: http://localhost:3000" \
-H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Headers: content-type" \
-X OPTIONS http://localhost:3001
# Test regular request
curl -v -H "Origin: http://localhost:3000" \
-H "Content-Type: application/json" \
-X POST http://localhost:3001Contributing
This module includes enhanced CORS support and improved security features. For issues or contributions, please refer to the project repository.