Broken Object Level Authorization

Broken Object Level Authorization - Node.js (Express) [CVE-2026-34532]

[Fixed month year] Updated CVE-2026-34532

Overview

Broken Object Level Authorization (BOLA) in Node.js ecosystems can occur when an API exposes object-specific actions behind a dynamic dispatch that relies on client-provided identifiers, and the server fails to enforce access controls for every object. In the Parse Server scenario described by CVE-2026-34532, attackers could bypass validator enforcement by manipulating the function endpoint name in the URL, causing the trigger store traversal to reach a handler while the validator store does not mirror that traversal. This allowed unauthenticated callers to invoke Cloud Functions that were intended to be protected by validators like requireUser or requireMaster. The issue is categorized under CWE-863 (Incorrect Authorization) and has been patched in Parse Server versions 8.6.67 and 9.7.0-alpha.11. This kind of vulnerability is especially dangerous in server-side code paths that map dynamically named entries (handlers/validators) and rely on prototype-based property lookups for authorization checks. In a Node.js/Express application, similar patterns can occur if you expose function-like endpoints that are resolved via user-controlled keys and then gated by validators that are not guaranteed to be consistent with the reached handler. Implementations must ensure that authorization decisions are made based on explicit, server-checked mappings rather than indirect or prototype-based property access. The risk exposure is a classic Broken Object Level Authorization scenario: an attacker can perform operations on an object they should not access by manipulating the object identifier in the request path or parameter.

Affected Versions

Parse Server versions prior to 8.6.67 and prior to 9.7.0-alpha.11 (i.e., < 8.6.67 and < 9.7.0-alpha.11).

Code Fix Example

Node.js (Express) API Security Remediation
Vulnerable pattern (conceptual, Node.js/Express inspired):

// Vulnerable: dynamic dispatch based on client-provided name, with separate validators that are not guaranteed to align with the chosen handler
const handlers = {
  getUserData: (req, res) => { res.json({ data: 'secret' }); }
};

const validators = {
  getUserData: (req, res, next) => {
    if (!req.user) return res.status(401).send('Unauthorized');
    next();
  }
};

app.get('/cloudfunc/:name', (req, res, next) => {
  const name = req.params.name; // attacker-controlled string
  const handler = handlers[name]; // dynamic lookup via name
  const validator = validators[name]; // could be undefined or mismatched
  if (validator) {
    validator(req, res, () => handler(req, res));
  } else if (handler) {
    handler(req, res);
  } else {
    res.status(404).send('Not found');
  }
});

// This pattern can allow bypass if an attacker supplies a name that traverses prototype chains or bypasses ownership checks via misaligned validator/handler mappings.

----------------------------------------
Fixed pattern (explicit, safe mapping):

// Safe: use a strict, whitelisted map of allowed operations with a single source of truth for validator + handler binding
const WHITELIST = {
  getUserData: {
    handler: (req, res) => { res.json({ data: 'secret' }); }
  }
};

// Centralized, explicit authorization enforcement
const requireUser = (req, res, next) => {
  if (!req.user) return res.status(401).send('Unauthorized');
  next();
};

app.get('/cloudfunc/:name', (req, res) => {
  const name = req.params.name;
  const entry = WHITELIST[name];
  if (!entry) return res.status(404).send('Not found');
  // Always enforce authorization first, using a single, explicit chain
  return requireUser(req, res, () => entry.handler(req, res));
});

// The fix uses a whitelist and explicit authorization middleware instead of dynamic, prototype-based resolution.

CVE References

Choose which optional cookies to allow. You can change this any time.