Critical severityCISA KEVNVD Advisory· Published Dec 24, 2019· Updated Oct 21, 2025
CVE-2019-10758
CVE-2019-10758
Description
mongo-express before 0.54.0 is vulnerable to Remote Code Execution via endpoints that uses the toBSON method. A misuse of the vm dependency to perform exec commands in a non-safe environment.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
mongo-expressnpm | < 0.54.0 | 0.54.0 |
Affected products
1- mongo-express/mongo-expressdescription
Patches
23 files changed · +748 −3
HISTORY.md+23 −0 modified@@ -1,3 +1,26 @@ +# 0.54 - Tue Dec 24, 2019 + +Breaking: +- Change bson parsing to use mongo-query-parser [(#522)](https://github.com/mongo-express/mongo-express/pull/#522) +- Drop support for node 6 + +New: +- Support playing .wav file inline in collection [(#508)](https://github.com/mongo-express/mongo-express/pull/508) +- Add node 12, and 13 to CI [(#517)](https://github.com/mongo-express/mongo-express/pull/517) +- Add yarn.lock [(#515)](https://github.com/mongo-express/mongo-express/pull/515) +- Fix broken save document for UUID (BinData 3 & 4) [(#537)](https://github.com/mongo-express/mongo-express/pull/#537) + +Deps: +- Pin Event stream to 4.0 [(#514)](https://github.com/mongo-express/mongo-express/pull/514) +- Bump bootstrap from 3.3.7 to 3.4.1 [(#523)](https://github.com/mongo-express/mongo-express/pull/#523) +- Bump lodash from 4.17.11 to 4.17.13 [(#532)](https://github.com/mongo-express/mongo-express/pull/#532) +- Bump jquery from 3.3.1 to 3.4.1 [(#530)](https://github.com/mongo-express/mongo-express/pull/#530) +- Bump mixin-deep from 1.3.1 to 1.3.2 [(#526)](https://github.com/mongo-express/mongo-express/pull/#526) +- Bump js-yaml from 3.12.0 to 3.13.1 [(#527)](https://github.com/mongo-express/mongo-express/pull/#527) +- Bump cross-env from 3.2.4 to 6.0.3 [(#519)](https://github.com/mongo-express/mongo-express/pull/#519) +- Bump concurrently from 3.6.1 to 5.0.0 [(#507)](https://github.com/mongo-express/mongo-express/pull/#507) + + # 0.53 - Sat Jul 20, 2019 New: - Add support to read CA certificate from file [(#465)](https://github.com/mongo-express/mongo-express/pull/465)
package.json+1 −1 modified@@ -1,5 +1,5 @@ { - "version": "0.53.0", + "version": "0.54.0", "author": "https://github.com/mongo-express", "name": "mongo-express", "description": "Web-based admin interface for MongoDB",
yarn.lock+724 −2 modified
d8c9bda46a20Change bson parsing to use mongo-query-parser
6 files changed · +123 −477
lib/bson.js+10 −101 modified@@ -1,65 +1,11 @@ 'use strict'; -var mongodb = require('mongodb'); -var vm = require('vm'); -var json = require('./json'); +const parser = require('mongodb-query-parser'); +const ESJON = require('mongodb-extended-json'); +const mongodb = require('mongodb'); -//Adaptors for BSON types - -var DBRef = function (namespace, oid, db) { - //Allow empty/undefined db value - if (db === undefined || db === null) { - db = ''; - } - - var objectId = exports.toObjectId(oid); - if (objectId === false) { - objectId = mongodb.ObjectId(oid); - } - return mongodb.DBRef(namespace, objectId, db); -}; - -var Timestamp = function (high, low) { - //Switch low/high bits to Timestamp constructor - return mongodb.Timestamp(low, high); -}; - -//Create sandbox with BSON data types -exports.getSandbox = function () { - return { - Long: mongodb.Long, - NumberLong: mongodb.Long, - Double: mongodb.Double, - NumberDouble: mongodb.Double, - ObjectId: mongodb.ObjectID, - ObjectID: mongodb.ObjectID, - Timestamp: Timestamp, - DBRef: DBRef, - Dbref: DBRef, - Binary: mongodb.Binary, - BinData: mongodb.Binary, - Code: mongodb.Code, - Symbol: mongodb.Symbol, - MinKey: mongodb.MinKey, - MaxKey: mongodb.MaxKey, - ISODate: Date, - Date: Date, - Buffer: Buffer, - }; -}; - -//JSON.parse doesn't support BSON data types -//Document is evaluated in a vm in order to support BSON data types -//Sandbox contains BSON data type functions from node-mongodb-native exports.toBSON = function (string) { - var sandbox = exports.getSandbox(); - - string = string.replace(/ISODate\(/g, 'new ISODate('); - string = string.replace(/Binary\(("[^"]+"),/g, 'Binary(new Buffer($1, "base64"),'); - - vm.runInNewContext('doc = eval((' + string + '));', sandbox); - - return sandbox.doc; + return parser(string); }; // This function as the name suggests attempts to parse @@ -74,55 +20,18 @@ exports.toSafeBSON = function (string) { } }; -// Converts string to ObjectID. -exports.toObjectId = function (string) { - var sandbox = exports.getSandbox(); - - // Validation - if ( - !string || // No input at all - string === '' || // empty string - string.toUpperCase().indexOf('OBJECTID(') === -1 || // missing the opening 'ObjectID(' - string.indexOf(')') === -1 // missing the closing '(' - ) { - return false; - } - - // Strip quotes - string = string.replace('"', '').replace('"', ''); - - // Convert ObjectId("526ddf5a9f610ffd26000001") to 526ddf5a9f610ffd26000001 - string = string.replace(/ObjectID\(/i, '').replace(')', ''); - - // Make sure it's a 24-character string to prevent errors. - if (string.length === 24) { - return sandbox.ObjectID(string); - } else { - return false; - } -}; - -// Convert 24-digit hex string to ObjectId -exports.hexToObjectId = function (string) { - if (!/^[0-9a-f]{24}$/.test(string)) { - return false; +exports.parseObjectId = function (string) { + if (/^[0-9a-f]{24}$/i.test(string)) { + return mongodb.ObjectId(string); } - var sandbox = exports.getSandbox(); - return sandbox.ObjectID(string); + return exports.toBSON(string); }; //Convert BSON documents to string exports.toString = function (doc) { - //Use custom json stringify function from json.js - return json.stringify(doc, null, ' '); + return parser.toJSString(doc, ' '); }; exports.toJsonString = function (doc) { - let sJson = json.stringify(doc, null); - sJson = sJson.replace(/ObjectID\(([^)]+)\)/g, '{ "$oid": $1 }'); - sJson = sJson.replace(/([-])?Infinity/g, '"$1Infinity"'); - sJson = sJson.replace(/NaN/g, '"NaN"'); - sJson = sJson.replace(/DBRef\(([^)]+)\)/g, '{ "$ref": $1 }'); - sJson = sJson.replace(/ISODate\(([^)]+)\)/g, '$1'); - return sJson; + return ESJON.stringify(doc); };
lib/json.js+0 −271 removed@@ -1,271 +0,0 @@ -'use strict'; - -var mongodb = require('mongodb'); - -//Original code from official JSON.stringify function -//Modified to accept BSON data types - -/*exported f */ -// function f(n) { -// // Format integers to have at least two digits. -// return n < 10 ? '0' + n : n; -// } - -/* -if (typeof Date.prototype.toJSON !== 'function') { - - Date.prototype.toJSON = function (key) { - - return isFinite(this.valueOf()) - ? this.getUTCFullYear() + '-' + - f(this.getUTCMonth() + 1) + '-' + - f(this.getUTCDate()) + 'T' + - f(this.getUTCHours()) + ':' + - f(this.getUTCMinutes()) + ':' + - f(this.getUTCSeconds()) + 'Z' - : null; - }; - - String.prototype.toJSON = - Number.prototype.toJSON = - Boolean.prototype.toJSON = function (key) { - return this.valueOf(); - }; -} -*/ - -/*exported cx */ -// var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; -// eslint-disable-next-line -var escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; -var gap; -var indent; -var meta = { // table of character substitutions - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '"': '\\"', - '\\': '\\\\', -}; -var rep; - -function quote(string) { - - // If the string contains no control characters, no quote characters, and no - // backslash characters, then we can safely slap some quotes around it. - // Otherwise we must also replace the offending characters with safe escape - // sequences. - - escapable.lastIndex = 0; - return escapable.test(string) ? '"' + string.replace(escapable, function (a) { - var c = meta[a]; - return typeof c === 'string' ? - c : - '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); - }) + '"' : '"' + string + '"'; -} - -function str(key, holder) { - - // Produce a string from holder[key]. - - var i; // The loop counter. - var k; // The member key. - var v; // The member value. - var length; - var mind = gap; - var partial; - var value = holder[key]; - - // If the value has a toJSON method, call it to obtain a replacement value. - - //Custom code to handle BSON data types - if (value instanceof mongodb.ObjectID) { - return 'ObjectID("' + value + '")'; - } else if (value instanceof mongodb.Timestamp) { - return 'Timestamp(' + value.high_ + ', ' + value.low_ + ')'; - } else if (value instanceof Date) { - return 'ISODate("' + value.toJSON() + '")'; - } else if (value instanceof mongodb.DBRef) { - if (value.db === '') { - return 'DBRef("' + value.namespace + '", "' + value.oid + '")'; - } else { - return 'DBRef("' + value.namespace + '", "' + value.oid + '", "' + value.db + '")'; - } - } else if (value instanceof mongodb.Code) { - return 'Code("' + value.code + '")'; - } else if (value instanceof mongodb.MinKey) { - return 'MinKey()'; - } else if (value instanceof mongodb.MaxKey) { - return 'MaxKey()'; - } else if (value instanceof mongodb.Symbol) { - return 'Symbol("' + value + '")'; - } else if (value instanceof mongodb.Binary) { - return 'Binary("' + value.toJSON(key) + '", ' + value.sub_type + ')'; - } - - if (value && typeof value === 'object' && - typeof value.toJSON === 'function') { - value = value.toJSON(key); - } - - // If we were called with a replacer function, then call the replacer to - // obtain a replacement value. - - if (typeof rep === 'function') { - value = rep.call(holder, key, value); - } - - // What happens next depends on the value's type. - switch (typeof value) { - case 'string': - return quote(value); - - case 'number': - // Whatever the value number is: - // * finite - // * NaN - // * +Infinity - // * -Infinity - // let's returning it as string - return String(value); - - case 'boolean': - case 'null': - - // If the value is a boolean or null, convert it to a string. Note: - // typeof null does not produce 'null'. The case is included here in - // the remote chance that this gets fixed someday. - - return String(value); - - // If the type is 'object', we might be dealing with an object or an array or - // null. - - case 'object': - - // Due to a specification blunder in ECMAScript, typeof null is 'object', - // so watch out for that case. - - if (!value) { - return 'null'; - } - - // Make an array to hold the partial results of stringifying this object value. - - gap += indent; - partial = []; - - // Is the value an array? - - if (Object.prototype.toString.apply(value) === '[object Array]') { - - // The value is an array. Stringify every element. Use null as a placeholder - // for non-JSON values. - - length = value.length; - for (i = 0; i < length; i += 1) { - partial[i] = str(i, value) || 'null'; - } - - // Join all of the elements together, separated with commas, and wrap them in - // brackets. - - v = partial.length === 0 ? - '[]' : - gap ? - '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : - '[' + partial.join(',') + ']'; - gap = mind; - return v; - } - - // If the replacer is an array, use it to select the members to be stringified. - - if (rep && typeof rep === 'object') { - length = rep.length; - for (i = 0; i < length; i += 1) { - if (typeof rep[i] === 'string') { - k = rep[i]; - v = str(k, value); - if (v) { - partial.push(quote(k) + (gap ? ': ' : ':') + v); - } - } - } - } else { - - // Otherwise, iterate through all of the keys in the object. - - for (k in value) { - if (Object.prototype.hasOwnProperty.call(value, k)) { - v = str(k, value); - if (v) { - partial.push(quote(k) + (gap ? ': ' : ':') + v); - } - } - } - } - - // Join all of the member texts together, separated with commas, - // and wrap them in braces. - - v = partial.length === 0 ? - '{}' : - gap ? - '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : - '{' + partial.join(',') + '}'; - gap = mind; - return v; - - default: - console.log('Unexpected Object Type', typeof value, value); - break; - } -} - -// If the JSON object does not yet have a stringify method, give it one. - -exports.stringify = function (value, replacer, space) { - - // The stringify method takes a value and an optional replacer, and an optional - // space parameter, and returns a JSON text. The replacer can be a function - // that can replace values, or an array of strings that will select the keys. - // A default replacer method can be provided. Use of the space parameter can - // produce text that is more easily readable. - - var i; - gap = ''; - indent = ''; - - // If the space parameter is a number, make an indent string containing that - // many spaces. - - if (typeof space === 'number') { - for (i = 0; i < space; i += 1) { - indent += ' '; - } - - // If the space parameter is a string, it will be used as the indent string. - - } else if (typeof space === 'string') { - indent = space; - } - - // If there is a replacer, it must be a function or an array. - // Otherwise, throw an error. - - rep = replacer; - if (replacer && typeof replacer !== 'function' && - (typeof replacer !== 'object' || - typeof replacer.length !== 'number')) { - throw new Error('JSON.stringify'); - } - - // Make a fake root object containing our value under the key of ''. - // Return the result of stringifying the value. - - return str('', { '': value }); -};
lib/routes/collection.js+1 −21 modified@@ -51,27 +51,7 @@ var routes = function (config) { }, // If type == O, convert value to ObjectID O: function (value) { - // Hex input - var result = bson.hexToObjectId(value); - - if (!result) { - // Basic validation - // Check we have ObjectID() wrapper - if ( - value.toUpperCase().indexOf('OBJECTID(') === -1 || // missing the opening 'ObjectID(' - value.indexOf(')') === -1 // missing the closing '(' - ) { - throw new Error('ObjectID(...) wrapper must be present'); - // req.session.error = 'ObjectID(...) wrapper must be present'; - // return res.redirect('back'); - } - - result = bson.toObjectId(value); - if (!value) { - throw new Error('ObjectID is invalid'); - } - } - return result; + return bson.parseObjectId(value); }, // If type == R, convert to RegExp R: function (value) {
package.json+6 −1 modified@@ -44,7 +44,10 @@ "lodash": "~4.17.4", "method-override": "^2.3.10", "mongodb": "2.2.24", + "mongodb-extended-json": "^1.10", + "mongodb-query-parser": "1.4.3", "morgan": "^1.9.0", + "patch-package": "^6.2.0", "serve-favicon": "^2.5.0", "swig-templates": "2.0.3", "update-notifier": "1.0.2" @@ -73,14 +76,16 @@ "webpack": "^2.4.1" }, "resolutions": { - "**/event-stream": "^4.0.1" + "**/event-stream": "^4.0.1", + "bson": "1.1.3" }, "engines": { "node": ">=6.0.0", "npm": ">=3.0.0" }, "license": "MIT", "scripts": { + "postinstall": "patch-package", "lint": "eslint .", "start": "cross-env NODE_ENV=production node app", "start-dev": "concurrently --kill-others \"nodemon app\" \"npm run build-dev\"",
patches/mongodb-query-parser+1.4.3.patch+19 −0 added@@ -0,0 +1,19 @@ +diff --git a/node_modules/mongodb-query-parser/lib/index.js b/node_modules/mongodb-query-parser/lib/index.js +index 451a0bb..a550779 100644 +--- a/node_modules/mongodb-query-parser/lib/index.js ++++ b/node_modules/mongodb-query-parser/lib/index.js +@@ -41,10 +41,12 @@ const BSON_TO_JS_STRING = { + return `BinData(${subType.toString(16)}, '${v.buffer.toString('base64')}')`; + }, + DBRef: function(v) { +- return `DBRef('${v.namespace}', '${v.oid}')`; ++ // add db as a param ++ return `DBRef('${v.namespace}', '${v.oid}'${typeof v.db === 'string' ? `, '${v.db}'` : ''})`; + }, + Timestamp: function(v) { +- return `Timestamp(${v.low}, ${v.high})`; ++ // low_ and high_ matches bson 1.X, which is used by this package ++ return `Timestamp(${v.low_}, ${v.high_})`; + }, + Long: function(v) { + return `NumberLong(${v.toString()})`;
test/lib/bsonSpec.js+87 −83 modified@@ -1,16 +1,15 @@ 'use strict'; -var expect = require('chai').expect; -var mongodb = require('mongodb'); +const expect = require('chai').expect; +const mongodb = require('mongodb'); -var bson = require('../../lib/bson'); +const bson = require('../../lib/bson'); describe('BSON', function () { describe('toBSON', function () { it('should convert documents with native JS types', function () { - var test = '{test: true, "s": "hello", i: -99.44}'; - var result = bson.toBSON(test); - + const test = '{test: true, "s": "hello", i: -99.44}'; + const result = bson.toBSON(test); expect(result).to.eql({ test: true, s: 'hello', @@ -19,185 +18,174 @@ describe('BSON', function () { }); it('should convert ObjectID to BSON', function () { - var test = '{_id: ObjectID(), id2: ObjectId()}'; - var result = bson.toBSON(test); - - expect(result).to.have.property('_id').to.be.an.instanceof(mongodb.ObjectID); - expect(result).to.have.property('id2').to.be.an.instanceof(mongodb.ObjectID); + const test = '{_id: ObjectID(), id2: ObjectId()}'; + const result = bson.toBSON(test); + expect(result).to.have.property('_id').to.be.an.instanceof(mongodb.ObjectId); + expect(result).to.have.property('id2').to.be.an.instanceof(mongodb.ObjectId); }); it('should convert ISODate to BSON', function () { - var test = '{date: ISODate(), date2: new Date()}'; - var result = bson.toBSON(test); + const test = '{date: ISODate(), date2: new Date()}'; + const result = bson.toBSON(test); expect(result).to.have.property('date').to.be.an.instanceof(Date); expect(result).to.have.property('date2').to.be.an.instanceof(Date); }); it('should convert Timestamp to BSON', function () { - var test = '{ts: Timestamp()}'; - var result = bson.toBSON(test); + const test = '{ts: Timestamp()}'; + const result = bson.toBSON(test); expect(result).to.have.property('ts').to.be.an.instanceof(mongodb.Timestamp); }); it('should convert DBRef to BSON', function () { - // eslint-disable-next-line max-len - var test = '{ref: DBRef("coll", "579e18580bddc20700502419"), ref2: DBRef("coll", "579e18580bddc20700502419", "db"), ref3: Dbref("coll", "579e18580bddc20700502419", "")}'; - var result = bson.toBSON(test); - + const test = `{ + ref: DBRef("coll", "579e18580bddc20700502419"), + ref2: DBRef("coll", "579e18580bddc20700502419", "db"), + ref3: DBRef("coll", "579e18580bddc20700502419", "") + }`; + const result = bson.toBSON(test); expect(result).to.have.property('ref').to.be.an.instanceof(mongodb.DBRef); expect(result).to.have.property('ref').to.have.property('namespace', 'coll'); - expect(result).to.have.property('ref').to.have.property('oid').to.be.an.instanceof(mongodb.ObjectID); - expect(result).to.have.property('ref').to.have.property('oid').eql(mongodb.ObjectID('579e18580bddc20700502419')); - expect(result).to.have.property('ref').to.have.property('db', ''); + expect(result).to.have.property('ref').to.have.property('oid').eql('579e18580bddc20700502419'); expect(result).to.have.property('ref2').to.be.an.instanceof(mongodb.DBRef); expect(result).to.have.property('ref2').to.have.property('db', 'db'); expect(result).to.have.property('ref3').to.be.an.instanceof(mongodb.DBRef); + expect(result).to.have.property('ref3').to.have.property('db', ''); }); it('should convert Symbol to BSON', function () { - var test = '{symbol: Symbol("test")}'; - var result = bson.toBSON(test); + const test = '{symbol: Symbol("test")}'; + const result = bson.toBSON(test); expect(result).to.have.property('symbol').to.be.an.instanceof(mongodb.Symbol); }); it('should convert MinKey to BSON', function () { - var test = '{key: MinKey()}'; - var result = bson.toBSON(test); + const test = '{key: MinKey()}'; + const result = bson.toBSON(test); expect(result).to.have.property('key').to.be.an.instanceof(mongodb.MinKey); }); it('should convert MaxKey to BSON', function () { - var test = '{key: MaxKey()}'; - var result = bson.toBSON(test); + const test = '{key: MaxKey()}'; + const result = bson.toBSON(test); expect(result).to.have.property('key').to.be.an.instanceof(mongodb.MaxKey); }); it('should convert Code to BSON', function () { - var test = '{code: Code(function() { x; }), code2: Code("function() { x; }")}'; - var result = bson.toBSON(test); + const test = '{code: Code(function() { x; }), code2: Code("function() { x; }")}'; + const result = bson.toBSON(test); expect(result).to.have.property('code').to.be.an.instanceof(mongodb.Code); expect(result).to.have.property('code2').to.be.an.instanceof(mongodb.Code); }); + + it('should not be executable', function () { + const test = 'this.constructor.constructor("return console")().log(this.constructor.constructor("return process")().mainModule.require(\'child_process\').execSync(\'id\').toString())'; // eslint-disable-line max-len + expect(() => bson.toBSON(test)).throws(/Cannot read property 'constructor' of undefined/); + }); }); describe('toString', function () { it('should convert simple documents', function () { - var test = { + const test = { bool: true, str: 'string', number: -678.53, - list: [ - 1, - 2, - 3, - ], + list: [1, 2, 3], }; - var result = bson.toString(test); - var test2 = bson.toBSON(result); + const result = bson.toString(test); + const test2 = bson.toBSON(result); expect(test).to.eql(test2); }); it('should convert ObjectID to string', function () { - var test = { - id: mongodb.ObjectID(), - id2: mongodb.ObjectID('4fb1299686a989240b000001'), + const test = { + id: mongodb.ObjectId(), + id2: mongodb.ObjectId('4fb1299686a989240b000001'), }; - var result = bson.toString(test); - var test2 = bson.toBSON(result); + const result = bson.toString(test); + const test2 = bson.toBSON(result); expect(test).to.eql(test2); }); it('should convert ISODate to string', function () { - var test = { + const test = { date: new Date(), }; - var result = bson.toString(test); - var test2 = bson.toBSON(result); + const result = bson.toString(test); + const test2 = bson.toBSON(result); expect(test).to.eql(test2); }); it('should convert Timestamp to string', function () { - var test = { + const test = { ts: mongodb.Timestamp(), ts2: mongodb.Timestamp(100, 100), }; - var result = bson.toString(test); - var test2 = bson.toBSON(result); - - expect(test).to.eql(test2); + const result = bson.toString(test); + const test2 = bson.toBSON(result); + expect(test2).to.eql(test); }); it('should convert DBRef to string', function () { - var test = { - ref: mongodb.DBRef('coll', mongodb.ObjectID('57b80f922128ccef64333288'), ''), - ref2: mongodb.DBRef('coll', mongodb.ObjectID('57b80f922128ccef64333288'), 'db'), + const test = { + ref: mongodb.DBRef('coll', mongodb.ObjectId('57b80f922128ccef64333288'), ''), + ref2: mongodb.DBRef('coll', mongodb.ObjectId('57b80f922128ccef64333288'), 'db'), }; - var result = bson.toString(test); - var test2 = bson.toBSON(result); - - expect(test).to.eql(test2); + const result = bson.toString(test); + const expected = `{\n ref: DBRef('coll', '57b80f922128ccef64333288', ''),\n ref2: DBRef('coll', '57b80f922128ccef64333288', 'db')\n}`; + expect(result).to.eql(expected); }); it('should convert Symbol to string', function () { - var test = { symbol: mongodb.Symbol('test') }; - var result = bson.toString(test); - var test2 = bson.toBSON(result); - - expect(test).to.eql(test2); + const test = { symbol: mongodb.Symbol('test') }; + const result = bson.toString(test); + expect(result).to.eql(`{\n symbol: {\n _bsontype: 'Symbol',\n value: 'test'\n }\n}`); }); it('should convert MinKey to string', function () { - var test = { key: mongodb.MinKey() }; - var result = bson.toString(test); - var test2 = bson.toBSON(result); + const test = { key: mongodb.MinKey() }; + const result = bson.toString(test); + const test2 = bson.toBSON(result); expect(test).to.eql(test2); }); it('should convert MaxKey to string', function () { - var test = { key: mongodb.MaxKey() }; - var result = bson.toString(test); - var test2 = bson.toBSON(result); + const test = { key: mongodb.MaxKey() }; + const result = bson.toString(test); + const test2 = bson.toBSON(result); expect(test).to.eql(test2); }); it('should convert Code to string', function () { - var test = { - code: mongodb.Code('function() { x; }'), - }; - var result = bson.toString(test); - var test2 = bson.toBSON(result); - - expect(test).to.eql(test2); + const test = { code: mongodb.Code('function() { x; }') }; + const result = bson.toString(test); + expect(result).to.eql(`{\n code: Code('function() { x; }')\n}`); }); }); describe('toJsonString', function () { it('should convert to a valid JSON string', function () { const doc = { dateObject: new Date(Date.UTC(2017, 1, 11)), - objectID: new mongodb.ObjectID('589f79826ea20d18e06b1c36'), + objectID: new mongodb.ObjectId('589f79826ea20d18e06b1c36'), someValue: 'someValue', - nestedObject: { - level1: { - level2: 2, - }, - }, + nestedObject: { level1: { level2: 2 } }, }; const result = bson.toJsonString(doc); - const expected = '{"dateObject":"2017-02-11T00:00:00.000Z","objectID":{ "$oid": "589f79826ea20d18e06b1c36" },"someValue":"someValue","nestedObject":{"level1":{"level2":2}}}'; // eslint-disable-line max-len + const expected = '{"dateObject":{"$date":"2017-02-11T00:00:00.000Z"},"objectID":{"$oid":"589f79826ea20d18e06b1c36"},"someValue":"someValue","nestedObject":{"level1":{"level2":2}}}'; // eslint-disable-line max-len expect(result).to.equal(expected); const parsed = JSON.parse(result); expect(parsed.someValue).to.equal(doc.someValue); @@ -214,4 +202,20 @@ describe('BSON', function () { expect(parsed.someString).to.equal(doc.someString); }); }); + + describe('parseObjectId', function () { + it('should parse a naked id', () => { + const test = '4fb1299686a989240b000001'; + const result = bson.parseObjectId(test); + expect(result).to.be.an.instanceof(mongodb.ObjectId); + expect(result.toHexString()).to.equal(test); + }); + it('should parse when it has an ObjectId wrapper', () => { + const objectIdStr = '4fb1299686a989240b000001'; + const test = `ObjectId("${objectIdStr}")`; + const result = bson.parseObjectId(test); + expect(result).to.be.an.instanceof(mongodb.ObjectId); + expect(result.toHexString()).to.equal(objectIdStr); + }); + }); });
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
9- github.com/advisories/GHSA-h47j-hc6x-h3qqghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2019-10758ghsaADVISORY
- github.com/mongo-express/mongo-express/blob/ea02b364d43f179f191fc91fb9962efdb0843a8d/lib/bson.jsghsaWEB
- github.com/mongo-express/mongo-express/commit/7d365141deadbd38fa961cd835ce68eab5731494ghsaWEB
- github.com/mongo-express/mongo-express/commit/d8c9bda46a204ecba1d35558452685cd0674e6f2ghsaWEB
- github.com/mongo-express/mongo-express/pull/522ghsaWEB
- github.com/mongo-express/mongo-express/security/advisories/GHSA-h47j-hc6x-h3qqghsaWEB
- snyk.io/vuln/SNYK-JS-MONGOEXPRESS-473215ghsax_refsource_MISCWEB
- www.cisa.gov/known-exploited-vulnerabilities-catalogghsaWEB
News mentions
0No linked articles in our index yet.