Skip to content

[Vulnerability] parse-community/parse-server: Authorization Bypass / Data Exposure #132

@github-actions

Description

@github-actions

Potential Security Vulnerability Detected

Repository: parse-community/parse-server
Commit: 4d48847
Author: Manuel
Date: 2026-03-10T20:53:25Z

Commit Message

fix: Protected fields bypass via LiveQuery subscription WHERE clause ([GHSA-j7mm-f4rv-6q6q](https://github.com/parse-community/parse-server/security/advisories/GHSA-j7mm-f4rv-6q6q)) (#10175)

Pull Request

PR: #10175 - fix: Protected fields bypass via LiveQuery subscription WHERE clause (GHSA-j7mm-f4rv-6q6q)
Labels: state:released-alpha

Description:

Pull Request

Issue

Protected fields bypass via LiveQuery subscription WHERE clause ([GHSA-j7mm-f4rv-6q6q](GHSA-j7mm-f4rv-6q6q))

Tasks

<!-- Check completed tasks and delete tasks that don't ...

Analysis

Vulnerability Type: Authorization Bypass / Data Exposure
Severity: High

Description

The patch fixes a vulnerability in the LiveQuery subscription's WHERE clause filtering that allowed bypassing protected field restrictions via dot-notation queries. Attackers could subscribe to LiveQuery updates with queries that filter on protected fields, such as 'secretObj.apiKey', thereby leaking sensitive information intended to be hidden by protected field ACLs. The patch adds thorough checks forbidding subscriptions containing conditions on protected fields, preventing unauthorized data access.

Affected Code

if (!client.hasMasterKey) {
  const auth = request.user ? { user: request.user, userRoles: [] } : {};
  const protectedFields =
    appConfig.database.addProtectedFields(
      classLevelPermissions,
      className,
      request.query.where,
      aclGroup,
      auth
    ) || [];
  if (protectedFields.length > 0 && request.query.where) {
    const checkWhere = (where: any) => {
      if (typeof where !== 'object' || where === null) {
        return;
      }
      for (const whereKey of Object.keys(where)) {
        const rootField = whereKey.split('.')[0];
        if (protectedFields.includes(whereKey) || protectedFields.includes(rootField)) {
          throw new Parse.Error(
            Parse.Error.OPERATION_FORBIDDEN,
            'Permission denied'
          );
        }
      }
      for (const op of ['$or', '$and', '$nor']) {
        if (Array.isArray(where[op])) {
          where[op].forEach((subQuery: any) => checkWhere(subQuery));
        }
      }
    };
    checkWhere(request.query.where);
  }
}

Proof of Concept

const query = new Parse.Query('SecretClass');
query._addCondition('secretObj.apiKey', '$eq', 'SENSITIVE_KEY_123');
await query.subscribe()
  .then(() => console.log('Subscription succeeded unexpectedly, data leakage possible!'))
  .catch(error => console.log('Subscription rejected: ' + error.message));

// Before patch: subscription succeeds, allowing attacker to subscribe to updates filtered by protected field secretObj.apiKey
// After patch: subscription throws 'Permission denied' error, blocking unauthorized access.

This issue was automatically created by Vulnerability Spoiler Alert.
Detected at: 2026-03-11T00:01:34.905Z

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions