@@ -10,8 +10,8 @@ jest.dontMock('../SingleInstanceStateController');
1010jest . dontMock ( '../TaskQueue' ) ;
1111jest . dontMock ( './test_helpers/flushPromises' ) ;
1212
13- const mockObject = function ( ) { } ;
14- mockObject . registerSubclass = function ( ) { } ;
13+ const mockObject = function ( ) { } ;
14+ mockObject . registerSubclass = function ( ) { } ;
1515jest . setMock ( '../ParseObject' , {
1616 __esModule : true ,
1717 default : mockObject ,
@@ -698,4 +698,93 @@ describe('SingleInstanceStateController', () => {
698698 existed : false ,
699699 } ) ;
700700 } ) ;
701+
702+ describe ( 'Prototype Pollution Protection (CVE-2025-57324)' , ( ) => {
703+ beforeEach ( ( ) => {
704+ SingleInstanceStateController . clearAllState ( ) ;
705+ } ) ;
706+
707+ it ( 'prevents prototype pollution via __proto__ as className' , ( ) => {
708+ const testObj = { className : '__proto__' , id : 'pollutedProperty' } ;
709+
710+ // Should not throw error (silent prevention via Object.create(null))
711+ SingleInstanceStateController . initializeState ( testObj , { } ) ;
712+
713+ // Verify no pollution occurred on actual Object.prototype
714+ expect ( { } . pollutedProperty ) . toBe ( undefined ) ;
715+ expect ( Object . prototype . pollutedProperty ) . toBe ( undefined ) ;
716+ } ) ;
717+
718+ it ( 'prevents prototype pollution via constructor as className' , ( ) => {
719+ const testObj = { className : 'constructor' , id : 'testId' } ;
720+
721+ // Should not throw error (silent prevention)
722+ SingleInstanceStateController . initializeState ( testObj , { } ) ;
723+
724+ // Verify no pollution occurred
725+ const freshObj = { } ;
726+ expect ( freshObj . testId ) . toBe ( undefined ) ;
727+ } ) ;
728+
729+ it ( 'prevents prototype pollution via prototype as className' , ( ) => {
730+ const testObj = { className : 'prototype' , id : 'testId' } ;
731+
732+ // Should not throw error (silent prevention)
733+ SingleInstanceStateController . initializeState ( testObj , { } ) ;
734+
735+ // Verify no pollution occurred
736+ const freshObj = { } ;
737+ expect ( freshObj . testId ) . toBe ( undefined ) ;
738+ } ) ;
739+
740+ it ( 'prevents prototype pollution via __proto__ as id' , ( ) => {
741+ const testObj = { className : 'TestClass' , id : '__proto__' } ;
742+
743+ // Should not throw error (silent prevention)
744+ SingleInstanceStateController . initializeState ( testObj , { } ) ;
745+
746+ // Verify no pollution occurred
747+ expect ( { } . TestClass ) . toBe ( undefined ) ;
748+ } ) ;
749+
750+ it ( 'can store and retrieve data even with dangerous property names' , ( ) => {
751+ const testObj1 = { className : '__proto__' , id : 'pollutedProperty' } ;
752+ const testObj2 = { className : 'constructor' , id : 'testId' } ;
753+
754+ // Should work normally without polluting
755+ SingleInstanceStateController . setServerData ( testObj1 , { value : 'test1' } ) ;
756+ SingleInstanceStateController . setServerData ( testObj2 , { value : 'test2' } ) ;
757+
758+ // Should be able to retrieve the data
759+ const state1 = SingleInstanceStateController . getState ( testObj1 ) ;
760+ const state2 = SingleInstanceStateController . getState ( testObj2 ) ;
761+
762+ expect ( state1 . serverData ) . toEqual ( { value : 'test1' } ) ;
763+ expect ( state2 . serverData ) . toEqual ( { value : 'test2' } ) ;
764+
765+ // But no pollution should occur
766+ expect ( { } . pollutedProperty ) . toBe ( undefined ) ;
767+ expect ( { } . testId ) . toBe ( undefined ) ;
768+ } ) ;
769+
770+ it ( 'allows normal className and id values' , ( ) => {
771+ const testObj = { className : 'NormalClass' , id : 'normalId123' } ;
772+
773+ SingleInstanceStateController . setServerData ( testObj , { counter : 12 } ) ;
774+
775+ const state = SingleInstanceStateController . getState ( testObj ) ;
776+ expect ( state ) . toBeTruthy ( ) ;
777+ expect ( state . serverData ) . toEqual ( { counter : 12 } ) ;
778+ } ) ;
779+
780+ it ( 'prevents pollution when removing dangerous property names' , ( ) => {
781+ const testObj = { className : '__proto__' , id : 'dangerousId' } ;
782+
783+ SingleInstanceStateController . setServerData ( testObj , { data : 'test' } ) ;
784+ SingleInstanceStateController . removeState ( testObj ) ;
785+
786+ // Verify no pollution occurred
787+ expect ( { } . dangerousId ) . toBe ( undefined ) ;
788+ } ) ;
789+ } ) ;
701790} ) ;
0 commit comments