CVE-2021-39194 (published 2021-09-07T20:15Z)

kaml is an open source implementation of the YAML format with support for kotlinx.serialization. In affected versions attackers that could provide arbitrary YAML input to an application that uses kaml could cause the application to endlessly loop while parsing the input. This could result in resource starvation and denial of service. This only affects applications that use polymorphic serialization with the default tagged polymorphism style. Applications using the property polymorphism style are not affected. YAML input for a polymorphic type that provided a tag but no value for the object would trigger the issue. Version 0.35.3 or later contain the fix for this issue.

Severity: MEDIUM
CVSS v2 base score: 4.0 (AV:N/AC:L/Au:S/C:N/I:N/A:P)
CVSS v3 base score: 6.5, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: CWE-835
cwe_name: Loop with Unreachable Exit Condition ('Infinite Loop')
description: The product contains an iteration or loop with an exit condition that cannot be reached, i.e., an infinite loop.
extended_description: If the loop can be influenced by an attacker, this weakness could allow attackers to consume excessive resources such as CPU or memory.
         

Fix information:
repo_url: https://github.com/charleskorn/kaml
commit_details: repo_url: https://github.com/charleskorn/kaml
author: Charles Korn
author_date: 2021-09-05 16:25:56+10:00
msg: Fix issue where decoding a polymorphic type that uses the tag polymorphism style could hang if no value was provided after the tag.

Fixes #179.
repository: repo_url: https://github.com/charleskorn/kaml
repo_name: charleskorn/kaml
description: YAML support for kotlinx.serialization
repo_language: Kotlin
owner: charleskorn
file_changes: filename: YamlInput.kt
change_type: ModificationType.MODIFY
diff: @@ -30,6 +30,7 @@ import kotlinx.serialization.descriptors.StructureKind
 import kotlinx.serialization.descriptors.elementNames
 import kotlinx.serialization.encoding.AbstractDecoder
 import kotlinx.serialization.encoding.CompositeDecoder
+import kotlinx.serialization.encoding.CompositeDecoder.Companion.DECODE_DONE
 import kotlinx.serialization.encoding.CompositeDecoder.Companion.UNKNOWN_NAME
 import kotlinx.serialization.modules.SerializersModule
 import kotlinx.serialization.modules.SerializersModuleCollector
@@ -168,7 +169,7 @@ private class YamlNullInput(val nullValue: YamlNode, context: SerializersModule,
     override fun getCurrentLocation(): Location = nullValue.location
     override fun getCurrentPath(): YamlPath = nullValue.path
 
-    override fun decodeElementIndex(descriptor: SerialDescriptor): Int = 0
+    override fun decodeElementIndex(descriptor: SerialDescriptor): Int = DECODE_DONE
 }
 
 @OptIn(ExperimentalSerializationApi::class)

programming_language: Scala
filename: YamlReadingTest.kt
change_type: ModificationType.MODIFY
diff: @@ -1193,6 +1193,25 @@ object YamlReadingTest : Spek({
                     }
                 }
 
+                // See https://github.com/charleskorn/kaml/issues/179.
+                context("given some input where a tag is provided but no value is provided") {
+                    val input = """
+                        !<sealedString>
+                    """.trimIndent()
+
+                    context("parsing that input") {
+                        it("throws an appropriate exception") {
+                            expect({ polymorphicYaml.decodeFromString(TestSealedStructure.serializer(), input) }).toThrow<MissingRequiredPropertyException> {
+                                message { toBe("Property 'value' is required but it is missing.") }
+                                line { toBe(1) }
+                                column { toBe(1) }
+                                propertyName { toBe("value") }
+                                path { toBe(YamlPath.root) }
+                            }
+                        }
+                    }
+                }
+
                 context("given some input where the value is a literal") {
                     val input = """
                         !<simpleString> "asdfg"

programming_language: Scala