Skip to content

Commit b3879c8

Browse files
cristunaranjoJoviDeCroock
authored andcommitted
feat(execution): add max coercion errors option to execution context (#4366)
This PR add `executionOptions` property to the `ExecutionArgs`. Currently only one option can be configured, as is the one I need, but I have built an object so it can easily be extended in the future. The property allows the configuration of the maximum number of errors (`maxErrors`) for coercion. This allows the current hardcoded limit (`50`) to be reduced to a small number to avoid possible DoS attacks. > Also, it updates the execution docs to reflect this new change. I think the documentation was outdated since functions were using positional arguments and now they only accept an object. No longer updates the docs.
1 parent 5a169fe commit b3879c8

File tree

2 files changed

+78
-4
lines changed

2 files changed

+78
-4
lines changed

src/execution/__tests__/executor-test.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { Kind } from '../../language/kinds.js';
1010
import { parse } from '../../language/parser.js';
1111

1212
import {
13+
GraphQLInputObjectType,
1314
GraphQLInterfaceType,
1415
GraphQLList,
1516
GraphQLNonNull,
@@ -1380,4 +1381,74 @@ describe('Execute: Handles basic execution tasks', () => {
13801381
expect(result).to.deep.equal({ data: { foo: { bar: 'bar' } } });
13811382
expect(possibleTypes).to.deep.equal([fooObject]);
13821383
});
1384+
1385+
it('uses a different number of max coercion errors', () => {
1386+
const schema = new GraphQLSchema({
1387+
query: new GraphQLObjectType({
1388+
name: 'Query',
1389+
fields: {
1390+
dummy: { type: GraphQLString },
1391+
},
1392+
}),
1393+
mutation: new GraphQLObjectType({
1394+
name: 'Mutation',
1395+
fields: {
1396+
updateUser: {
1397+
type: GraphQLString,
1398+
args: {
1399+
data: {
1400+
type: new GraphQLInputObjectType({
1401+
name: 'User',
1402+
fields: {
1403+
email: { type: new GraphQLNonNull(GraphQLString) },
1404+
},
1405+
}),
1406+
},
1407+
},
1408+
},
1409+
},
1410+
}),
1411+
});
1412+
1413+
const document = parse(`
1414+
mutation ($data: User) {
1415+
updateUser(data: $data)
1416+
}
1417+
`);
1418+
1419+
const options = {
1420+
maxCoercionErrors: 1,
1421+
};
1422+
1423+
const result = executeSync({
1424+
schema,
1425+
document,
1426+
variableValues: {
1427+
data: {
1428+
email: '',
1429+
wrongArg: 'wrong',
1430+
wrongArg2: 'wrong',
1431+
wrongArg3: 'wrong',
1432+
},
1433+
},
1434+
options,
1435+
});
1436+
1437+
// Returns at least 2 errors, one for the first 'wrongArg', and one for coercion limit
1438+
expect(result.errors).to.have.lengthOf(options.maxCoercionErrors + 1);
1439+
1440+
expectJSON(result).toDeepEqual({
1441+
errors: [
1442+
{
1443+
message:
1444+
'Variable "$data" got invalid value { email: "", wrongArg: "wrong", wrongArg2: "wrong", wrongArg3: "wrong" }; Field "wrongArg" is not defined by type "User".',
1445+
locations: [{ line: 2, column: 17 }],
1446+
},
1447+
{
1448+
message:
1449+
'Too many errors processing variables, error limit reached. Execution aborted.',
1450+
},
1451+
],
1452+
});
1453+
});
13831454
});

src/execution/execute.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,11 @@ export interface ExecutionArgs {
200200
enableEarlyExecution?: Maybe<boolean>;
201201
hideSuggestions?: Maybe<boolean>;
202202
abortSignal?: Maybe<AbortSignal>;
203+
/** Additional execution options. */
204+
options?: {
205+
/** Set the maximum number of errors allowed for coercing (defaults to 50). */
206+
maxCoercionErrors?: number;
207+
};
203208
}
204209

205210
export interface StreamUsage {
@@ -473,6 +478,7 @@ export function validateExecutionArgs(
473478
perEventExecutor,
474479
enableEarlyExecution,
475480
abortSignal,
481+
options,
476482
} = args;
477483

478484
if (abortSignal?.aborted) {
@@ -534,10 +540,7 @@ export function validateExecutionArgs(
534540
schema,
535541
variableDefinitions,
536542
rawVariableValues ?? {},
537-
{
538-
maxErrors: 50,
539-
hideSuggestions,
540-
},
543+
{ maxErrors: options?.maxCoercionErrors ?? 50, hideSuggestions },
541544
);
542545

543546
if (variableValuesOrErrors.errors) {

0 commit comments

Comments
 (0)