CVE-2024-21907 (published 2024-01-03T16:15Z)

Newtonsoft.Json before version 13.0.1 is affected by a mishandling of exceptional conditions vulnerability. Crafted data that is passed to the JsonConvert.DeserializeObject method may trigger a StackOverflow exception resulting in denial of service. Depending on the usage of the library, an unauthenticated and remote attacker may be able to cause the denial of service condition.\n

CVSS v3 base score: 7.5, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: CWE-755
cwe_name: Improper Handling of Exceptional Conditions
description: The product does not handle or incorrectly handles an exceptional condition.
extended_description: 
            
         
         

Fix information:
repo_url: https://github.com/JamesNK/Newtonsoft.Json
commit_details: repo_url: https://github.com/JamesNK/Newtonsoft.Json
author: James Newton-King
author_date: 2021-01-31 15:57:06+13:00
msg: Change JsonReader and JsonSerializer default max depth to 128 (#2462)
repository: repo_url: https://github.com/JamesNK/Newtonsoft.Json
repo_name: JamesNK/Newtonsoft.Json
description: Json.NET is a popular high-performance JSON framework for .NET
repo_language: C#
owner: JamesNK
file_changes: filename: JsonSerializerTest.cs
change_type: ModificationType.MODIFY
diff: @@ -7995,5 +7995,46 @@ public void NullableDoubleEmptyValue()
                 () => JsonConvert.DeserializeObject<EmptyJsonValueTestClass>("{ A: \"\", B: 1, C: 123, D: 1.23, E: , F: null }"),
                 "Unexpected character encountered while parsing value: ,. Path 'E', line 1, position 36.");
         }
+
+        [Test]
+        public void SetMaxDepth_DepthExceeded()
+        {
+            JsonTextReader reader = new JsonTextReader(new StringReader("[[['text']]]"));
+            Assert.AreEqual(128, reader.MaxDepth);
+
+            JsonSerializerSettings settings = new JsonSerializerSettings();
+            Assert.AreEqual(128, settings.MaxDepth);
+            Assert.AreEqual(false, settings._maxDepthSet);
+
+            // Default should be the same
+            Assert.AreEqual(reader.MaxDepth, settings.MaxDepth);
+
+            settings.MaxDepth = 2;
+            Assert.AreEqual(2, settings.MaxDepth);
+            Assert.AreEqual(true, settings._maxDepthSet);
+
+            JsonSerializer serializer = JsonSerializer.Create(settings);
+            Assert.AreEqual(2, serializer.MaxDepth);
+
+            ExceptionAssert.Throws<JsonReaderException>(
+                () => serializer.Deserialize(reader),
+                "The reader's MaxDepth of 2 has been exceeded. Path '[0][0]', line 1, position 3.");
+        }
+
+        [Test]
+        public void SetMaxDepth_DepthNotExceeded()
+        {
+            JsonTextReader reader = new JsonTextReader(new StringReader("['text']"));
+            JsonSerializerSettings settings = new JsonSerializerSettings();
+
+            settings.MaxDepth = 2;
+
+            JsonSerializer serializer = JsonSerializer.Create(settings);
+            Assert.AreEqual(2, serializer.MaxDepth);
+
+            serializer.Deserialize(reader);
+
+            Assert.AreEqual(128, reader.MaxDepth);
+        }
     }
 }

programming_language: C#
filename: JsonReader.cs
change_type: ModificationType.MODIFY
diff: @@ -227,6 +227,8 @@ public FloatParseHandling FloatParseHandling
 
         /// <summary>
         /// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a <see cref="JsonReaderException"/>.
+        /// A null value means there is no maximum. 
+        /// The default value is <c>128</c>.
         /// </summary>
         public int? MaxDepth
         {
@@ -327,6 +329,7 @@ protected JsonReader()
             _dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
             _dateParseHandling = DateParseHandling.DateTime;
             _floatParseHandling = FloatParseHandling.Double;
+            _maxDepth = 128;
 
             CloseInput = true;
         }

programming_language: C#
filename: JsonSerializer.cs
change_type: ModificationType.MODIFY
diff: @@ -514,7 +514,7 @@ public virtual CultureInfo Culture
         /// <summary>
         /// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a <see cref="JsonReaderException"/>.
         /// A null value means there is no maximum.
-        /// The default value is <c>null</c>.
+        /// The default value is <c>128</c>.
         /// </summary>
         public virtual int? MaxDepth
         {

programming_language: C#
filename: JsonSerializerSettings.cs
change_type: ModificationType.MODIFY
diff: @@ -61,6 +61,7 @@ public class JsonSerializerSettings
         internal static readonly CultureInfo DefaultCulture;
         internal const bool DefaultCheckAdditionalContent = false;
         internal const string DefaultDateFormatString = @"yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";
+        internal const int DefaultMaxDepth = 128;
 
         internal Formatting? _formatting;
         internal DateFormatHandling? _dateFormatHandling;
@@ -325,11 +326,11 @@ public string DateFormatString
         /// <summary>
         /// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a <see cref="JsonReaderException"/>.
         /// A null value means there is no maximum.
-        /// The default value is <c>null</c>.
+        /// The default value is <c>128</c>.
         /// </summary>
         public int? MaxDepth
         {
-            get => _maxDepth;
+            get => _maxDepthSet ? _maxDepth : DefaultMaxDepth;
             set
             {
                 if (value <= 0)

programming_language: C#