CVE-2026-34532
Description
Parse Server is an open source backend that can be deployed to any infrastructure that can run Node.js. Prior to versions 8.6.67 and 9.7.0-alpha.11, an attacker can bypass Cloud Function validator access controls by appending "prototype.constructor" to the function name in the URL. When a Cloud Function handler is declared using the function keyword and its validator is a plain object or arrow function, the trigger store traversal resolves the handler through its own prototype chain while the validator store fails to mirror this traversal, causing all access control enforcement to be skipped. This allows unauthenticated callers to invoke Cloud Functions that are meant to be protected by validators such as requireUser, requireMaster, or custom validation logic. This issue has been patched in versions 8.6.67 and 9.7.0-alpha.11.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
parse-servernpm | >= 9.0.0, < 9.7.0-alpha.11 | 9.7.0-alpha.11 |
parse-servernpm | < 8.6.67 | 8.6.67 |
Affected products
11cpe:2.3:a:parseplatform:parse-server:9.7.0:alpha5:*:*:*:node.js:*:*+ 10 more
- cpe:2.3:a:parseplatform:parse-server:9.7.0:alpha5:*:*:*:node.js:*:*
- cpe:2.3:a:parseplatform:parse-server:9.7.0:alpha6:*:*:*:node.js:*:*
- cpe:2.3:a:parseplatform:parse-server:9.7.0:alpha7:*:*:*:node.js:*:*
- cpe:2.3:a:parseplatform:parse-server:9.7.0:alpha8:*:*:*:node.js:*:*
- cpe:2.3:a:parseplatform:parse-server:9.7.0:alpha9:*:*:*:node.js:*:*
- cpe:2.3:a:parseplatform:parse-server:*:*:*:*:*:node.js:*:*range: <8.6.67
- cpe:2.3:a:parseplatform:parse-server:9.7.0:alpha1:*:*:*:node.js:*:*
- cpe:2.3:a:parseplatform:parse-server:9.7.0:alpha10:*:*:*:node.js:*:*
- cpe:2.3:a:parseplatform:parse-server:9.7.0:alpha2:*:*:*:node.js:*:*
- cpe:2.3:a:parseplatform:parse-server:9.7.0:alpha3:*:*:*:node.js:*:*
- cpe:2.3:a:parseplatform:parse-server:9.7.0:alpha4:*:*:*:node.js:*:*
Patches
24fc48cf28f22fix: Cloud function validator bypass via prototype chain traversal ([GHSA-vpj2-qq7w-5qq6](https://github.com/parse-community/parse-server/security/advisories/GHSA-vpj2-qq7w-5qq6)) (#10343)
2 files changed · +64 −1
spec/vulnerabilities.spec.js+63 −0 modified@@ -287,6 +287,69 @@ describe('Vulnerabilities', () => { }); }); + describe('(GHSA-vpj2-qq7w-5qq6) Cloud function validator bypass via prototype.constructor traversal', () => { + const headers = { + 'Content-Type': 'application/json', + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + }; + + it('rejects prototype.constructor traversal on function keyword handler', async () => { + Parse.Cloud.define('protectedFn', function () { return 'secret'; }, { requireUser: true }); + const response = await request({ + headers, + method: 'POST', + url: 'http://localhost:8378/1/functions/protectedFn.prototype.constructor', + body: JSON.stringify({}), + }).catch(e => e); + expect(response.status).toBe(400); + const text = JSON.parse(response.text); + expect(text.code).toBe(Parse.Error.SCRIPT_FAILED); + expect(text.error).toContain('Invalid function'); + }); + + it('rejects prototype traversal without constructor suffix', async () => { + Parse.Cloud.define('protectedFn2', function () { return 'secret'; }, { requireUser: true }); + const response = await request({ + headers, + method: 'POST', + url: 'http://localhost:8378/1/functions/protectedFn2.prototype', + body: JSON.stringify({}), + }).catch(e => e); + expect(response.status).toBe(400); + const text = JSON.parse(response.text); + expect(text.code).toBe(Parse.Error.SCRIPT_FAILED); + expect(text.error).toContain('Invalid function'); + }); + + it('enforces validator when calling function normally', async () => { + Parse.Cloud.define('protectedFn3', function () { return 'secret'; }, { requireUser: true }); + const response = await request({ + headers, + method: 'POST', + url: 'http://localhost:8378/1/functions/protectedFn3', + body: JSON.stringify({}), + }).catch(e => e); + expect(response.status).toBe(400); + const text = JSON.parse(response.text); + expect(text.code).toBe(Parse.Error.VALIDATION_ERROR); + }); + + it('enforces requireMaster validator against prototype.constructor bypass', async () => { + Parse.Cloud.define('masterOnlyFn', function () { return 'admin data'; }, { requireMaster: true }); + const response = await request({ + headers, + method: 'POST', + url: 'http://localhost:8378/1/functions/masterOnlyFn.prototype.constructor', + body: JSON.stringify({}), + }).catch(e => e); + expect(response.status).toBe(400); + const text = JSON.parse(response.text); + expect(text.code).toBe(Parse.Error.SCRIPT_FAILED); + expect(text.error).toContain('Invalid function'); + }); + }); + describe('Request denylist', () => { describe('(GHSA-q342-9w2p-57fp) Denylist bypass via sibling nested objects', () => { it('denies _bsontype:Code after a sibling nested object', async () => {
src/triggers.js+1 −1 modified@@ -113,7 +113,7 @@ function getStore(category, name, applicationId) { return createStore(); } store = store[component]; - if (!store) { + if (!store || Object.getPrototypeOf(store) !== null) { return createStore(); } }
dc59e2726656fix: Cloud function validator bypass via prototype chain traversal ([GHSA-vpj2-qq7w-5qq6](https://github.com/parse-community/parse-server/security/advisories/GHSA-vpj2-qq7w-5qq6)) (#10342)
2 files changed · +64 −1
spec/vulnerabilities.spec.js+63 −0 modified@@ -316,6 +316,69 @@ describe('Vulnerabilities', () => { }); }); + describe('(GHSA-vpj2-qq7w-5qq6) Cloud function validator bypass via prototype.constructor traversal', () => { + const headers = { + 'Content-Type': 'application/json', + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + }; + + it('rejects prototype.constructor traversal on function keyword handler', async () => { + Parse.Cloud.define('protectedFn', function () { return 'secret'; }, { requireUser: true }); + const response = await request({ + headers, + method: 'POST', + url: 'http://localhost:8378/1/functions/protectedFn.prototype.constructor', + body: JSON.stringify({}), + }).catch(e => e); + expect(response.status).toBe(400); + const text = JSON.parse(response.text); + expect(text.code).toBe(Parse.Error.SCRIPT_FAILED); + expect(text.error).toContain('Invalid function'); + }); + + it('rejects prototype traversal without constructor suffix', async () => { + Parse.Cloud.define('protectedFn2', function () { return 'secret'; }, { requireUser: true }); + const response = await request({ + headers, + method: 'POST', + url: 'http://localhost:8378/1/functions/protectedFn2.prototype', + body: JSON.stringify({}), + }).catch(e => e); + expect(response.status).toBe(400); + const text = JSON.parse(response.text); + expect(text.code).toBe(Parse.Error.SCRIPT_FAILED); + expect(text.error).toContain('Invalid function'); + }); + + it('enforces validator when calling function normally', async () => { + Parse.Cloud.define('protectedFn3', function () { return 'secret'; }, { requireUser: true }); + const response = await request({ + headers, + method: 'POST', + url: 'http://localhost:8378/1/functions/protectedFn3', + body: JSON.stringify({}), + }).catch(e => e); + expect(response.status).toBe(400); + const text = JSON.parse(response.text); + expect(text.code).toBe(Parse.Error.VALIDATION_ERROR); + }); + + it('enforces requireMaster validator against prototype.constructor bypass', async () => { + Parse.Cloud.define('masterOnlyFn', function () { return 'admin data'; }, { requireMaster: true }); + const response = await request({ + headers, + method: 'POST', + url: 'http://localhost:8378/1/functions/masterOnlyFn.prototype.constructor', + body: JSON.stringify({}), + }).catch(e => e); + expect(response.status).toBe(400); + const text = JSON.parse(response.text); + expect(text.code).toBe(Parse.Error.SCRIPT_FAILED); + expect(text.error).toContain('Invalid function'); + }); + }); + describe('(GHSA-3v4q-4q9g-x83q) Prototype pollution via application ID in trigger store', () => { const prototypeProperties = ['constructor', 'toString', 'valueOf', 'hasOwnProperty', '__proto__'];
src/triggers.js+1 −1 modified@@ -114,7 +114,7 @@ function getStore(category, name, applicationId) { return createStore(); } store = store[component]; - if (!store) { + if (!store || Object.getPrototypeOf(store) !== null) { return createStore(); } }
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
7- github.com/parse-community/parse-server/commit/4fc48cf28f22eea200d74d883505f485234a48d7nvdPatchWEB
- github.com/parse-community/parse-server/commit/dc59e272665644083c5b7f6862d88ce1ef0b2674nvdPatchWEB
- github.com/parse-community/parse-server/pull/10342nvdIssue TrackingPatchWEB
- github.com/parse-community/parse-server/pull/10343nvdIssue TrackingPatchWEB
- github.com/parse-community/parse-server/security/advisories/GHSA-vpj2-qq7w-5qq6nvdPatchVendor AdvisoryMitigationWEB
- github.com/advisories/GHSA-vpj2-qq7w-5qq6ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-34532ghsaADVISORY
News mentions
0No linked articles in our index yet.