npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

nestjs-security-module

v1.1.1

Published

A plug-and-play NestJS security module with CORS, Helmet, rate limiting, audit logging, CSP, XSS sanitization, and more.

Readme

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.