nestjs-security-module
Version:
A plug-and-play NestJS security module with CORS, Helmet, rate limiting, audit logging, CSP, XSS sanitization, and more.
163 lines • 6.87 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
var SecurityModule_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SecurityModule = exports.SECURITY_MODULE_OPTIONS = void 0;
const common_1 = require("@nestjs/common");
const helmet_1 = require("helmet");
const config_1 = require("@nestjs/config");
const audit_log_middleware_1 = require("./middlewares/audit-log.middleware");
const rate_limit_middleware_1 = require("./middlewares/rate-limit.middleware");
exports.SECURITY_MODULE_OPTIONS = 'SECURITY_MODULE_OPTIONS';
let SecurityModule = SecurityModule_1 = class SecurityModule {
options;
static register(securityConfig) {
throw new Error('Method not implemented.');
}
constructor(options) {
this.options = options;
}
static forRoot(options) {
const optsProvider = {
provide: exports.SECURITY_MODULE_OPTIONS,
useValue: options,
};
return {
module: SecurityModule_1,
providers: [optsProvider],
exports: [optsProvider],
};
}
static forRootAsync(asyncOptions) {
const asyncOptsProvider = {
provide: exports.SECURITY_MODULE_OPTIONS,
useFactory: asyncOptions.useFactory,
inject: asyncOptions.inject || [],
};
return {
module: SecurityModule_1,
imports: [...(asyncOptions.imports || []), config_1.ConfigModule],
providers: [asyncOptsProvider],
exports: [asyncOptsProvider],
};
}
configure(consumer) {
const options = this.options;
if (!options) {
throw new Error('[SecurityModule] SecurityModuleOptions not provided. Use forRoot or forRootAsync to configure.');
}
if (options.helmet !== false) {
consumer.apply((0, helmet_1.default)()).forRoutes('*');
}
if (options.cors) {
const corsOpts = typeof options.cors === 'object' ? options.cors : {};
consumer
.apply((_req, res, next) => {
if (corsOpts.origin) {
res.setHeader('Access-Control-Allow-Origin', corsOpts.origin);
}
if (corsOpts.methods) {
res.setHeader('Access-Control-Allow-Methods', corsOpts.methods);
}
next();
})
.forRoutes('*');
}
if (options.rateLimit) {
consumer
.apply((0, rate_limit_middleware_1.createRateLimitMiddleware)(options.rateLimit))
.forRoutes('*');
}
if (options.auditLog) {
consumer.apply((0, audit_log_middleware_1.createAuditLogMiddleware)()).forRoutes('*');
}
if (options.csp) {
const cspConfig = typeof options.csp === 'object'
? options.csp
: {
useDefaults: true,
directives: {
"default-src": ["'self'"],
"script-src": ["'self'"],
"style-src": ["'self'", "'unsafe-inline'"],
"img-src": ["'self'", 'data:'],
},
};
consumer
.apply(helmet_1.default.contentSecurityPolicy(cspConfig))
.forRoutes('*');
}
if (options.xFrameOptions) {
const action = typeof options.xFrameOptions === 'string'
? options.xFrameOptions.toLowerCase()
: 'sameorigin';
consumer
.apply(helmet_1.default.frameguard({ action: action }))
.forRoutes('*');
}
if (options.referrerPolicy) {
const policy = typeof options.referrerPolicy === 'object'
? options.referrerPolicy
: { policy: 'no-referrer' };
consumer.apply(helmet_1.default.referrerPolicy(policy)).forRoutes('*');
}
if (options.hsts) {
const hstsConfig = typeof options.hsts === 'object'
? options.hsts
: { maxAge: 60 * 60 * 24 * 180 };
consumer.apply(helmet_1.default.hsts(hstsConfig)).forRoutes('*');
}
if (options.xContentTypeOptions !== false) {
consumer.apply(helmet_1.default.noSniff()).forRoutes('*');
}
if (options.expectCt) {
const expectCtConfig = typeof options.expectCt === 'object'
? options.expectCt
: { maxAge: 86400, enforce: true };
consumer
.apply((_, res, next) => {
res.setHeader('Expect-CT', `max-age=${expectCtConfig.maxAge}${expectCtConfig.enforce ? ', enforce' : ''}`);
next();
})
.forRoutes('*');
}
if (options.permissionsPolicy) {
const policy = Object.entries(options.permissionsPolicy)
.map(([key, val]) => `${key}=(${val.join(' ')})`)
.join(', ');
consumer
.apply((_, res, next) => {
res.setHeader('Permissions-Policy', policy);
next();
})
.forRoutes('*');
}
if (options.crossOriginEmbedderPolicy !== false) {
const coepConfig = typeof options.crossOriginEmbedderPolicy === 'object'
? options.crossOriginEmbedderPolicy
: {};
consumer
.apply(helmet_1.default.crossOriginEmbedderPolicy(coepConfig))
.forRoutes('*');
}
}
};
exports.SecurityModule = SecurityModule;
exports.SecurityModule = SecurityModule = SecurityModule_1 = __decorate([
(0, common_1.Global)(),
(0, common_1.Module)({}),
__param(0, (0, common_1.Inject)(exports.SECURITY_MODULE_OPTIONS)),
__metadata("design:paramtypes", [Object])
], SecurityModule);
//# sourceMappingURL=security.module.js.map
;