diff --git a/lib/schema.js b/lib/schema.js index 781ccdbbcf8..730bddeac49 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -554,6 +554,10 @@ Schema.prototype.add = function add(obj, prefix) { const keys = Object.keys(obj); const typeKey = this.options.typeKey; for (const key of keys) { + if (utils.specialProperties.has(key)) { + continue; + } + const fullPath = prefix + key; const val = obj[key]; @@ -854,6 +858,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 7bc6299e23e..6ef548b0059 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -2792,4 +2792,14 @@ describe('schema', function() { }); }, /Cannot use schema-level projections.*subdocument_mapping.not_selected/); }); + + 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()); + }); });