Headline
CVE-2023-26144: OverlappingFieldsCanBeMergedRule: Fix performance degradation (#3958) · graphql/graphql-js@f94b511
Versions of the package graphql from 16.3.0 and before 16.8.1 are vulnerable to Denial of Service (DoS) due to insufficient checks in the OverlappingFieldsCanBeMergedRule.ts file when parsing large queries. This vulnerability allows an attacker to degrade system performance. Note: It was not proven that this vulnerability can crash the process.
Expand Up @@ -7,8 +7,8 @@ import type { DirectiveNode, FieldNode, FragmentDefinitionNode, ObjectValueNode, SelectionSetNode, ValueNode, } from '…/…/language/ast.js’; import { Kind } from '…/…/language/kinds.js’; import { print } from '…/…/language/printer.js’; Expand Down Expand Up @@ -592,7 +592,7 @@ function findConflict( }
// Two field calls must have the same arguments. if (stringifyArguments(node1) !== stringifyArguments(node2)) { if (!sameArguments(node1, node2)) { return [ [responseName, ‘they have differing arguments’], [node1], Expand Down Expand Up @@ -649,19 +649,38 @@ function findConflict( } }
function stringifyArguments(fieldNode: FieldNode | DirectiveNode): string { // FIXME https://github.com/graphql/graphql-js/issues/2203 const args = /* c8 ignore next */ fieldNode.arguments ?? [];
const inputObjectWithArgs: ObjectValueNode = { kind: Kind.OBJECT, fields: args.map((argNode) => ({ kind: Kind.OBJECT_FIELD, name: argNode.name, value: argNode.value, })), }; return print(sortValueNode(inputObjectWithArgs)); function sameArguments( node1: FieldNode | DirectiveNode, node2: FieldNode | DirectiveNode, ): boolean { const args1 = node1.arguments; const args2 = node2.arguments;
if (args1 === undefined || args1.length === 0) { return args2 === undefined || args2.length === 0; } if (args2 === undefined || args2.length === 0) { return false; }
if (args1.length !== args2.length) { return false; }
const values2 = new Map(args2.map(({ name, value }) => [name.value, value])); return args1.every((arg1) => { const value1 = arg1.value; const value2 = values2.get(arg1.name.value); if (value2 === undefined) { return false; }
return stringifyValue(value1) === stringifyValue(value2); }); }
function stringifyValue(value: ValueNode): string | null { return print(sortValueNode(value)); }
function getStreamDirective( Expand All @@ -681,7 +700,7 @@ function sameStreams( return true; } else if (stream1 && stream2) { // check if both fields have equivalent streams return stringifyArguments(stream1) === stringifyArguments(stream2); return sameArguments(stream1, stream2); } // fields have a mix of stream and no stream return false; Expand Down
Related news
Versions of the package graphql from 16.3.0 and before 16.8.1 are vulnerable to Denial of Service (DoS) due to insufficient checks in the OverlappingFieldsCanBeMergedRule.ts file when parsing large queries. This vulnerability allows an attacker to degrade system performance. **Note:** It was not proven that this vulnerability can crash the process.