{"id":"CVE-2026-125119","aliases":["CLSA-2026-1794390937","EUVD-2026-120502","GHSA-gg4r-jv3p-qx3c"],"status":"published","title":"Mongoose: Connection-level sanitizeFilter not applied","description":"Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment. From 6.0.0 until 6.13.12, 7.8.13, 8.24.7, and 9.11.4, Mongoose stores the connection-level sanitizeFilter option in Connection.config, but Query.prototype._castConditions() and query casting check other option locations and do not read that configuration. An application that enables sanitizeFilter through mongoose.connect() or createConnection() and passes an attacker-controlled object into a query filter therefore receives a connection that reports the defense as enabled while query selector objects remain unsanitized. A crafted password value using a query operator can match an account record without the expected literal password, while global configuration through mongoose.set('sanitizeFilter') and per-query Model.find().sanitizeFilter() remain unaffected. This issue is fixed in versions 6.13.12, 7.8.13, 8.24.7, and 9.11.4.","severity":{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-12","score":0.00541,"percentile":0.45982,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-943"],"published":"2026-11-09T22:32:49Z","modified":"2026-11-12T18:04:30Z","fixes":[{"ecosystem":"npm","package":"mongoose","fixed_in":["6.13.12","7.8.13","8.24.7","9.11.4"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"mongoose","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"6.0.0"},{"fixed":"6.13.12"}]}]},{"source":"ghsa","ecosystem":"npm","package":"mongoose","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"7.0.0"},{"fixed":"7.8.13"}]}]},{"source":"ghsa","ecosystem":"npm","package":"mongoose","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"8.0.0"},{"fixed":"8.24.7"}]}]},{"source":"ghsa","ecosystem":"npm","package":"mongoose","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"9.0.0"},{"fixed":"9.11.4"}]}]},{"source":"osv","ecosystem":"TuxCare:npm","package":"mongoose","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"6.12.2-tuxcare.0"},{"fixed":"6.12.2-tuxcare.6"}]}],"versions":["6.12.2","6.12.2-tuxcare.1","6.12.2-tuxcare.2","6.12.2-tuxcare.3","6.12.2-tuxcare.4","6.12.2-tuxcare.5"],"bundled":2},{"source":"osv","ecosystem":"npm","package":"mongoose","ranges":[{"type":"SEMVER","events":[{"introduced":"6.0.0"},{"fixed":"6.13.12"}]}]},{"source":"osv","ecosystem":"npm","package":"mongoose","ranges":[{"type":"SEMVER","events":[{"introduced":"7.0.0"},{"fixed":"7.8.13"}]}]},{"source":"osv","ecosystem":"npm","package":"mongoose","ranges":[{"type":"SEMVER","events":[{"introduced":"8.0.0"},{"fixed":"8.24.7"}]}]},{"source":"osv","ecosystem":"npm","package":"mongoose","ranges":[{"type":"SEMVER","events":[{"introduced":"9.0.0"},{"fixed":"9.11.4"}]}]}],"products":[{"vendor":"automattic","product":"mongoose"}],"references":[{"url":"https://github.com/Automattic/mongoose/security/advisories/GHSA-gg4r-jv3p-qx3c","tags":["x_refsource_CONFIRM","advisory","web"]},{"url":"https://github.com/Automattic/mongoose/commit/4bb659478be2f30655a7bdd78bc251bdf111cd29","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/Automattic/mongoose/commit/4f4f9a79f860786a54133bee2c9af967ec691491","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/Automattic/mongoose/commit/83eda6af1489e9ef60bb8eee8cf9ee005771b9d5","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/Automattic/mongoose/commit/b8970c25998c23fbccd17f76c0398b902ff4911d","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/Automattic/mongoose/releases/tag/6.13.12","tags":["x_refsource_MISC","web"]},{"url":"https://github.com/Automattic/mongoose/releases/tag/7.8.13","tags":["x_refsource_MISC","web"]},{"url":"https://github.com/Automattic/mongoose/releases/tag/8.24.7","tags":["x_refsource_MISC","web"]},{"url":"https://github.com/Automattic/mongoose/releases/tag/9.11.4","tags":["x_refsource_MISC","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-125119","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-gg4r-jv3p-qx3c"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/125xxx/CVE-2026-125119.json","tags":["advisory"]},{"url":"https://github.com/Automattic/mongoose","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-125119","title":"Mongoose: Connection-level sanitizeFilter not applied","description":"Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment. From 6.0.0 until 6.13.12, 7.8.13, 8.24.7, and 9.11.4, Mongoose stores the connection-level sanitizeFilter option in Connection.config, but Query.prototype._castConditions() and query casting check other option locations and do not read that configuration. An application that enables sanitizeFilter through mongoose.connect() or createConnection() and passes an attacker-controlled object into a query filter therefore receives a connection that reports the defense as enabled while query selector objects remain unsanitized. A crafted password value using a query operator can match an account record without the expected literal password, while global configuration through mongoose.set('sanitizeFilter') and per-query Model.find().sanitizeFilter() remain unaffected. This issue is fixed in versions 6.13.12, 7.8.13, 8.24.7, and 9.11.4.","status":"published","published":"2026-11-09T22:32:49.132Z","modified":"2026-11-12T18:04:30.712Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","level":"high","assessor":"cna"}],"cwes":["CWE-943"],"updated_at":"2026-11-09T23:35:21.703923Z"}],"euvd":[{"id":"EUVD-2026-120502","description":"Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment. From 6.0.0 until 6.13.12, 7.8.13, 8.24.7, and 9.11.4, Mongoose stores the connection-level sanitizeFilter option in Connection.config, but Query.prototype._castConditions() and query casting check other option locations and do not read that configuration. An application that enables sanitizeFilter through mongoose.connect() or createConnection() and passes an attacker-controlled object into a query filter therefore receives a connection that reports the defense as enabled while query selector objects remain unsanitized. A crafted password value using a query operator can match an account record without the expected literal password, while global configuration through mongoose.set('sanitizeFilter') and per-query Model.find().sanitizeFilter() remain unaffected. This issue is fixed in versions 6.13.12, 7.8.13, 8.24.7, and 9.11.4.","status":"published","published":"2026-11-09T22:32:49Z","modified":"2026-11-12T18:04:30Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","level":"high"}],"updated_at":"2026-11-12T19:34:41.593638Z"}],"ghsa":[{"id":"GHSA-gg4r-jv3p-qx3c","title":"Mongoose: Connection-level sanitizeFilter not applied","description":"### Summary\n\nsanitizeFilter exists to stop query selector injection: it wraps operator objects such as `{ $ne: null }` in filter values in `$eq`, so they are matched literally. Set on a connection with `mongoose.connect()` or `createConnection(uri, { sanitizeFilter: true })`, the connection reports it as enabled but queries never apply it. An application that relies on the connection-level option and passes an attacker-controlled object into a filter therefore remains open to selector injection, and a password value of `{ $ne: null }` returns the account record without the password.\n\n### Details\n\n`NativeConnection#createClient()` at `lib/drivers/node-mongodb-native/connection.js:270-272` moves `options.sanitizeFilter` into `Connection.config` and deletes the original option. `Query#_castConditions()` at `lib/query.js:2413-2423` checks `Connection.options`, the global `options`, and the per-query options, but never `Connection.config`. The defense therefore does not run even though `Connection#get('sanitizeFilter')` returns true. This storage was introduced in Mongoose 6.0.0 and the same mismatch is present in 9.11.2.\n\n### Proof of concept\n\n```javascript\nimport mongoose from 'mongoose'\n\nconst conn = await mongoose.createConnection('\u003cMONGODB_URI\u003e', { sanitizeFilter: true }).asPromise()\nconst User = conn.model('User', new mongoose.Schema({\n  username: String,\n  password: String,\n  marker: String\n}))\n\nawait User.create({\n  username: 'victim',\n  password: 'correct-password',\n  marker: 'PROTECTED_RECORD'\n})\n\nconst filter = { username: 'victim', password: { $ne: null } }\nconsole.log(conn.get('sanitizeFilter'))\nconsole.log((await User.findOne(filter).lean()).marker)\n```\n\nA control query with a literal wrong password returned no document in the same run, confirming the filter is otherwise enforced.\n\n### Impact\n\nConnection-level `sanitizeFilter` option is not respected. Any user that relies on connection-level config and `sanitizeFilter` to defend against query selector injection is affected. Users that set `sanitizeFilter` globally using `mongoose.set('sanitizeFilter')` or on specific queries using `Model.find().sanitizeFilter()` are not affected.","status":"published","published":"2026-11-10T19:56:12Z","modified":"2026-11-10T19:56:12Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","level":"high"}],"cwes":["CWE-943"],"updated_at":"2026-11-10T19:56:29.95192Z"}],"nvd":[{"id":"CVE-2026-125119","description":"Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment. From 6.0.0 until 6.13.12, 7.8.13, 8.24.7, and 9.11.4, Mongoose stores the connection-level sanitizeFilter option in Connection.config, but Query.prototype._castConditions() and query casting check other option locations and do not read that configuration. An application that enables sanitizeFilter through mongoose.connect() or createConnection() and passes an attacker-controlled object into a query filter therefore receives a connection that reports the defense as enabled while query selector objects remain unsanitized. A crafted password value using a query operator can match an account record without the expected literal password, while global configuration through mongoose.set('sanitizeFilter') and per-query Model.find().sanitizeFilter() remain unaffected. This issue is fixed in versions 6.13.12, 7.8.13, 8.24.7, and 9.11.4.","status":"published","published":"2026-11-09T23:17:22.397Z","modified":"2026-11-12T19:18:09.51Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","level":"high","assessor":"secondary"}],"cwes":["CWE-943"],"updated_at":"2026-11-10T02:16:33.542716Z"}],"osv":[{"id":"CVE-2026-125119","title":"Mongoose: Connection-level sanitizeFilter not applied","description":"Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment. From 6.0.0 until 6.13.12, 7.8.13, 8.24.7, and 9.11.4, Mongoose stores the connection-level sanitizeFilter option in Connection.config, but Query.prototype._castConditions() and query casting check other option locations and do not read that configuration. An application that enables sanitizeFilter through mongoose.connect() or createConnection() and passes an attacker-controlled object into a query filter therefore receives a connection that reports the defense as enabled while query selector objects remain unsanitized. A crafted password value using a query operator can match an account record without the expected literal password, while global configuration through mongoose.set('sanitizeFilter') and per-query Model.find().sanitizeFilter() remain unaffected. This issue is fixed in versions 6.13.12, 7.8.13, 8.24.7, and 9.11.4.","status":"published","published":"2026-11-09T22:32:49.132Z","modified":"2026-11-11T02:48:47.385028726Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","level":"high"}],"cwes":["CWE-943"],"updated_at":"2026-11-11T03:22:00.901153Z"},{"id":"GHSA-gg4r-jv3p-qx3c","title":"Mongoose: Connection-level sanitizeFilter not applied","description":"### Summary\n\nsanitizeFilter exists to stop query selector injection: it wraps operator objects such as `{ $ne: null }` in filter values in `$eq`, so they are matched literally. Set on a connection with `mongoose.connect()` or `createConnection(uri, { sanitizeFilter: true })`, the connection reports it as enabled but queries never apply it. An application that relies on the connection-level option and passes an attacker-controlled object into a filter therefore remains open to selector injection, and a password value of `{ $ne: null }` returns the account record without the password.\n\n### Details\n\n`NativeConnection#createClient()` at `lib/drivers/node-mongodb-native/connection.js:270-272` moves `options.sanitizeFilter` into `Connection.config` and deletes the original option. `Query#_castConditions()` at `lib/query.js:2413-2423` checks `Connection.options`, the global `options`, and the per-query options, but never `Connection.config`. The defense therefore does not run even though `Connection#get('sanitizeFilter')` returns true. This storage was introduced in Mongoose 6.0.0 and the same mismatch is present in 9.11.2.\n\n### Proof of concept\n\n```javascript\nimport mongoose from 'mongoose'\n\nconst conn = await mongoose.createConnection('\u003cMONGODB_URI\u003e', { sanitizeFilter: true }).asPromise()\nconst User = conn.model('User', new mongoose.Schema({\n  username: String,\n  password: String,\n  marker: String\n}))\n\nawait User.create({\n  username: 'victim',\n  password: 'correct-password',\n  marker: 'PROTECTED_RECORD'\n})\n\nconst filter = { username: 'victim', password: { $ne: null } }\nconsole.log(conn.get('sanitizeFilter'))\nconsole.log((await User.findOne(filter).lean()).marker)\n```\n\nA control query with a literal wrong password returned no document in the same run, confirming the filter is otherwise enforced.\n\n### Impact\n\nConnection-level `sanitizeFilter` option is not respected. Any user that relies on connection-level config and `sanitizeFilter` to defend against query selector injection is affected. Users that set `sanitizeFilter` globally using `mongoose.set('sanitizeFilter')` or on specific queries using `Model.find().sanitizeFilter()` are not affected.","status":"published","published":"2026-11-10T19:56:12Z","modified":"2026-11-10T20:00:05.034751092Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","level":"high"}],"cwes":["CWE-943"],"updated_at":"2026-11-10T20:07:06.990596Z"},{"id":"CLSA-2026-1794390937","title":"TuxCare security update for mongoose (2 CVEs)","description":"TuxCare rebuilt mongoose to address 2 CVEs. Fixed in 6.12.2-tuxcare.6.","status":"published","published":"2026-11-11T10:55:38Z","modified":"2026-11-11T13:30:03.775433351Z","updated_at":"2026-11-11T13:39:54.306536Z"}]}}
