CVE-2025-57324
Description
parse is a package designed to parse JavaScript SDK. A Prototype Pollution vulnerability in the SingleInstanceStateController.initializeState function of parse version 5.3.0 and before allows attackers to inject properties on Object.prototype via supplying a crafted payload, causing denial of service (DoS) as the minimum consequence.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Prototype Pollution in Parse JavaScript SDK <=5.3.0 via SingleInstanceStateController.initializeState allows attackers to cause denial of service by injecting properties on Object.prototype.
Vulnerability
Overview
CVE-2025-57324 is a Prototype Pollution vulnerability in the Parse JavaScript SDK version 5.3.0 and earlier. The flaw resides in the SingleInstanceStateController.initializeState function, which improperly handles the className parameter. By providing a crafted payload with a className value set to __proto__, constructor, or prototype, an attacker can inject arbitrary properties onto Object.prototype [1][4].
Exploitation
Conditions
An attacker able to supply input to the Parse SDK's state initialization, such as via a malicious object or user-controlled data, can exploit this vulnerability. No special authentication or network access is required beyond typical usage of the SDK. The PoC demonstrates that simply calling initializeState with a payload containing className: '__proto__' suffices to pollute the global prototype [4].
Impact
The primary impact is denial of service (DoS), as polluted prototypes can cause unexpected behavior, crashes, or infinite loops in applications relying on the SDK. Additionally, prototype pollution can lead to security control bypasses or further exploitation depending on the application context [1][4].
Mitigation
The vulnerability has been fixed in commit 9e7c1ba [3]. Users are strongly advised to upgrade to a patched version. No workarounds are documented, but ensuring that user-supplied data is sanitized before reaching the vulnerable function may reduce risk.
AI Insight generated on May 19, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
parsenpm | < 7.0.0-alpha.1 | 7.0.0-alpha.1 |
Affected products
1- parse/parsedescription
Patches
19e7c1bad472bfix: Prototype Pollution vulnerability in `SingleInstanceStateController`; fixes security vulnerability [GHSA-9g8m-v378-pcg3](https://github.com/advisories/GHSA-9g8m-v378-pcg3) (#2745)
3 files changed · +124 −15
src/SingleInstanceStateController.ts+30 −10 modified@@ -1,10 +1,17 @@ -import * as ObjectStateMutations from './ObjectStateMutations'; +import * as ObjectStateMutations from "./ObjectStateMutations"; -import type { Op } from './ParseOp'; -import type ParseObject from './ParseObject'; -import type { AttributeMap, ObjectCache, OpsMap, State } from './ObjectStateMutations'; +import type { Op } from "./ParseOp"; +import type ParseObject from "./ParseObject"; +import type { + AttributeMap, + ObjectCache, + OpsMap, + State, +} from "./ObjectStateMutations"; -let objectState: Record<string, Record<string, State>> = {}; +// Use Object.create(null) to create an object without prototype chain +// This prevents prototype pollution attacks +let objectState: Record<string, Record<string, State>> = Object.create(null); export function getState(obj: ParseObject): State | null { const classData = objectState[obj.className]; @@ -20,7 +27,8 @@ export function initializeState(obj: ParseObject, initial?: State): State { return state; } if (!objectState[obj.className]) { - objectState[obj.className] = {}; + // Use Object.create(null) for nested objects too + objectState[obj.className] = Object.create(null); } if (!initial) { initial = ObjectStateMutations.defaultState(); @@ -90,7 +98,12 @@ export function getObjectCache(obj: ParseObject): ObjectCache { export function estimateAttribute(obj: ParseObject, attr: string): any { const serverData = getServerData(obj); const pendingOps = getPendingOps(obj); - return ObjectStateMutations.estimateAttribute(serverData, pendingOps, obj, attr); + return ObjectStateMutations.estimateAttribute( + serverData, + pendingOps, + obj, + attr + ); } export function estimateAttributes(obj: ParseObject): AttributeMap { @@ -101,16 +114,23 @@ export function estimateAttributes(obj: ParseObject): AttributeMap { export function commitServerChanges(obj: ParseObject, changes: AttributeMap) { const state = initializeState(obj); - ObjectStateMutations.commitServerChanges(state.serverData, state.objectCache, changes); + ObjectStateMutations.commitServerChanges( + state.serverData, + state.objectCache, + changes + ); } -export function enqueueTask(obj: ParseObject, task: () => Promise<any>): Promise<void> { +export function enqueueTask( + obj: ParseObject, + task: () => Promise<any> +): Promise<void> { const state = initializeState(obj); return state.tasks.enqueue(task); } export function clearAllState() { - objectState = {}; + objectState = Object.create(null); } export function duplicateState(source: { id: string }, dest: { id: string }) {
src/__tests__/SingleInstanceStateController-test.js+91 −2 modified@@ -10,8 +10,8 @@ jest.dontMock('../SingleInstanceStateController'); jest.dontMock('../TaskQueue'); jest.dontMock('./test_helpers/flushPromises'); -const mockObject = function () {}; -mockObject.registerSubclass = function () {}; +const mockObject = function () { }; +mockObject.registerSubclass = function () { }; jest.setMock('../ParseObject', { __esModule: true, default: mockObject, @@ -698,4 +698,93 @@ describe('SingleInstanceStateController', () => { existed: false, }); }); + + describe('Prototype Pollution Protection (CVE-2025-57324)', () => { + beforeEach(() => { + SingleInstanceStateController.clearAllState(); + }); + + it('prevents prototype pollution via __proto__ as className', () => { + const testObj = { className: '__proto__', id: 'pollutedProperty' }; + + // Should not throw error (silent prevention via Object.create(null)) + SingleInstanceStateController.initializeState(testObj, {}); + + // Verify no pollution occurred on actual Object.prototype + expect({}.pollutedProperty).toBe(undefined); + expect(Object.prototype.pollutedProperty).toBe(undefined); + }); + + it('prevents prototype pollution via constructor as className', () => { + const testObj = { className: 'constructor', id: 'testId' }; + + // Should not throw error (silent prevention) + SingleInstanceStateController.initializeState(testObj, {}); + + // Verify no pollution occurred + const freshObj = {}; + expect(freshObj.testId).toBe(undefined); + }); + + it('prevents prototype pollution via prototype as className', () => { + const testObj = { className: 'prototype', id: 'testId' }; + + // Should not throw error (silent prevention) + SingleInstanceStateController.initializeState(testObj, {}); + + // Verify no pollution occurred + const freshObj = {}; + expect(freshObj.testId).toBe(undefined); + }); + + it('prevents prototype pollution via __proto__ as id', () => { + const testObj = { className: 'TestClass', id: '__proto__' }; + + // Should not throw error (silent prevention) + SingleInstanceStateController.initializeState(testObj, {}); + + // Verify no pollution occurred + expect({}.TestClass).toBe(undefined); + }); + + it('can store and retrieve data even with dangerous property names', () => { + const testObj1 = { className: '__proto__', id: 'pollutedProperty' }; + const testObj2 = { className: 'constructor', id: 'testId' }; + + // Should work normally without polluting + SingleInstanceStateController.setServerData(testObj1, { value: 'test1' }); + SingleInstanceStateController.setServerData(testObj2, { value: 'test2' }); + + // Should be able to retrieve the data + const state1 = SingleInstanceStateController.getState(testObj1); + const state2 = SingleInstanceStateController.getState(testObj2); + + expect(state1.serverData).toEqual({ value: 'test1' }); + expect(state2.serverData).toEqual({ value: 'test2' }); + + // But no pollution should occur + expect({}.pollutedProperty).toBe(undefined); + expect({}.testId).toBe(undefined); + }); + + it('allows normal className and id values', () => { + const testObj = { className: 'NormalClass', id: 'normalId123' }; + + SingleInstanceStateController.setServerData(testObj, { counter: 12 }); + + const state = SingleInstanceStateController.getState(testObj); + expect(state).toBeTruthy(); + expect(state.serverData).toEqual({ counter: 12 }); + }); + + it('prevents pollution when removing dangerous property names', () => { + const testObj = { className: '__proto__', id: 'dangerousId' }; + + SingleInstanceStateController.setServerData(testObj, { data: 'test' }); + SingleInstanceStateController.removeState(testObj); + + // Verify no pollution occurred + expect({}.dangerousId).toBe(undefined); + }); + }); });
types/SingleInstanceStateController.d.ts+3 −3 modified@@ -1,6 +1,6 @@ -import type { Op } from './ParseOp'; -import type ParseObject from './ParseObject'; -import type { AttributeMap, ObjectCache, OpsMap, State } from './ObjectStateMutations'; +import type { Op } from "./ParseOp"; +import type ParseObject from "./ParseObject"; +import type { AttributeMap, ObjectCache, OpsMap, State } from "./ObjectStateMutations"; export declare function getState(obj: ParseObject): State | null; export declare function initializeState(obj: ParseObject, initial?: State): State; export declare function removeState(obj: ParseObject): State | null;
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-9g8m-v378-pcg3ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-57324ghsaADVISORY
- github.com/VulnSageAgent/PoCs/blob/main/JavaScript/prototype-pollution/parse%405.3.0/index.jsghsaWEB
- github.com/VulnSageAgent/PoCs/tree/main/JavaScript/prototype-pollution/CVE-2025-57324ghsaWEB
- github.com/parse-community/Parse-SDK-JS/commit/9e7c1bad472b1ed2463cbac567b8ec752ae5b4c9ghsaWEB
News mentions
0No linked articles in our index yet.