@@ -2833,6 +2833,90 @@ describe('(GHSA-9xp9-j92r-p88v) Stack overflow process crash via deeply nested q
28332833 } )
28342834 ) ;
28352835 } ) ;
2836+
2837+ it ( 'rejects deeply nested query before transform pipeline processes it' , async ( ) => {
2838+ await reconfigureServer ( {
2839+ requestComplexity : { queryDepth : 10 } ,
2840+ } ) ;
2841+ const auth = require ( '../lib/Auth' ) ;
2842+ const rest = require ( '../lib/rest' ) ;
2843+ const config = Config . get ( 'test' ) ;
2844+ // Depth 50 bypasses the fix because RestQuery.js transform pipeline
2845+ // recursively traverses the structure before validateQuery() is reached
2846+ let where = { username : 'test' } ;
2847+ for ( let i = 0 ; i < 50 ; i ++ ) {
2848+ where = { $and : [ where ] } ;
2849+ }
2850+ await expectAsync (
2851+ rest . find ( config , auth . nobody ( config ) , '_User' , where )
2852+ ) . toBeRejectedWith (
2853+ jasmine . objectContaining ( {
2854+ 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 / ) ,
2855+ } )
2856+ ) ;
2857+ } ) ;
2858+
2859+ it ( 'rejects deeply nested query via REST API without authentication' , async ( ) => {
2860+ await reconfigureServer ( {
2861+ requestComplexity : { queryDepth : 10 } ,
2862+ } ) ;
2863+ let where = { username : 'test' } ;
2864+ for ( let i = 0 ; i < 50 ; i ++ ) {
2865+ where = { $or : [ where ] } ;
2866+ }
2867+ await expectAsync (
2868+ request ( {
2869+ method : 'GET' ,
2870+ url : `${ Parse . serverURL } /classes/_User` ,
2871+ headers : {
2872+ 'X-Parse-Application-Id' : Parse . applicationId ,
2873+ 'X-Parse-REST-API-Key' : 'rest' ,
2874+ } ,
2875+ qs : { where : JSON . stringify ( where ) } ,
2876+ } )
2877+ ) . toBeRejectedWith (
2878+ jasmine . objectContaining ( {
2879+ data : jasmine . objectContaining ( {
2880+ code : Parse . Error . INVALID_QUERY ,
2881+ } ) ,
2882+ } )
2883+ ) ;
2884+ } ) ;
2885+
2886+ it ( 'rejects deeply nested $nor query before transform pipeline' , async ( ) => {
2887+ await reconfigureServer ( {
2888+ requestComplexity : { queryDepth : 10 } ,
2889+ } ) ;
2890+ const auth = require ( '../lib/Auth' ) ;
2891+ const rest = require ( '../lib/rest' ) ;
2892+ const config = Config . get ( 'test' ) ;
2893+ let where = { username : 'test' } ;
2894+ for ( let i = 0 ; i < 50 ; i ++ ) {
2895+ where = { $nor : [ where ] } ;
2896+ }
2897+ await expectAsync (
2898+ rest . find ( config , auth . nobody ( config ) , '_User' , where )
2899+ ) . toBeRejectedWith (
2900+ jasmine . objectContaining ( {
2901+ 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 / ) ,
2902+ } )
2903+ ) ;
2904+ } ) ;
2905+
2906+ it ( 'allows queries within the depth limit' , async ( ) => {
2907+ await reconfigureServer ( {
2908+ requestComplexity : { queryDepth : 10 } ,
2909+ } ) ;
2910+ const auth = require ( '../lib/Auth' ) ;
2911+ const rest = require ( '../lib/rest' ) ;
2912+ const config = Config . get ( 'test' ) ;
2913+ let where = { username : 'test' } ;
2914+ for ( let i = 0 ; i < 5 ; i ++ ) {
2915+ where = { $or : [ where ] } ;
2916+ }
2917+ const result = await rest . find ( config , auth . nobody ( config ) , '_User' , where ) ;
2918+ expect ( result . results ) . toBeDefined ( ) ;
2919+ } ) ;
28362920} ) ;
28372921
28382922describe ( '(GHSA-fjxm-vhvc-gcmj) LiveQuery Operator Type Confusion' , ( ) => {
0 commit comments