VYPR
High severityNVD Advisory· Published Sep 2, 2021· Updated Aug 4, 2024

Crash server with query parameter

CVE-2021-39187

Description

Parse Server is an open source backend that can be deployed to any infrastructure that can run Node.js. Prior to version 4.10.3, Parse Server crashes when if a query request contains an invalid value for the explain option. This is due to a bug in the MongoDB Node.js driver which throws an exception that Parse Server cannot catch. There is a patch for this issue in version 4.10.3. No workarounds aside from upgrading are known to exist.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
parse-servernpm
< 4.10.34.10.3

Affected products

1

Patches

1
308668c89474

Merge pull request from GHSA-xqp8-w826-hh6x

https://github.com/parse-community/parse-serverAntonio Davi Macedo Coelho de CastroSep 2, 2021via ghsa
4 files changed · +80 4
  • CHANGELOG.md+11 2 modified
    @@ -4,7 +4,8 @@ Jump directly to a version:
     
     | 4.x                                  |
     |--------------------------------------|
    -| [**4.10.2 (latest release)**](#4102) |
    +| [**4.10.3 (latest release)**](#4103) |
    +| [4.10.2](#4102)                      |
     | [4.10.1](#4101)                      |
     | [4.10.0](#4100)                      |
     | [4.5.2](#452)                        |
    @@ -93,14 +94,16 @@ Jump directly to a version:
     ___
     
     ## Unreleased (Master Branch)
    -[Full Changelog](https://github.com/parse-community/parse-server/compare/4.10.2...master)
    +[Full Changelog](https://github.com/parse-community/parse-server/compare/4.10.3...master)
    +
     ### Breaking Changes
     - Improved schema caching through database real-time hooks. Reduces DB queries, decreases Parse Query execution time and fixes a potential schema memory leak. If multiple Parse Server instances connect to the same DB (for example behind a load balancer), set the [Parse Server Option](https://parseplatform.org/parse-server/api/master/ParseServerOptions.html) `databaseOptions.enableSchemaHooks: true` to enable this feature and keep the schema in sync across all instances. Failing to do so will cause a schema change to not propagate to other instances and re-syncing will only happen when these instances restart. The options `enableSingleSchemaCache` and `schemaCacheTTL` have been removed. To use this feature with MongoDB, a replica set cluster with [change stream](https://docs.mongodb.com/manual/changeStreams/#availability) support is required. (Diamond Lewis, SebC) [#7214](https://github.com/parse-community/parse-server/issues/7214)
     - Added file upload restriction. File upload is now only allowed for authenticated users by default for improved security. To allow file upload also for Anonymous Users or Public, set the `fileUpload` parameter in the [Parse Server Options](https://parseplatform.org/parse-server/api/master/ParseServerOptions.html) (dblythy, Manuel Trezza) [#7071](https://github.com/parse-community/parse-server/pull/7071)
     - Removed [parse-server-simple-mailgun-adapter](https://github.com/parse-community/parse-server-simple-mailgun-adapter) dependency; to continue using the adapter it has to be explicitly installed (Manuel Trezza) [#7321](https://github.com/parse-community/parse-server/pull/7321)
     - Remove support for MongoDB 3.6 which has reached its End-of-Life date and PostgreSQL 10 (Manuel Trezza) [#7315](https://github.com/parse-community/parse-server/pull/7315)
     - Remove support for Node 10 which has reached its End-of-Life date (Manuel Trezza) [#7314](https://github.com/parse-community/parse-server/pull/7314)
     - Remove S3 Files Adapter from Parse Server, instead install separately as `@parse/s3-files-adapter` (Manuel Trezza) [#7324](https://github.com/parse-community/parse-server/pull/7324)
    +
     ### Notable Changes
     - Added Parse Server Security Check to report weak security settings (Manuel Trezza, dblythy) [#7247](https://github.com/parse-community/parse-server/issues/7247)
     - EXPERIMENTAL: Added new page router with placeholder rendering and localization of custom and feature pages such as password reset and email verification (Manuel Trezza) [#7128](https://github.com/parse-community/parse-server/pull/7128)
    @@ -147,6 +150,12 @@ ___
     - Add CI check to add changelog entry (Manuel Trezza) [#7512](https://github.com/parse-community/parse-server/pull/7512)
     - Refactor: uniform issue templates across repos (Manuel Trezza) [#7528](https://github.com/parse-community/parse-server/pull/7528)
     
    +## 4.10.3
    +[Full Changelog](https://github.com/parse-community/parse-server/compare/4.10.2...4.10.3)
    +
    +### Security Fixes
    +- Validate `explain` query parameter to avoid a server crash due to MongoDB bug [NODE-3463](https://jira.mongodb.org/browse/NODE-3463) (Kartal Kaan Bozdogan) [GHSA-xqp8-w826-hh6x](https://github.com/parse-community/parse-server/security/advisories/GHSA-xqp8-w826-hh6x)
    +
     ## 4.10.2
     [Full Changelog](https://github.com/parse-community/parse-server/compare/4.10.1...4.10.2)
     
    
  • spec/ParseQuery.spec.js+48 0 modified
    @@ -37,6 +37,54 @@ describe('Parse.Query testing', () => {
         });
       });
     
    +  it_only_db('mongo')('gracefully handles invalid explain values', async () => {
    +    // Note that anything that is not truthy (like 0) does not cause an exception, as they get swallowed up by ClassesRouter::optionsFromBody
    +    const values = [1, 'yolo', { a: 1 }, [1, 2, 3]];
    +    for (const value of values) {
    +      try {
    +        await request({
    +          method: 'GET',
    +          url: `http://localhost:8378/1/classes/_User?explain=${value}`,
    +          json: true,
    +          headers: masterKeyHeaders,
    +        });
    +        fail('request did not throw');
    +      } catch (e) {
    +        // Expect that Parse Server did not crash
    +        expect(e.code).not.toEqual('ECONNRESET');
    +        // Expect that Parse Server validates the explain value and does not crash;
    +        // see https://jira.mongodb.org/browse/NODE-3463
    +        equal(e.data.code, Parse.Error.INVALID_QUERY);
    +        equal(e.data.error, 'Invalid value for explain');
    +      }
    +      // get queries (of the form '/classes/:className/:objectId' cannot have the explain key, see ClassesRouter.js)
    +      // so it is enough that we test find queries
    +    }
    +  });
    +
    +  it_only_db('mongo')('supports valid explain values', async () => {
    +    const values = [
    +      false,
    +      true,
    +      'queryPlanner',
    +      'executionStats',
    +      'allPlansExecution',
    +      // 'queryPlannerExtended' is excluded as it only applies to MongoDB Data Lake which is currently not available in our CI environment
    +    ];
    +    for (const value of values) {
    +      const response = await request({
    +        method: 'GET',
    +        url: `http://localhost:8378/1/classes/_User?explain=${value}`,
    +        json: true,
    +        headers: masterKeyHeaders,
    +      });
    +      expect(response.status).toBe(200);
    +      if (value) {
    +        expect(response.data.results.ok).toBe(1);
    +      }
    +    }
    +  });
    +
       it('searching for null', function (done) {
         const baz = new TestObject({ foo: null });
         const qux = new TestObject({ foo: 'qux' });
    
  • src/Adapters/Storage/Mongo/MongoStorageAdapter.js+19 0 modified
    @@ -108,6 +108,23 @@ const mongoSchemaFromFieldsAndClassNameAndCLP = (
       return mongoObject;
     };
     
    +function validateExplainValue(explain) {
    +  if (explain) {
    +    // The list of allowed explain values is from node-mongodb-native/lib/explain.js
    +    const explainAllowedValues = [
    +      'queryPlanner',
    +      'queryPlannerExtended',
    +      'executionStats',
    +      'allPlansExecution',
    +      false,
    +      true,
    +    ];
    +    if (!explainAllowedValues.includes(explain)) {
    +      throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Invalid value for explain');
    +    }
    +  }
    +}
    +
     export class MongoStorageAdapter implements StorageAdapter {
       // Private
       _uri: string;
    @@ -578,6 +595,7 @@ export class MongoStorageAdapter implements StorageAdapter {
         query: QueryType,
         { skip, limit, sort, keys, readPreference, hint, caseInsensitive, explain }: QueryOptions
       ): Promise<any> {
    +    validateExplainValue(explain);
         schema = convertParseSchemaToMongoSchema(schema);
         const mongoWhere = transformWhere(className, query, schema);
         const mongoSort = _.mapKeys(sort, (value, fieldName) =>
    @@ -756,6 +774,7 @@ export class MongoStorageAdapter implements StorageAdapter {
         hint: ?mixed,
         explain?: boolean
       ) {
    +    validateExplainValue(explain);
         let isPointerField = false;
         pipeline = pipeline.map(stage => {
           if (stage.$group) {
    
  • src/RestQuery.js+2 2 modified
    @@ -657,7 +657,7 @@ RestQuery.prototype.runFind = function (options = {}) {
       return this.config.database
         .find(this.className, this.restWhere, findOptions, this.auth)
         .then(results => {
    -      if (this.className === '_User' && findOptions.explain !== true) {
    +      if (this.className === '_User' && !findOptions.explain) {
             for (var result of results) {
               cleanResultAuthData(result);
             }
    @@ -866,7 +866,7 @@ function includePath(config, auth, response, path, restOptions = {}) {
               return set;
             }
           }
    -      if (i == (keyPath.length - 1)) {
    +      if (i == keyPath.length - 1) {
             set.add(keyPath[i]);
           }
           return set;
    

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

6

News mentions

0

No linked articles in our index yet.