Skip to content

A plug-and-play security module for [NestJS](https://nestjs.com/) that enables security best practices in one go.

Notifications You must be signed in to change notification settings

contem/nestjs-security-module

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NestJS Security Module 🔐

npm version Downloads/week

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

  1. Features
  2. Installation
  3. Basic Usage
  4. Async / Env-Based Configuration
  5. Options Reference
  6. CORS Configuration
  7. Example .env
  8. 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-module

Basic 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-Type and content-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=true

Troubleshooting

CORS Issues

If you encounter CORS errors, ensure:

  1. Origin is correctly set: Use specific origin instead of wildcard *
  2. Headers are case-sensitive: Include both Content-Type and content-type
  3. Methods are properly formatted: Use array format for better compatibility
  4. Credentials are enabled: Set credentials: true for authenticated requests

Rate Limiting

  • Rate limiting is per-IP address
  • Default: 10 requests per 60 seconds
  • Configure via RATE_LIMIT_WINDOW and RATE_LIMIT_MAX environment variables

Security Headers

All security headers are automatically applied when enabled:

  • Content-Security-Policy
  • Strict-Transport-Security
  • X-Frame-Options
  • X-Content-Type-Options
  • Referrer-Policy
  • Permissions-Policy
  • Cross-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:3001

Contributing

This module includes enhanced CORS support and improved security features. For issues or contributions, please refer to the project repository.


About

A plug-and-play security module for [NestJS](https://nestjs.com/) that enables security best practices in one go.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published