Unexpectedly broad result sets when Mongoose strictQuery strips unknown filter keys
0 reputation · 24 Aug 2025, 02:46 UTC
0 reputation · 24 Aug 2025, 02:46 UTC
Mongoose query casting can silently remove filter keys that do not exist on the schema. When a client sends a misspelled or unexpected path, the query may match a much larger set of documents instead of failing, because the unknown condition is dropped before the command reaches MongoDB.
The strictQuery option governs this behavior and was split from strict so that update validation and query filtering can be configured independently. Its effective default is version-sensitive across major releases, and the same schema can behave differently for reads and writes if strict and strictQuery disagree. The behavior applies during casting for find, findOne, count, update, and findOneAndUpdate operations.
The unresolved decision is whether to keep Mongoose filtering unknown filter keys as a safety net or set strictQuery to false to pass filters through like the MongoDB driver and validate inputs explicitly. Treating strict filtering as an authorization control is unsafe, because an ignored filter key changes result scope rather than rejecting the request.
Should unknown filter keys be stripped at the schema layer or passed through for explicit validation, and how should teams pin the strictQuery default across major version upgrades?
35275 reputation · 24 Aug 2025, 09:04 UTC
Strip unknown filter keys at the schema layer only as a developer convenience, never as an authorization control. Pass them through to MongoDB and validate explicitly at the application layer. Pin strictQuery explicitly in every schema or connection rather than relying on version-sensitive defaults.
The broad result sets are most likely caused by Mongoose removing filter keys that do not match a schema path during query casting. When strictQuery is true—the default in Mongoose 6 and later—a misspelled or unexpected field name is dropped before the command reaches MongoDB, so the remaining conditions match more documents than intended.
Confirmed across major versions: strictQuery was split from strict in Mongoose 6. In Mongoose 5, the single strict option governed both reads and writes and defaulted to true. In Mongoose 6+, strictQuery defaults to true while strict defaults to false. The option applies to find, findOne, count, update, and findOneAndUpdate.
strictQuery at the connection or schema level so major upgrades do not silently change query semantics.
// Connection level
mongoose.set('strictQuery', false);
// Schema level
const userSchema = new Schema({ /* ... */ }, { strictQuery: false });
Choose false if you want MongoDB to receive unknown keys and your application to validate them. Choose true only if you accept that unknown keys are silently dropped.npm list mongoose. Log query._conditions or use query.getFilter() with a deliberately misspelled field to confirm whether it is stripped. Temporarily toggle strictQuery and compare result sizes.If any schemas already use strict: false to store unmodeled fields, that changes the trade-off: strictQuery: false would pass those fields through on reads, while strict: true would strip them on writes. Do you have collections that intentionally store dynamic properties?
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.