File tree Expand file tree Collapse file tree 3 files changed +49
-9
lines changed
packages/plugins/max-depth Expand file tree Collapse file tree 3 files changed +49
-9
lines changed Original file line number Diff line number Diff line change 1+ ---
2+ " @escape.tech/graphql-armor-max-depth " : patch
3+ ---
4+
5+ fix: max-depth bypass using fragment cache
Original file line number Diff line number Diff line change @@ -98,20 +98,20 @@ class MaxDepthVisitor {
9898 }
9999 }
100100 } else if ( node . kind == Kind . FRAGMENT_SPREAD ) {
101+ if ( ! this . config . flattenFragments ) {
102+ parentDepth += 1 ;
103+ }
104+
101105 if ( this . visitedFragments . has ( node . name . value ) ) {
102- return this . visitedFragments . get ( node . name . value ) ?? 0 ;
106+ return parentDepth + ( this . visitedFragments . get ( node . name . value ) ?? 0 ) ;
103107 } else {
104108 this . visitedFragments . set ( node . name . value , - 1 ) ;
105109 }
106110 const fragment = this . context . getFragment ( node . name . value ) ;
107111 if ( fragment ) {
108- let fragmentDepth ;
109- if ( this . config . flattenFragments ) {
110- fragmentDepth = this . countDepth ( fragment , parentDepth ) ;
111- } else {
112- fragmentDepth = this . countDepth ( fragment , parentDepth + 1 ) ;
113- }
114- depth = Math . max ( depth , fragmentDepth ) ;
112+ let fragmentDepth = this . countDepth ( fragment , 0 ) ;
113+
114+ depth = Math . max ( depth , parentDepth + fragmentDepth ) ;
115115 if ( this . visitedFragments . get ( node . name . value ) === - 1 ) {
116116 this . visitedFragments . set ( node . name . value , fragmentDepth ) ;
117117 }
Original file line number Diff line number Diff line change @@ -191,7 +191,7 @@ describe('maxDepthPlugin', () => {
191191 assertSingleExecutionValue ( result ) ;
192192 expect ( result . errors ) . toBeDefined ( ) ;
193193 expect ( result . errors ?. map ( ( error ) => error . message ) ) . toContain (
194- 'Syntax Error: Query depth limit of 3 exceeded, found 4 .' ,
194+ 'Syntax Error: Query depth limit of 3 exceeded, found 5 .' ,
195195 ) ;
196196 } ) ;
197197
@@ -269,4 +269,39 @@ describe('maxDepthPlugin', () => {
269269 `Syntax Error: Query depth limit of ${ maxDepth } exceeded, found ${ maxDepth + 2 } .` ,
270270 ] ) ;
271271 } ) ;
272+
273+ it ( 'rejects for exceeding max depth by reusing a cached Fragment' , async ( ) => {
274+ const bypass_query = `
275+ query {
276+ books {
277+ author {
278+ ...Test
279+ }
280+ }
281+ books {
282+ author {
283+ books {
284+ author {
285+ ...Test
286+ }
287+ }
288+ }
289+ }
290+ }
291+ fragment Test on Author {
292+ books {
293+ title
294+ }
295+ }
296+ ` ;
297+ const maxDepth = 6 ;
298+ const testkit = createTestkit ( [ maxDepthPlugin ( { n : maxDepth , exposeLimits : true } ) ] , schema ) ;
299+ const result = await testkit . execute ( bypass_query ) ;
300+
301+ assertSingleExecutionValue ( result ) ;
302+ expect ( result . errors ) . toBeDefined ( ) ;
303+ expect ( result . errors ?. map ( ( error ) => error . message ) ) . toEqual ( [
304+ `Syntax Error: Query depth limit of ${ maxDepth } exceeded, found ${ maxDepth + 2 } .` ,
305+ ] ) ;
306+ } ) ;
272307} ) ;
You can’t perform that action at this time.
0 commit comments