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 {
98
98
}
99
99
}
100
100
} else if ( node . kind == Kind . FRAGMENT_SPREAD ) {
101
+ if ( ! this . config . flattenFragments ) {
102
+ parentDepth += 1 ;
103
+ }
104
+
101
105
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 ) ;
103
107
} else {
104
108
this . visitedFragments . set ( node . name . value , - 1 ) ;
105
109
}
106
110
const fragment = this . context . getFragment ( node . name . value ) ;
107
111
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 ) ;
115
115
if ( this . visitedFragments . get ( node . name . value ) === - 1 ) {
116
116
this . visitedFragments . set ( node . name . value , fragmentDepth ) ;
117
117
}
Original file line number Diff line number Diff line change @@ -191,7 +191,7 @@ describe('maxDepthPlugin', () => {
191
191
assertSingleExecutionValue ( result ) ;
192
192
expect ( result . errors ) . toBeDefined ( ) ;
193
193
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 .' ,
195
195
) ;
196
196
} ) ;
197
197
@@ -269,4 +269,39 @@ describe('maxDepthPlugin', () => {
269
269
`Syntax Error: Query depth limit of ${ maxDepth } exceeded, found ${ maxDepth + 2 } .` ,
270
270
] ) ;
271
271
} ) ;
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
+ } ) ;
272
307
} ) ;
You can’t perform that action at this time.
0 commit comments