From e29578d2ec18a68aeb4717d66dd5eb66bae53de1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 8 Jul 2023 20:10:42 -0400 Subject: [PATCH 1/2] fix: avoid prototype pollution on init --- lib/document.js | 4 ++++ test/document.test.js | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/lib/document.js b/lib/document.js index 81d51a2ce3e..8d35993da8a 100644 --- a/lib/document.js +++ b/lib/document.js @@ -741,6 +741,10 @@ function init(self, obj, doc, opts, prefix) { function _init(index) { i = keys[index]; + // avoid prototype pollution + if (i === '__proto__' || i === 'constructor') { + return; + } path = prefix + i; schemaType = docSchema.path(path); diff --git a/test/document.test.js b/test/document.test.js index 1e6c9ef7afd..5a5945cd57e 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -12212,6 +12212,24 @@ describe('document', function() { const fromDb = await Test.findById(x._id).lean(); assert.equal(fromDb.c.x.y, 1); }); + + it('avoids prototype pollution on init', async function() { + const Example = db.model('Example', new Schema({ hello: String })); + + const example = await new Example({ hello: 'world!' }).save(); + await Example.findByIdAndUpdate(example._id, { + $rename: { + hello: '__proto__.polluted' + } + }); + + // this is what causes the pollution + await Example.find(); + + const test = {}; + assert.strictEqual(test.polluted, undefined); + assert.strictEqual(Object.prototype.polluted, undefined); + }); }); describe('Check if instance function that is supplied in schema option is availabe', function() { From cc722a139bf68fee32a3ac862e959fa23fe09191 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sun, 9 Jul 2023 10:26:33 -0400 Subject: [PATCH 2/2] test: add coverage for constructor properties --- test/document.test.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index 5a5945cd57e..62877edc98d 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -12229,6 +12229,18 @@ describe('document', function() { const test = {}; assert.strictEqual(test.polluted, undefined); assert.strictEqual(Object.prototype.polluted, undefined); + + const example2 = await new Example({ hello: 'world!' }).save(); + await Example.findByIdAndUpdate(example2._id, { + $rename: { + hello: 'constructor.polluted' + } + }); + + await Example.find(); + const test2 = {}; + assert.strictEqual(test2.constructor.polluted, undefined); + assert.strictEqual(Object.polluted, undefined); }); });