@@ -3928,3 +3928,119 @@ describe('(GHSA-qpc3-fg4j-8hgm) Protected field change detection oracle via Live
39283928 } ) ;
39293929
39303930} ) ;
3931+
3932+ describe ( '(GHSA-6qh5-m6g3-xhq6) LiveQuery query depth DoS via deeply nested subscription' , ( ) => {
3933+ afterEach ( async ( ) => {
3934+ const client = await Parse . CoreManager . getLiveQueryController ( ) . getDefaultLiveQueryClient ( ) ;
3935+ if ( client ) {
3936+ await client . close ( ) ;
3937+ }
3938+ } ) ;
3939+
3940+ it ( 'should reject LiveQuery subscription with deeply nested $or when queryDepth is set' , async ( ) => {
3941+ Parse . CoreManager . getLiveQueryController ( ) . setDefaultLiveQueryClient ( null ) ;
3942+ await reconfigureServer ( {
3943+ liveQuery : { classNames : [ 'TestClass' ] } ,
3944+ startLiveQueryServer : true ,
3945+ verbose : false ,
3946+ silent : true ,
3947+ requestComplexity : { queryDepth : 10 } ,
3948+ } ) ;
3949+ const query = new Parse . Query ( 'TestClass' ) ;
3950+ let where = { field : 'value' } ;
3951+ for ( let i = 0 ; i < 15 ; i ++ ) {
3952+ where = { $or : [ where ] } ;
3953+ }
3954+ query . _where = where ;
3955+ await expectAsync ( query . subscribe ( ) ) . toBeRejectedWith (
3956+ jasmine . objectContaining ( {
3957+ code : Parse . Error . INVALID_QUERY ,
3958+ message : jasmine . stringMatching ( / Q u e r y c o n d i t i o n n e s t i n g d e p t h e x c e e d s m a x i m u m a l l o w e d d e p t h / ) ,
3959+ } )
3960+ ) ;
3961+ } ) ;
3962+
3963+ it ( 'should reject LiveQuery subscription with deeply nested $and when queryDepth is set' , async ( ) => {
3964+ Parse . CoreManager . getLiveQueryController ( ) . setDefaultLiveQueryClient ( null ) ;
3965+ await reconfigureServer ( {
3966+ liveQuery : { classNames : [ 'TestClass' ] } ,
3967+ startLiveQueryServer : true ,
3968+ verbose : false ,
3969+ silent : true ,
3970+ requestComplexity : { queryDepth : 10 } ,
3971+ } ) ;
3972+ const query = new Parse . Query ( 'TestClass' ) ;
3973+ let where = { field : 'value' } ;
3974+ for ( let i = 0 ; i < 50 ; i ++ ) {
3975+ where = { $and : [ where ] } ;
3976+ }
3977+ query . _where = where ;
3978+ await expectAsync ( query . subscribe ( ) ) . toBeRejectedWith (
3979+ jasmine . objectContaining ( {
3980+ code : Parse . Error . INVALID_QUERY ,
3981+ message : jasmine . stringMatching ( / Q u e r y c o n d i t i o n n e s t i n g d e p t h e x c e e d s m a x i m u m a l l o w e d d e p t h / ) ,
3982+ } )
3983+ ) ;
3984+ } ) ;
3985+
3986+ it ( 'should reject LiveQuery subscription with deeply nested $nor when queryDepth is set' , async ( ) => {
3987+ Parse . CoreManager . getLiveQueryController ( ) . setDefaultLiveQueryClient ( null ) ;
3988+ await reconfigureServer ( {
3989+ liveQuery : { classNames : [ 'TestClass' ] } ,
3990+ startLiveQueryServer : true ,
3991+ verbose : false ,
3992+ silent : true ,
3993+ requestComplexity : { queryDepth : 10 } ,
3994+ } ) ;
3995+ const query = new Parse . Query ( 'TestClass' ) ;
3996+ let where = { field : 'value' } ;
3997+ for ( let i = 0 ; i < 50 ; i ++ ) {
3998+ where = { $nor : [ where ] } ;
3999+ }
4000+ query . _where = where ;
4001+ await expectAsync ( query . subscribe ( ) ) . toBeRejectedWith (
4002+ jasmine . objectContaining ( {
4003+ code : Parse . Error . INVALID_QUERY ,
4004+ message : jasmine . stringMatching ( / Q u e r y c o n d i t i o n n e s t i n g d e p t h e x c e e d s m a x i m u m a l l o w e d d e p t h / ) ,
4005+ } )
4006+ ) ;
4007+ } ) ;
4008+
4009+ it ( 'should allow LiveQuery subscription within the depth limit' , async ( ) => {
4010+ Parse . CoreManager . getLiveQueryController ( ) . setDefaultLiveQueryClient ( null ) ;
4011+ await reconfigureServer ( {
4012+ liveQuery : { classNames : [ 'TestClass' ] } ,
4013+ startLiveQueryServer : true ,
4014+ verbose : false ,
4015+ silent : true ,
4016+ requestComplexity : { queryDepth : 10 } ,
4017+ } ) ;
4018+ const query = new Parse . Query ( 'TestClass' ) ;
4019+ let where = { field : 'value' } ;
4020+ for ( let i = 0 ; i < 5 ; i ++ ) {
4021+ where = { $or : [ where ] } ;
4022+ }
4023+ query . _where = where ;
4024+ const subscription = await query . subscribe ( ) ;
4025+ expect ( subscription ) . toBeDefined ( ) ;
4026+ } ) ;
4027+
4028+ it ( 'should allow LiveQuery subscription when queryDepth is disabled' , async ( ) => {
4029+ Parse . CoreManager . getLiveQueryController ( ) . setDefaultLiveQueryClient ( null ) ;
4030+ await reconfigureServer ( {
4031+ liveQuery : { classNames : [ 'TestClass' ] } ,
4032+ startLiveQueryServer : true ,
4033+ verbose : false ,
4034+ silent : true ,
4035+ requestComplexity : { queryDepth : - 1 } ,
4036+ } ) ;
4037+ const query = new Parse . Query ( 'TestClass' ) ;
4038+ let where = { field : 'value' } ;
4039+ for ( let i = 0 ; i < 15 ; i ++ ) {
4040+ where = { $or : [ where ] } ;
4041+ }
4042+ query . _where = where ;
4043+ const subscription = await query . subscribe ( ) ;
4044+ expect ( subscription ) . toBeDefined ( ) ;
4045+ } ) ;
4046+ } ) ;
0 commit comments