Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b3af7cf

Browse files
committed
Guard JSON conversion depth for CWE-674
ConvertFromJson now applies the configured MessagePackSecurity maximum object graph depth while translating nested JSON objects and arrays, preventing deeply nested input from recursing until stack exhaustion. Added a bounded regression test that verifies over-depth JSON is rejected for both compressed and uncompressed conversion paths.
1 parent 06ea249 commit b3af7cf

2 files changed

Lines changed: 32 additions & 2 deletions

File tree

src/MessagePack/MessagePackSerializer.Json.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,11 @@ public static void ConvertFromJson(TextReader reader, ref MessagePackWriter writ
187187
}
188188

189189
private static uint FromJsonCore(TinyJsonReader jr, ref MessagePackWriter writer, MessagePackSerializerOptions options)
190+
{
191+
return FromJsonCore(jr, ref writer, options, 0);
192+
}
193+
194+
private static uint FromJsonCore(TinyJsonReader jr, ref MessagePackWriter writer, MessagePackSerializerOptions options, int depth)
190195
{
191196
uint count = 0;
192197
while (jr.Read())
@@ -196,11 +201,13 @@ private static uint FromJsonCore(TinyJsonReader jr, ref MessagePackWriter writer
196201
case TinyJsonToken.None:
197202
break;
198203
case TinyJsonToken.StartObject:
204+
VerifyJsonObjectGraphDepth(options, depth);
205+
199206
// Set up a scratch area to serialize the collection since we don't know its length yet, which must be written first.
200207
using (var scratchRental = options.SequencePool.Rent())
201208
{
202209
MessagePackWriter scratchWriter = writer.Clone(scratchRental.Value);
203-
var mapCount = FromJsonCore(jr, ref scratchWriter, options);
210+
var mapCount = FromJsonCore(jr, ref scratchWriter, options, depth + 1);
204211
scratchWriter.Flush();
205212

206213
mapCount = mapCount / 2; // remove propertyname string count.
@@ -213,11 +220,13 @@ private static uint FromJsonCore(TinyJsonReader jr, ref MessagePackWriter writer
213220
case TinyJsonToken.EndObject:
214221
return count; // break
215222
case TinyJsonToken.StartArray:
223+
VerifyJsonObjectGraphDepth(options, depth);
224+
216225
// Set up a scratch area to serialize the collection since we don't know its length yet, which must be written first.
217226
using (var scratchRental = options.SequencePool.Rent())
218227
{
219228
MessagePackWriter scratchWriter = writer.Clone(scratchRental.Value);
220-
var arrayCount = FromJsonCore(jr, ref scratchWriter, options);
229+
var arrayCount = FromJsonCore(jr, ref scratchWriter, options, depth + 1);
221230
scratchWriter.Flush();
222231

223232
writer.WriteArrayHeader(arrayCount);
@@ -273,6 +282,14 @@ private static uint FromJsonCore(TinyJsonReader jr, ref MessagePackWriter writer
273282
return count;
274283
}
275284

285+
private static void VerifyJsonObjectGraphDepth(MessagePackSerializerOptions options, int depth)
286+
{
287+
if (depth >= options.Security.MaximumObjectGraphDepth)
288+
{
289+
throw new InsufficientExecutionStackException($"This JSON sequence has an object graph that exceeds the maximum depth allowed of {options.Security.MaximumObjectGraphDepth}.");
290+
}
291+
}
292+
276293
private static void ToJsonCore(ref MessagePackReader reader, TextWriter writer, MessagePackSerializerOptions options)
277294
{
278295
MessagePackType type = reader.NextMessagePackType;

tests/MessagePack.Tests/ToJsonTest.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,19 @@ public void ComplexToJson()
4747
this.JsonConvert(json, LZ4Standard).Is(json);
4848
}
4949

50+
[Theory]
51+
[InlineData(false)]
52+
[InlineData(true)]
53+
[Trait("CWE", "674")]
54+
public void ConvertFromJsonRejectsExcessiveNesting(bool compression)
55+
{
56+
var options = MessagePackSerializerOptions.Standard
57+
.WithCompression(compression ? MessagePackCompression.Lz4Block : MessagePackCompression.None)
58+
.WithSecurity(MessagePackSecurity.UntrustedData.WithMaximumObjectGraphDepth(3));
59+
60+
Assert.Throws<InsufficientExecutionStackException>(() => MessagePackSerializer.ConvertFromJson("[[[[1]]]]", options));
61+
}
62+
5063
[Fact]
5164
public void FloatJson()
5265
{

0 commit comments

Comments
 (0)