From 05ce5771ab2ceafc51d8c7f27fbe6e52fa23e390 Mon Sep 17 00:00:00 2001 From: "Laisson R. Silveira" Date: Tue, 8 Feb 2022 15:18:30 -0300 Subject: [PATCH 01/11] Fix broken link from findandmodify method deprecation --- docs/deprecations.md | 2 +- lib/query.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/deprecations.md b/docs/deprecations.md index f8a3472bc54..b17953659c0 100644 --- a/docs/deprecations.md +++ b/docs/deprecations.md @@ -60,7 +60,7 @@ If you use [`Model.findOneAndUpdate()`](/docs/api.html#model_Model.findOneAndUpd by default you'll see one of the below deprecation warnings. ``` -DeprecationWarning: Mongoose: `findOneAndUpdate()` and `findOneAndDelete()` without the `useFindAndModify` option set to false are deprecated. See: https://mongoosejs.com/docs/deprecations.html#findandmodify +DeprecationWarning: Mongoose: `findOneAndUpdate()` and `findOneAndDelete()` without the `useFindAndModify` option set to false are deprecated. See: https://mongoosejs.com/docs/5.x/docs/deprecations.html#findandmodify DeprecationWarning: collection.findAndModify is deprecated. Use findOneAndUpdate, findOneAndReplace or findOneAndDelete instead. ``` diff --git a/lib/query.js b/lib/query.js index 4eb5b4a4cde..65817f65fc0 100644 --- a/lib/query.js +++ b/lib/query.js @@ -3777,7 +3777,7 @@ const _legacyFindAndModify = util.deprecate(function(filter, update, opts, cb) { collection.collection._findAndModify(filter, sort, update, opts, _cb); }, 'Mongoose: `findOneAndUpdate()` and `findOneAndDelete()` without the ' + '`useFindAndModify` option set to false are deprecated. See: ' + - 'https://mongoosejs.com/docs/deprecations.html#findandmodify'); + 'https://mongoosejs.com/docs/5.x/docs/deprecations.html#findandmodify'); /*! * Override mquery.prototype._mergeUpdate to handle mongoose objects in From 6a197316564742c0422309e1b5fecfa4faec126e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 18 Jul 2022 22:21:57 -0400 Subject: [PATCH 02/11] fix(schema): disallow setting __proto__ when creating schema with dotted properties Fix #12085 --- lib/schema.js | 7 +++++++ test/schema.test.js | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/lib/schema.js b/lib/schema.js index c740902d2fd..895e452a36c 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -478,6 +478,10 @@ Schema.prototype.add = function add(obj, prefix) { const keys = Object.keys(obj); for (const key of keys) { + if (utils.specialProperties.has(key)) { + continue; + } + const fullPath = prefix + key; if (obj[key] == null) { @@ -663,6 +667,9 @@ Schema.prototype.path = function(path, obj) { let fullPath = ''; for (const sub of subpaths) { + if (utils.specialProperties.has(sub)) { + throw new Error('Cannot set special property `' + sub + '` on a schema'); + } fullPath = fullPath += (fullPath.length > 0 ? '.' : '') + sub; if (!branch[sub]) { this.nested[fullPath] = true; diff --git a/test/schema.test.js b/test/schema.test.js index f5adc214066..711054abccd 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -2682,4 +2682,14 @@ describe('schema', function() { assert.equal(TestSchema.path('testprop.$*').instance, 'Number'); assert.equal(TestSchema.path('testprop.$*').options.ref, 'OtherModel'); }); + + it('disallows setting special properties with `add()` or constructor (gh-12085)', async function() { + const maliciousPayload = '{"__proto__.toString": "Number"}'; + + assert.throws(() => { + mongoose.Schema(JSON.parse(maliciousPayload)); + }, /__proto__/); + + assert.ok({}.toString()); + }); }); From 5eb11dd5d434ba24ea10d19e5eb2054a276bb22e Mon Sep 17 00:00:00 2001 From: Shubanker Chourasia Date: Fri, 19 Aug 2022 13:48:46 +0530 Subject: [PATCH 03/11] made function non async --- test/schema.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/schema.test.js b/test/schema.test.js index 711054abccd..d2bff3ce34e 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -2682,8 +2682,8 @@ describe('schema', function() { assert.equal(TestSchema.path('testprop.$*').instance, 'Number'); assert.equal(TestSchema.path('testprop.$*').options.ref, 'OtherModel'); }); - - it('disallows setting special properties with `add()` or constructor (gh-12085)', async function() { + + it('disallows setting special properties with `add()` or constructor (gh-12085)', function() { const maliciousPayload = '{"__proto__.toString": "Number"}'; assert.throws(() => { From 4d813fa01bb9170f4e0a91d0f3f5234bc163d501 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 21 Aug 2022 17:12:24 -0400 Subject: [PATCH 04/11] test: fix @types/node version in tests re: #12297 --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 8434ae258a1..856290dcf29 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "@babel/preset-env": "7.10.4", "@typescript-eslint/eslint-plugin": "4.10.0", "@typescript-eslint/parser": "4.10.0", + "@types/node": "16.x", "acquit": "1.x", "acquit-ignore": "0.1.x", "acquit-require": "0.1.x", From b9e985c629e05a9a73f23ae42027e6c215c6a9d1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 21 Aug 2022 17:16:39 -0400 Subject: [PATCH 05/11] test: more strict @types/node version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 856290dcf29..4a70cd5cb62 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "@babel/preset-env": "7.10.4", "@typescript-eslint/eslint-plugin": "4.10.0", "@typescript-eslint/parser": "4.10.0", - "@types/node": "16.x", + "@types/node": "16.11.23", "acquit": "1.x", "acquit-ignore": "0.1.x", "acquit-require": "0.1.x", From dfc4ad750bf91ae5743ed8dce676bf5a96041a6d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 21 Aug 2022 19:12:33 -0400 Subject: [PATCH 06/11] test: try upgrading npm for node v4 tests re: #12297 --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9c1b78b454e..7a4eb6af80d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,9 +18,9 @@ jobs: with: node-version: ${{ matrix.node }} - - name: Upgrade Node 5 npm + - name: Upgrade Node <= 5 npm run: npm install -g npm@3 - if: ${{ matrix.node == 5 }} + if: ${{ matrix.node <= 5 }} - run: npm install From a1144dc0220929de0e9b7faf93d793c10e77f094 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 21 Aug 2022 19:19:33 -0400 Subject: [PATCH 07/11] test: run node 7 tests with upgraded npm re: #12297 --- .github/workflows/test.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7a4eb6af80d..861870b0dc7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,6 +22,10 @@ jobs: run: npm install -g npm@3 if: ${{ matrix.node <= 5 }} + - name: Upgrade Node 7 npm + run: npm install -g npm@6 + if: ${{ matrix.node == 7 }} + - run: npm install - name: Setup From ca7996b125c1baf24b056c8fef10cfdd24dc1ae9 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 22 Aug 2022 13:28:12 -0400 Subject: [PATCH 08/11] chore: release 5.13.15 --- History.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 6891820d86a..dc466dbb1c0 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +5.13.15 / 2022-08-22 +==================== + * fix: backport fix for CVE-2022-2564 #12281 [shubanker](https://github.com/shubanker) + * docs: fix broken link from findandmodify method deprecation #11366 [laissonsilveira](https://github.com/laissonsilveira) + 5.13.14 / 2021-12-27 ==================== * fix(timestamps): avoid setting createdAt on documents that already exist but dont have createdAt #11024 diff --git a/package.json b/package.json index 4a70cd5cb62..cbb17a6b225 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "5.13.14", + "version": "5.13.15", "author": "Guillermo Rauch ", "keywords": [ "mongodb", From 0096c3d1329842b476d1186139dcf68bd36d5922 Mon Sep 17 00:00:00 2001 From: Richard De Avila Date: Thu, 10 Nov 2022 13:25:52 -0800 Subject: [PATCH 09/11] Safely handling NamespaceNotFound errors when calling diffIndexes on model with no documents --- lib/model.js | 8 ++++++++ test/model.indexes.test.js | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/lib/model.js b/lib/model.js index 412803aca9f..d1aac13b6e9 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1427,6 +1427,14 @@ Model.diffIndexes = function diffIndexes(options, callback) { return this.db.base._promiseOrCallback(callback, cb => { cb = this.$wrapCallback(cb); this.listIndexes((err, indexes) => { + if (err) { + // If the collection does not exist, it does not have indexes; safely proceed + if (err.codeName === 'NamespaceNotFound') { + indexes = []; + } else { + return cb(err, { toDrop, toCreate }); + } + } const schemaIndexes = this.schema.indexes(); // Iterate through the indexes created in mongodb and // compare against the indexes in the schema. diff --git a/test/model.indexes.test.js b/test/model.indexes.test.js index e00e52c08bf..41ba6d97e23 100644 --- a/test/model.indexes.test.js +++ b/test/model.indexes.test.js @@ -70,6 +70,15 @@ describe('model', function() { }); }); + it('should have schema-defined indexes in toCreate when calling diffIndexes on model with no documents (gh-12676)', () => { + const MySchema = new Schema({ + name: { type: String, index: true } + }); + + const MyModel = db.model('my-model', MySchema); // This collection should not exist in DB; no documents + return MyModel.diffIndexes().then((res) => assert.deepEqual(res.toCreate[0], { name: 1 })); + }); + it('of embedded documents', function(done) { const BlogPosts = new Schema({ _id: { type: ObjectId, index: true }, From 1cbe8e8c00183e5185c1ada483cd54d456295beb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 22 Dec 2022 17:33:52 -0500 Subject: [PATCH 10/11] fix(query): fix unexpected validation error when doing findOneAndReplace() with a nullish value --- lib/helpers/query/castUpdate.js | 8 +++++--- test/query.test.js | 12 +++++++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/lib/helpers/query/castUpdate.js b/lib/helpers/query/castUpdate.js index 50d56509610..2e1dde1a6c0 100644 --- a/lib/helpers/query/castUpdate.js +++ b/lib/helpers/query/castUpdate.js @@ -85,9 +85,11 @@ module.exports = function castUpdate(schema, obj, options, context, filter) { val = ret[op]; hasDollarKey = hasDollarKey || op.startsWith('$'); const toUnset = {}; - for (const key of Object.keys(val)) { - if (val[key] === undefined) { - toUnset[key] = 1; + if (val != null) { + for (const key of Object.keys(val)) { + if (val[key] === undefined) { + toUnset[key] = 1; + } } } diff --git a/test/query.test.js b/test/query.test.js index f291c5d226f..a02a37896d0 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -4314,7 +4314,7 @@ describe('Query', function() { assert.strictEqual(found[0].title, 'burrito bowl'); }); - it('update operation should remove fields set to undefined (gh-12794)', async() => { + it('update operation should remove fields set to undefined (gh-12794) (gh-12821)', async function() { const m = new mongoose.Mongoose(); await m.connect(start.uri); @@ -4338,5 +4338,15 @@ describe('Query', function() { ).lean(); assert.ok('title' in updatedDoc === false); + + const replacedDoc = await Test.findOneAndReplace( + { + _id: doc._id + }, + { title: undefined }, + { returnOriginal: false } + ).lean(); + + assert.ok('title' in replacedDoc === false); }); }); From 0c75a1f85c58ae7b42df55101ecbd56df358a9e4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 23 Dec 2022 12:33:48 -0500 Subject: [PATCH 11/11] add version to 5.x docs search build re: #12548 --- docs/search.js | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/docs/search.js b/docs/search.js index d093bc812e2..ca18f2bae13 100644 --- a/docs/search.js +++ b/docs/search.js @@ -6,6 +6,7 @@ const filemap = require('./source'); const fs = require('fs'); const pug = require('pug'); const mongoose = require('../'); +let { version } = require('../package.json'); const markdown = require('marked'); const highlight = require('highlight.js'); @@ -15,12 +16,14 @@ markdown.setOptions({ } }); -mongoose.set('useCreateIndex', true); +// 5.13.5 -> 5.x, 6.8.2 -> 6.x, etc. +version = version.slice(0, version.indexOf('.')) + '.x'; const contentSchema = new mongoose.Schema({ title: { type: String, required: true }, body: { type: String, required: true }, - url: { type: String, required: true } + url: { type: String, required: true }, + version: { type: String, required: true, default: version } }); contentSchema.index({ title: 'text', body: 'text' }); const Content = mongoose.model('Content', contentSchema, 'Content'); @@ -30,7 +33,6 @@ const files = Object.keys(filemap); for (const filename of files) { const file = filemap[filename]; - console.log(file) if (file.api) { // API docs are special, raw content is in the `docs` property for (const _class of file.docs) { @@ -42,6 +44,7 @@ for (const filename of files) { }); const err = content.validateSync(); if (err != null) { + console.log(content); throw err; } contents.push(content); @@ -49,7 +52,7 @@ for (const filename of files) { } } else if (file.markdown) { let text = fs.readFileSync(filename, 'utf8'); - text = markdown(text); + text = markdown.parse(text); const content = new Content({ title: file.title, @@ -114,15 +117,18 @@ for (const filename of files) { run().catch(error => console.error(error.stack)); async function run() { - await mongoose.connect(config.uri, { useNewUrlParser: true, dbName: 'mongoose' }); + await mongoose.connect(config.uri, { dbName: 'mongoose' }); - await Content.deleteMany({}); + await Content.deleteMany({ version }); for (const content of contents) { + if (version !== '6.x') { + content.url = `/docs/${version}/docs${content.url}`; + } await content.save(); } const results = await Content. - find({ $text: { $search: 'validate' } }, { score: { $meta: 'textScore' } }). + find({ $text: { $search: 'validate' }, version }, { score: { $meta: 'textScore' } }). sort({ score: { $meta: 'textScore' } }). limit(10);