Mongoose applications must assume an explicit security model where input validation, schema strictness, and query sanitization are not fully automatic across all operational paths. Developers must guard against query injection, mass assignment, and authorization bypasses by explicitly configuring strict options, runtime validators, and secure connection parameters. Security-sensitive surfaces include query construction, update pipelines, middleware hooks, and database credential management, all of which must fail closed when encountering unvalidated inputs or connection anomalies.
Essential implementation rules
Enforce Tenant Isolation and Authorization via Document Hooks
Set document-level query filters inside pre('save') middleware hooks by checking this.isNew and assigning tenant ownership properties such as this.$where = { tenantId: this.$locals.tenantId, isDeleted: false } to prevent cross-tenant modifications.
Manage Transaction Sessions and Atomic Array Operations Correctly
Attach transaction sessions explicitly using .session(session) or passing { session } in options, or enable transactionAsyncLocalStorage. When working with partial array projections like $slice, use atomic methods such as .push() or update operators like $push to avoid DivergentArrayError exceptions.
Configure Explicit Connection Credentials and Secure Network Options
Define authentication sources and credentials using environment variables, and set authSource explicitly when user credentials belong to a different database. Enable TLS with certificate validation in production and avoid tlsAllowInvalidCertificates or tlsInsecure.
Specify Target Scope for Deletion Middleware and Lifecycle Hooks
Explicitly configure hook targets with { query: true, document: true } when implementing deletion middleware or cascading security cleanups to ensure boundary checks apply equally to document instances and static model queries.
Configure Client-Side Field-Level Encryption and Schema Options
Declare cryptographic parameters like keyId and algorithms directly on sensitive schema paths and supply autoEncryption options including kmsProviders and keyVaultNamespace when opening database connections.
Restrict Update Pipelines and Neutralize Query Injection
Keep updatePipeline set to false unless input stages are strictly validated, and avoid unvalidated string concatenation or dynamic code execution in $where expressions. Enable sanitizeFilter globally or per query to wrap $-prefixed properties in $eq.
Explicitly Cast Aggregation Inputs and Validate ObjectIds
Always explicitly cast field types using mongoose.Types.ObjectId and sanitize user input before passing it into aggregation pipelines. Use mongoose.isObjectIdOrHexString() for strict ObjectId input validation rather than relying on looser coercion checks.
Configure Schema Strictness and Validation Boundaries
Configure strict: 'throw' and strictRead: 'throw' to reject unknown fields and prevent mass assignment. Define explicit validation boundaries including required fields, string enums, regular expressions, and numeric limits on all schemas.
Constrain Dynamic Model Lookups with Schema Enums
When using dynamic document references via refPath, always constrain the discriminator field in the schema using an enum validator to prevent attackers from querying or populating arbitrary models.
Set Global Execution Timeouts and Disable Command Buffering
Configure a global maxTimeMS timeout on all queries to enforce execution limits, and set bufferCommands: false during connection creation to prevent operations from hanging indefinitely during database outages.
Exclude Sensitive Fields from Default Projections
Set select: false on schema paths storing sensitive data like password hashes, API keys, or session tokens to exclude them by default from query projections.
Enable Update Validators and Maintain Security Control Integrity
Set runValidators: true or enable mongoose.set('runValidators', true) when executing update methods like updateOne() or findOneAndUpdate(), keeping in mind that update validators run only on included paths and supported operators.
Preserve Middleware Execution and State Across Writes
Keep validateBeforeSave enabled, use Model.create() when every inserted document must run save() middleware and validation instead of raw bulk writes, and store custom metadata in doc.$locals for safe state transfer between middleware hooks.
mongoose: All Security Cards
Approximately 4,818 tokens
On this card
Category: access control
Enforce Tenant Isolation and Authorization Filters in Save Hooks
Use when
When saving documents in Mongoose where updating existing records could bypass tenant ownership or authorization boundaries.
Secure rules
Rule 1: Set document-level query filters inside pre-save middleware hooks to enforce tenant isolation and ownership rules.
When updating existing documents where $isNew is false, assign additional filter conditions such as tenantId and isDeleted checks to this.$where inside a pre('save') hook to prevent unauthorized cross-tenant modifications.
Manage Transaction Sessions and Atomic Operations Correctly
Use when
When executing database transactions and handling modifications on partial or subdocument query results.
Secure rules
Rule 1: Attach the session to every operation that must participate in a manually managed transaction
Pass the same session to every operation intended to participate in a manually managed transaction. An operation without the session executes outside the transaction and cannot see that transaction’s uncommitted writes. Use the session option for writes and .session(session) for queries. Manual propagation is unnecessary inside a Connection#transaction() executor when transactionAsyncLocalStorage is enabled because Mongoose attaches the session automatically.
const Customer = mongoose.model( 'Customer', new mongoose.Schema({ name: String }));await Customer.createCollection();const session = await mongoose.startSession();try { await session.withTransaction(async () => { await Customer.create( [{ name: 'Test' }], { session } ); await Customer.findOne({ name: 'Test' }).session(session); });} finally { await session.endSession();}```**Rule 1: Set `authSource` when credentials belong to a different database**MongoDB users are scoped to a database. When the credentials supplied through Mongoose's `user` and `pass` options are stored in a database other than the target application database, set `authSource` to the database that contains those credentials.```javascriptawait mongoose.connect('mongodb://127.0.0.1:27017/application', { user: 'appUser', pass: 'examplePassword', authSource: 'admin'});
Rule 2: Use atomic array methods on partial array projections before saving documents.
When documents are loaded with partial array projections such as $slice, perform modifications using atomic methods like .push() or use direct query methods like updateOne(). Non-atomic mutations on partial arrays followed by doc.save() cause DivergentArrayError exceptions.
Properly Structure API Calls and Argument Signatures
Use when
When invoking Mongoose query and connection APIs that require specific argument formats, method call sequences, or signature structures.
Secure rules
Rule 1: Specify query projections using space-delimited string syntax or projection objects.
When configuring field selections with Query.prototype.select, pass either a single space-separated string or an object representation. Passing multiple separate string arguments violates the expected method signature and results in runtime exceptions.
When a connection instance has been closed via destroy(), do not call openUri() on it. Instantiate a new connection using mongoose.createConnection() or mongoose.connect() to maintain proper connection lifecycles.
Configure database credentials and authentication options for Mongoose connections
Use when
Establishing a database connection in Mongoose that requires user credentials and explicit authentication settings.
Secure rules
Rule 1: Explicitly define authentication sources and credentials when connecting to MongoDB databases.
When configuring authentication credentials for Mongoose connections, explicitly set authSource if user credentials are created on a database other than the target application database. Additionally, when using X.509 authentication, embed the username inside the connection string and supply client certificate configurations via connection options.
Specify Target Scope for Deletion Middleware Boundary Checks
Use when
Implementing deletion middleware or security hooks to ensure boundary checks execute correctly across document and query operations.
Secure rules
Rule 1: Explicitly configure hook targets for both query and document execution contexts when security checks are required for delete operations.
Mongoose distinguishes document middleware from query middleware. Hooks intended for deletion boundary checks or cascading security cleanups must explicitly specify their target scope to avoid bypassed authorization checks during static model query deletions.
Configure Client-Side Field-Level Encryption and Auto-Encryption Options
Use when
Defining schemas with sensitive paths requiring cryptographic protection and initializing database connections with key management configurations.
Secure rules
Rule 1: Declare encryption metadata on schema paths using explicit BSON types and supply autoEncryption options during connection initialization.
Specify cryptographic parameters such as keyId and algorithm definitions directly on sensitive schema paths using supported BSON-compatible types, and configure autoEncryption options including kmsProviders and keyVaultNamespace when opening the database connection.
When performing update queries in Mongoose where untrusted input might otherwise be passed to updatePipeline.
Secure rules
Rule 1: Keep updatePipeline set to false or strictly validate and sanitize all pipeline stages before passing them to update methods.
Avoid enabling updatePipeline: true when executing update queries with untrusted input because Mongoose explicitly disables update pipelines by default and update pipeline operations are not schema-cast.
Use Mongoose model methods instead of Model collection directly
Use when
performing routine database operations and handling untrusted data to ensure schema validation, type casting, and middleware hooks remain enforced
Secure rules
Rule 1: Avoid passing user-defined objects directly as query filters
Construct query filters from explicitly selected input fields instead of passing an entire user-defined object. Enable sanitizeFilter so Mongoose wraps nested objects containing $-prefixed properties in $eq to defend against query-selector injection.
Use standard query operators and structured parameter binding instead of string concatenation in Mongoose queries
Use when
Building Mongoose queries or aggregation pipelines using user-supplied input where unvalidated structures or concatenated strings can lead to injection.
Secure rules
Rule 1: Avoid untrusted string concatenation or dynamic code execution in $where expressions.
Do not pass user-controlled input or concatenated strings directly into $where() expressions because $where executes JavaScript code directly on the MongoDB server. Prefer standard Mongoose query operators like $eq, $gt, or $expr to ensure query parameters remain separated from query syntax.
Rule 2: Enable sanitizeFilter to neutralize NoSQL operator injection globally.
Configure sanitizeFilter globally during application initialization before defining or executing queries. When untrusted input containing object structures with keys starting with $ is passed into query filters, enabling this option ensures they are wrapped safely.
Rule 3: Explicitly cast and sanitize user input in aggregation pipelines.
Always explicitly cast field types, such as using mongoose.Types.ObjectId, and sanitize user input before passing it into pipeline operators since aggregation stages bypass automatic schema casting.
Configure Schema Strictness and Validation Boundaries
Use when
Defining schemas and processing external input payloads to prevent mass assignment and ensure valid data types, enums, ranges, and required properties.
Secure rules
Rule 1: Configure strict writes and strict reads separately
Use strict to control unknown fields supplied through constructors, setters, and updates. strict: true strips them, while strict: "throw" rejects them. Configure strictRead separately for documents hydrated from MongoDB: strictRead: true strips unknown stored fields, and strictRead: "throw" rejects documents containing them. strict defaults to true, but strictRead defaults to false.
When defining schemas that use dynamic document references via refPath to populate documents from untrusted sources.
Secure rules
Rule 1: Whitelisted allowed target models using schema enum validation on the discriminator path.
When using dynamic document references via refPath, always constrain the discriminator field in the schema using an enum validator to prevent attackers from querying or populating arbitrary models within the application.
Strictly Validate and Cast Input Parameters to Prevent Interpretation Bypasses
Use when
Handling untrusted user inputs or query parameters in Mongoose schemas, queries, and validation workflows.
Secure rules
Rule 1: Use isObjectIdOrHexString() for strict ObjectId input validation
Use mongoose.isObjectIdOrHexString() when an input contract should accept only an ObjectId instance or a 24-character hexadecimal string. Do not treat isValidObjectId() as an equivalent strict validator because its documented contract is whether Mongoose can coerce the value to an ObjectId.
function requireObjectId(value) { if (!mongoose.isObjectIdOrHexString(value)) { throw new TypeError( 'Expected an ObjectId or a 24-character hexadecimal string' ); } return value;}const userId = requireObjectId('62261a65d66c6be0a63c051f');
Rule 2: Catch and handle CastError exceptions from incompatible user inputs.
Wrap Mongoose operations in try-catch blocks to handle CastError exceptions raised when casting invalid or malformed inputs, ensuring type discrepancies do not cause unhandled rejections or server crashes.
Restrict MongoDB network access to trusted IP ranges
Use when
Configuring database cluster network connections and firewall rules to restrict network access.
Secure rules
Rule 1: Use TLS and keep certificate validation enabled in production
Enable TLS when connecting with a mongodb:// URI. Keep Mongoose’s default TLS certificate validation enabled in production; do not enable tlsAllowInvalidCertificates or tlsInsecure. When the server certificate requires a specific certificate authority, configure tlsCAFile with the allowed CA certificate.
Configure global query execution timeouts to prevent resource exhaustion
Use when
Developing database queries and operations that require protection against unbounded execution times and denial-of-service conditions.
Secure rules
Rule 1: Set a global maxTimeMS timeout on all Mongoose queries to enforce execution limits.
Configure maxTimeMS globally using mongoose.set('maxTimeMS', ms) to ensure that unoptimized aggregations or complex queries fail fast instead of consuming database CPU, memory, and connection slots indefinitely.
const mongoose = require('mongoose');// Attach maxTimeMS limit of 5 seconds to all queriesmongoose.set('maxTimeMS', 5000);
Category: runtime environment hardening
Disable command buffering to prevent runtime resource exhaustion on connection loss
Use when
Configuring database connections and handling connection failures during application startup and runtime.
Secure rules
Rule 1: Set bufferCommands to false when creating connections to prevent hanging operations during database outages.
Mongoose buffers database commands issued before a connection is established by default. When connection attempts fail or URIs are malformed, unhandled rejections can crash the process, while default command buffering during connection loss can cause requests to hang or fail unexpectedly. Always handle connection promises with catch/try-catch blocks and set bufferCommands to false if immediate failure during connection outages is preferred.
Supply Database Credentials Securely and Exclude Sensitive Fields
Use when
Configuring database connections and defining schema projections in Mongoose.
Secure rules
Rule 1: Supply database credentials using environment variables instead of hardcoding them in source code.
Avoid hardcoding plain-text database credentials or connection strings containing passwords directly in application source code when calling connect or createConnection. Pass credentials dynamically using environment variables or dedicated secret management stores.
import { connect } from 'mongoose';const uri = process.env.MONGODB_URI;if (!uri) { throw new Error('MONGODB_URI environment variable is required');}await connect(uri, { user: process.env.MONGODB_USER, pass: process.env.MONGODB_PASS});
Rule 2: Exclude sensitive fields from default query projections using schema options.
Set select: false on schema paths storing sensitive data like password hashes, API keys, or session tokens to exclude them by default from query projections.
Enforce Schema Immutability and Prevent Bypass of Security Hooks
Use when
When configuring schema options, query update filters, and discriminator models to prevent unauthorized data modifications and control bypasses.
Secure rules
Rule 1: Enforce strict mode to prevent unauthorized mutation of immutable fields.
Keep strict mode enabled or set { strict: 'throw' } in query update options to ensure immutable properties such as immutable: true fields cannot be altered.
Rule 2: Enable schema validation explicitly for update operations
Update validators are disabled by default. Set runValidators: true when using updateOne(), updateMany(), or findOneAndUpdate() to validate the update against the model’s schema. Account for the documented limitations: update validators only validate updated paths and only run for supported update operators.
const toySchema = new mongoose.Schema({ color: String});toySchema.path('color').validate( value => /red|green|blue/i.test(value), 'Invalid color');const Toy = mongoose.model('Toy', toySchema);await Toy.updateOne( {}, { color: 'not a color' }, { runValidators: true });
Enforce Schema Validation and Lifecycle Middleware on Writes
Use when
When saving, updating, or performing batch writes on documents to prevent unvalidated data and ensure security middleware executes.
Secure rules
Rule 1: Keep validateBeforeSave enabled when saving documents derived from untrusted input.
Do not pass validateBeforeSave: false when calling doc.save(). Mongoose validates document properties against schema constraints before saving by default to prevent invalid or unvalidated data from reaching the database.
Rule 2: Enable update validators globally and account for their limited scope
Set mongoose.set('runValidators', true) to enable update validators by default. Update validators run only on paths included in the update and only for supported operators such as $set, $unset, $push, $addToSet, $pull, and $pullAll. They do not validate $inc, and required validators fail only when a path is explicitly $unset. Do not treat this setting as full-document validation.
Rule 3: Use create() when every document must run save() middleware and validation
bulkWrite() does not run per-document save() or update() middleware. When every inserted document must run save() middleware, use Model.create(), which saves each document individually and runs save validation by default. Although bulkWrite() validates insertOne and replaceOne operations unless skipValidation is enabled, that validation does not replace per-document save middleware.
Maintain Session Isolation and State Integrity across Database Operations
Use when
When managing transactions, custom document states, and atomic query execution to ensure consistency and prevent state race conditions.
Secure rules
Rule 1: Use doc.$locals for custom state transfer between middleware hooks.
Store request context, user IDs, or temporary audit metadata in doc.$locals instead of setting custom top-level properties directly on document instances to avoid overwriting internal properties.
Rule 2: Pass session options or enable AsyncLocalStorage for transaction isolation.
Explicitly pass { session } to every query and save call or set mongoose.set('transactionAsyncLocalStorage', true) to guarantee atomic transaction behavior.
Enforce Tenant Isolation and Authorization Filters in Save Hooks
Approximately 192 tokens
Use when
When saving documents in Mongoose where updating existing records could bypass tenant ownership or authorization boundaries.
Secure rules
Rule 1: Set document-level query filters inside pre-save middleware hooks to enforce tenant isolation and ownership rules.
When updating existing documents where $isNew is false, assign additional filter conditions such as tenantId and isDeleted checks to this.$where inside a pre('save') hook to prevent unauthorized cross-tenant modifications.
Manage Transaction Sessions and Atomic Operations Correctly
Approximately 727 tokens
Use when
When executing database transactions and handling modifications on partial or subdocument query results.
Secure rules
Rule 1: Attach the session to every operation that must participate in a manually managed transaction
Pass the same session to every operation intended to participate in a manually managed transaction. An operation without the session executes outside the transaction and cannot see that transaction’s uncommitted writes. Use the session option for writes and .session(session) for queries. Manual propagation is unnecessary inside a Connection#transaction() executor when transactionAsyncLocalStorage is enabled because Mongoose attaches the session automatically.
const Customer = mongoose.model( 'Customer', new mongoose.Schema({ name: String }));await Customer.createCollection();const session = await mongoose.startSession();try { await session.withTransaction(async () => { await Customer.create( [{ name: 'Test' }], { session } ); await Customer.findOne({ name: 'Test' }).session(session); });} finally { await session.endSession();}```**Rule 1: Set `authSource` when credentials belong to a different database**MongoDB users are scoped to a database. When the credentials supplied through Mongoose's `user` and `pass` options are stored in a database other than the target application database, set `authSource` to the database that contains those credentials.```javascriptawait mongoose.connect('mongodb://127.0.0.1:27017/application', { user: 'appUser', pass: 'examplePassword', authSource: 'admin'});
Rule 2: Use atomic array methods on partial array projections before saving documents.
When documents are loaded with partial array projections such as $slice, perform modifications using atomic methods like .push() or use direct query methods like updateOne(). Non-atomic mutations on partial arrays followed by doc.save() cause DivergentArrayError exceptions.
Properly Structure API Calls and Argument Signatures
Use when
When invoking Mongoose query and connection APIs that require specific argument formats, method call sequences, or signature structures.
Secure rules
Rule 1: Specify query projections using space-delimited string syntax or projection objects.
When configuring field selections with Query.prototype.select, pass either a single space-separated string or an object representation. Passing multiple separate string arguments violates the expected method signature and results in runtime exceptions.
When a connection instance has been closed via destroy(), do not call openUri() on it. Instantiate a new connection using mongoose.createConnection() or mongoose.connect() to maintain proper connection lifecycles.
Configure database credentials and authentication options for Mongoose connections
Approximately 194 tokens
Use when
Establishing a database connection in Mongoose that requires user credentials and explicit authentication settings.
Secure rules
Rule 1: Explicitly define authentication sources and credentials when connecting to MongoDB databases.
When configuring authentication credentials for Mongoose connections, explicitly set authSource if user credentials are created on a database other than the target application database. Additionally, when using X.509 authentication, embed the username inside the connection string and supply client certificate configurations via connection options.
Specify Target Scope for Deletion Middleware Boundary Checks
Approximately 204 tokens
Use when
Implementing deletion middleware or security hooks to ensure boundary checks execute correctly across document and query operations.
Secure rules
Rule 1: Explicitly configure hook targets for both query and document execution contexts when security checks are required for delete operations.
Mongoose distinguishes document middleware from query middleware. Hooks intended for deletion boundary checks or cascading security cleanups must explicitly specify their target scope to avoid bypassed authorization checks during static model query deletions.
Configure Client-Side Field-Level Encryption and Auto-Encryption Options
Approximately 280 tokens
Use when
Defining schemas with sensitive paths requiring cryptographic protection and initializing database connections with key management configurations.
Secure rules
Rule 1: Declare encryption metadata on schema paths using explicit BSON types and supply autoEncryption options during connection initialization.
Specify cryptographic parameters such as keyId and algorithm definitions directly on sensitive schema paths using supported BSON-compatible types, and configure autoEncryption options including kmsProviders and keyVaultNamespace when opening the database connection.
When performing update queries in Mongoose where untrusted input might otherwise be passed to updatePipeline.
Secure rules
Rule 1: Keep updatePipeline set to false or strictly validate and sanitize all pipeline stages before passing them to update methods.
Avoid enabling updatePipeline: true when executing update queries with untrusted input because Mongoose explicitly disables update pipelines by default and update pipeline operations are not schema-cast.
Use Mongoose model methods instead of Model collection directly
Approximately 174 tokens
Use when
performing routine database operations and handling untrusted data to ensure schema validation, type casting, and middleware hooks remain enforced
Secure rules
Rule 1: Avoid passing user-defined objects directly as query filters
Construct query filters from explicitly selected input fields instead of passing an entire user-defined object. Enable sanitizeFilter so Mongoose wraps nested objects containing $-prefixed properties in $eq to defend against query-selector injection.
Use standard query operators and structured parameter binding instead of string concatenation in Mongoose queries
Approximately 377 tokens
Use when
Building Mongoose queries or aggregation pipelines using user-supplied input where unvalidated structures or concatenated strings can lead to injection.
Secure rules
Rule 1: Avoid untrusted string concatenation or dynamic code execution in $where expressions.
Do not pass user-controlled input or concatenated strings directly into $where() expressions because $where executes JavaScript code directly on the MongoDB server. Prefer standard Mongoose query operators like $eq, $gt, or $expr to ensure query parameters remain separated from query syntax.
Rule 2: Enable sanitizeFilter to neutralize NoSQL operator injection globally.
Configure sanitizeFilter globally during application initialization before defining or executing queries. When untrusted input containing object structures with keys starting with $ is passed into query filters, enabling this option ensures they are wrapped safely.
Rule 3: Explicitly cast and sanitize user input in aggregation pipelines.
Always explicitly cast field types, such as using mongoose.Types.ObjectId, and sanitize user input before passing it into pipeline operators since aggregation stages bypass automatic schema casting.
Configure Schema Strictness and Validation Boundaries
Approximately 405 tokens
Use when
Defining schemas and processing external input payloads to prevent mass assignment and ensure valid data types, enums, ranges, and required properties.
Secure rules
Rule 1: Configure strict writes and strict reads separately
Use strict to control unknown fields supplied through constructors, setters, and updates. strict: true strips them, while strict: "throw" rejects them. Configure strictRead separately for documents hydrated from MongoDB: strictRead: true strips unknown stored fields, and strictRead: "throw" rejects documents containing them. strict defaults to true, but strictRead defaults to false.
When defining schemas that use dynamic document references via refPath to populate documents from untrusted sources.
Secure rules
Rule 1: Whitelisted allowed target models using schema enum validation on the discriminator path.
When using dynamic document references via refPath, always constrain the discriminator field in the schema using an enum validator to prevent attackers from querying or populating arbitrary models within the application.
Strictly Validate and Cast Input Parameters to Prevent Interpretation Bypasses
Approximately 365 tokens
Use when
Handling untrusted user inputs or query parameters in Mongoose schemas, queries, and validation workflows.
Secure rules
Rule 1: Use isObjectIdOrHexString() for strict ObjectId input validation
Use mongoose.isObjectIdOrHexString() when an input contract should accept only an ObjectId instance or a 24-character hexadecimal string. Do not treat isValidObjectId() as an equivalent strict validator because its documented contract is whether Mongoose can coerce the value to an ObjectId.
function requireObjectId(value) { if (!mongoose.isObjectIdOrHexString(value)) { throw new TypeError( 'Expected an ObjectId or a 24-character hexadecimal string' ); } return value;}const userId = requireObjectId('62261a65d66c6be0a63c051f');
Rule 2: Catch and handle CastError exceptions from incompatible user inputs.
Wrap Mongoose operations in try-catch blocks to handle CastError exceptions raised when casting invalid or malformed inputs, ensuring type discrepancies do not cause unhandled rejections or server crashes.
Restrict MongoDB network access to trusted IP ranges
Approximately 186 tokens
Use when
Configuring database cluster network connections and firewall rules to restrict network access.
Secure rules
Rule 1: Use TLS and keep certificate validation enabled in production
Enable TLS when connecting with a mongodb:// URI. Keep Mongoose’s default TLS certificate validation enabled in production; do not enable tlsAllowInvalidCertificates or tlsInsecure. When the server certificate requires a specific certificate authority, configure tlsCAFile with the allowed CA certificate.
Configure global query execution timeouts to prevent resource exhaustion
Approximately 177 tokens
Use when
Developing database queries and operations that require protection against unbounded execution times and denial-of-service conditions.
Secure rules
Rule 1: Set a global maxTimeMS timeout on all Mongoose queries to enforce execution limits.
Configure maxTimeMS globally using mongoose.set('maxTimeMS', ms) to ensure that unoptimized aggregations or complex queries fail fast instead of consuming database CPU, memory, and connection slots indefinitely.
const mongoose = require('mongoose');// Attach maxTimeMS limit of 5 seconds to all queriesmongoose.set('maxTimeMS', 5000);
Disable command buffering to prevent runtime resource exhaustion on connection loss
Approximately 215 tokens
Use when
Configuring database connections and handling connection failures during application startup and runtime.
Secure rules
Rule 1: Set bufferCommands to false when creating connections to prevent hanging operations during database outages.
Mongoose buffers database commands issued before a connection is established by default. When connection attempts fail or URIs are malformed, unhandled rejections can crash the process, while default command buffering during connection loss can cause requests to hang or fail unexpectedly. Always handle connection promises with catch/try-catch blocks and set bufferCommands to false if immediate failure during connection outages is preferred.
Supply Database Credentials Securely and Exclude Sensitive Fields
Approximately 281 tokens
Use when
Configuring database connections and defining schema projections in Mongoose.
Secure rules
Rule 1: Supply database credentials using environment variables instead of hardcoding them in source code.
Avoid hardcoding plain-text database credentials or connection strings containing passwords directly in application source code when calling connect or createConnection. Pass credentials dynamically using environment variables or dedicated secret management stores.
import { connect } from 'mongoose';const uri = process.env.MONGODB_URI;if (!uri) { throw new Error('MONGODB_URI environment variable is required');}await connect(uri, { user: process.env.MONGODB_USER, pass: process.env.MONGODB_PASS});
Rule 2: Exclude sensitive fields from default query projections using schema options.
Set select: false on schema paths storing sensitive data like password hashes, API keys, or session tokens to exclude them by default from query projections.
Enforce Schema Immutability and Prevent Bypass of Security Hooks
Approximately 1,079 tokens
Use when
When configuring schema options, query update filters, and discriminator models to prevent unauthorized data modifications and control bypasses.
Secure rules
Rule 1: Enforce strict mode to prevent unauthorized mutation of immutable fields.
Keep strict mode enabled or set { strict: 'throw' } in query update options to ensure immutable properties such as immutable: true fields cannot be altered.
Rule 2: Enable schema validation explicitly for update operations
Update validators are disabled by default. Set runValidators: true when using updateOne(), updateMany(), or findOneAndUpdate() to validate the update against the model’s schema. Account for the documented limitations: update validators only validate updated paths and only run for supported update operators.
const toySchema = new mongoose.Schema({ color: String});toySchema.path('color').validate( value => /red|green|blue/i.test(value), 'Invalid color');const Toy = mongoose.model('Toy', toySchema);await Toy.updateOne( {}, { color: 'not a color' }, { runValidators: true });
Enforce Schema Validation and Lifecycle Middleware on Writes
Use when
When saving, updating, or performing batch writes on documents to prevent unvalidated data and ensure security middleware executes.
Secure rules
Rule 1: Keep validateBeforeSave enabled when saving documents derived from untrusted input.
Do not pass validateBeforeSave: false when calling doc.save(). Mongoose validates document properties against schema constraints before saving by default to prevent invalid or unvalidated data from reaching the database.
Rule 2: Enable update validators globally and account for their limited scope
Set mongoose.set('runValidators', true) to enable update validators by default. Update validators run only on paths included in the update and only for supported operators such as $set, $unset, $push, $addToSet, $pull, and $pullAll. They do not validate $inc, and required validators fail only when a path is explicitly $unset. Do not treat this setting as full-document validation.
Rule 3: Use create() when every document must run save() middleware and validation
bulkWrite() does not run per-document save() or update() middleware. When every inserted document must run save() middleware, use Model.create(), which saves each document individually and runs save validation by default. Although bulkWrite() validates insertOne and replaceOne operations unless skipValidation is enabled, that validation does not replace per-document save middleware.
Maintain Session Isolation and State Integrity across Database Operations
Use when
When managing transactions, custom document states, and atomic query execution to ensure consistency and prevent state race conditions.
Secure rules
Rule 1: Use doc.$locals for custom state transfer between middleware hooks.
Store request context, user IDs, or temporary audit metadata in doc.$locals instead of setting custom top-level properties directly on document instances to avoid overwriting internal properties.
Rule 2: Pass session options or enable AsyncLocalStorage for transaction isolation.
Explicitly pass { session } to every query and save call or set mongoose.set('transactionAsyncLocalStorage', true) to guarantee atomic transaction behavior.