Skip to content

Commit d4c48d9

Browse files
committed
Added Introspection Cycle Detection Rule
1 parent a190f03 commit d4c48d9

27 files changed

+473
-38
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77

88
jobs:
99
release:
10-
runs-on: ubuntu-latest
10+
runs-on: ubuntu-22.04
1111
steps:
1212
- name: Checkout
1313
uses: actions/checkout@v3

src/HotChocolate/Core/src/Abstractions/ErrorCodes.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,11 @@ public static class Validation
321321
/// The introspection is not allowed for the current request
322322
/// </summary>
323323
public const string IntrospectionNotAllowed = "HC0046";
324+
325+
/// <summary>
326+
/// The maximum allowed introspection depth was exceeded.
327+
/// </summary>
328+
public const string MaxIntrospectionDepthOverflow = "HC0086";
324329
}
325330

326331
/// <summary>

src/HotChocolate/Core/src/Abstractions/packages.lock.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -284,9 +284,9 @@
284284
"net8.0": {
285285
"Microsoft.NET.ILLink.Tasks": {
286286
"type": "Direct",
287-
"requested": "[8.0.7, )",
288-
"resolved": "8.0.7",
289-
"contentHash": "iI52ptEKby2ymQ6B7h4TWbFmm85T4VvLgc/HvS45Yr3lgi4IIFbQtjON3bQbX/Vc94jXNSLvrDOp5Kh7SJyFYQ=="
287+
"requested": "[8.0.8, )",
288+
"resolved": "8.0.8",
289+
"contentHash": "P8wR6MUWwYXIjPJuBaZgo5zlI/GWI6QEAo6NyVIbPefa9CCkohYu7dP2rD/mrqnjEqfRHyl+h9VZrDoGpELqYg=="
290290
},
291291
"Microsoft.SourceLink.GitHub": {
292292
"type": "Direct",

src/HotChocolate/Core/src/Types.Shared/packages.lock.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,9 @@
158158
"net8.0": {
159159
"Microsoft.NET.ILLink.Tasks": {
160160
"type": "Direct",
161-
"requested": "[8.0.7, )",
162-
"resolved": "8.0.7",
163-
"contentHash": "iI52ptEKby2ymQ6B7h4TWbFmm85T4VvLgc/HvS45Yr3lgi4IIFbQtjON3bQbX/Vc94jXNSLvrDOp5Kh7SJyFYQ=="
161+
"requested": "[8.0.8, )",
162+
"resolved": "8.0.8",
163+
"contentHash": "P8wR6MUWwYXIjPJuBaZgo5zlI/GWI6QEAo6NyVIbPefa9CCkohYu7dP2rD/mrqnjEqfRHyl+h9VZrDoGpELqYg=="
164164
},
165165
"Microsoft.SourceLink.GitHub": {
166166
"type": "Direct",
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
namespace HotChocolate.Validation;
2+
3+
internal sealed class CoordinateLimit
4+
{
5+
public ushort MaxAllowed { get; private set; }
6+
7+
public ushort Count { get; private set; }
8+
9+
public bool Add()
10+
{
11+
if (Count < MaxAllowed)
12+
{
13+
Count++;
14+
return true;
15+
}
16+
17+
return false;
18+
}
19+
20+
public void Remove() => Count--;
21+
22+
public void Reset(ushort maxAllowed)
23+
{
24+
MaxAllowed = maxAllowed;
25+
Count = 0;
26+
}
27+
}

src/HotChocolate/Core/src/Validation/DocumentValidator.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,11 @@ public ValueTask<DocumentValidatorResult> ValidateAsync(
110110
for (var i = 0; i < length; i++)
111111
{
112112
Unsafe.Add(ref start, i).Validate(context, document);
113+
114+
if (context.FatalErrorDetected)
115+
{
116+
break;
117+
}
113118
}
114119

115120
if (_aggregators.Length == 0)

src/HotChocolate/Core/src/Validation/DocumentValidatorContext.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ public IOutputType NonNullString
9898

9999
public bool UnexpectedErrorsDetected { get; set; }
100100

101+
public bool FatalErrorDetected { get; set; }
102+
101103
public int Count { get; set; }
102104

103105
public int Max { get; set; }
@@ -112,6 +114,8 @@ public IOutputType NonNullString
112114

113115
public HashSet<FieldInfoPair> ProcessedFieldPairs { get; } = [];
114116

117+
public FieldDepthCycleTracker FieldDepth { get; } = new();
118+
115119
public IList<FieldInfo> RentFieldInfoList()
116120
{
117121
var buffer = _buffers.Peek();
@@ -168,7 +172,9 @@ public void Clear()
168172
CurrentFieldPairs.Clear();
169173
NextFieldPairs.Clear();
170174
ProcessedFieldPairs.Clear();
175+
FieldDepth.Reset();
171176
UnexpectedErrorsDetected = false;
177+
FatalErrorDetected = false;
172178
Count = 0;
173179
Max = 0;
174180
Allowed = 0;

src/HotChocolate/Core/src/Validation/ErrorHelper.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,4 +725,18 @@ public static IError StreamOnNonListField(
725725
.SpecifiedBy("sec-Stream-Directives-Are-Used-On-List-Fields")
726726
.SetPath(context.CreateErrorPath())
727727
.Build();
728+
729+
public static void ReportMaxIntrospectionDepthOverflow(
730+
this IDocumentValidatorContext context,
731+
ISyntaxNode selection)
732+
{
733+
context.FatalErrorDetected = true;
734+
context.ReportError(
735+
ErrorBuilder.New()
736+
.SetMessage("Maximum allowed introspection depth exceeded.")
737+
.SetCode(ErrorCodes.Validation.MaxIntrospectionDepthOverflow)
738+
.SetSyntaxNode(selection)
739+
.SetPath(context.CreateErrorPath())
740+
.Build());
741+
}
728742
}

src/HotChocolate/Core/src/Validation/Extensions/ValidatiobBuilderExtensions.Rules.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,4 +342,11 @@ public static IValidationBuilder AddMaxExecutionDepthRule(
342342
public static IValidationBuilder AddIntrospectionAllowedRule(
343343
this IValidationBuilder builder) =>
344344
builder.TryAddValidationVisitor((_, _) => new IntrospectionVisitor(), false);
345+
346+
/// <summary>
347+
/// Adds a validation rule that restricts the depth of a GraphQL introspection request.
348+
/// </summary>
349+
public static IValidationBuilder AddIntrospectionDepthRule(
350+
this IValidationBuilder builder)
351+
=> builder.TryAddValidationVisitor<IntrospectionDepthVisitor>();
345352
}

src/HotChocolate/Core/src/Validation/Extensions/ValidationServiceCollectionExtensions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public static IValidationBuilder AddValidation(
2828
var builder = new DefaultValidationBuilder(schemaName, services);
2929

3030
builder
31+
.AddIntrospectionDepthRule()
3132
.AddDocumentRules()
3233
.AddOperationRules()
3334
.AddFieldRules()

0 commit comments

Comments
 (0)