CVE-2023-50572
Description
CVE-2023-50572: jline-groovy v3.24.1 allows denial of service via OutOfMemory error through the GroovyEngine.execute component.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
CVE-2023-50572: jline-groovy v3.24.1 allows denial of service via OutOfMemory error through the GroovyEngine.execute component.
Vulnerability
Overview
An issue in the GroovyEngine.execute component of jline-groovy v3.24.1 allows attackers to cause an OutOfMemory (OOM) error, leading to a denial of service [4]. The vulnerability is rooted in how the internalPrintln method handles long lines or large objects without proper constraints, specifically missing a maxrows parameter to limit output [2]. Without this limit, the highlightAndPrint method can process unlimited amounts of data, exhausting available heap memory [2][3].
Exploitation
To trigger the OOM condition, an attacker could provide crafted input that causes the GroovyEngine to generate excessively long strings or large JSON outputs [1][2]. The attack does not require authentication if the application exposes the console or script execution to untrusted users. The jline library is used for reading console input in Java applications, so any application that uses jline-groovy's REPL or scripting features with arbitrary input is potentially affected [1][3].
Impact
Successful exploitation results in a denial of service through memory exhaustion, which can crash the Java process or degrade system performance [4]. This could disrupt services relying on jline for terminal input/output operations, especially those processing large data structures or long lines without size validation.
Mitigation
The maintainers have addressed this issue by adding a maxrows parameter to limit the number of rows processed in internalPrintln and highlightAndPrint calls [2]. Users should update to a patched version of jline3 that includes the commit fixing the OOM vulnerability [2][3]. As of the publication date, no workaround is documented beyond applying the patch.
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.jline:jline-parentMaven | < 3.25.0 | 3.25.0 |
Affected products
2- jline-groovy/jline-groovydescription
Patches
1f3c60a3e6255GroovyEngine.execute cause an OOM exception, fixes #909
1 file changed · +20 −12
console/src/main/java/org/jline/console/impl/DefaultPrinter.java+20 −12 modified@@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2022, the original author(s). + * Copyright (c) 2002-2023, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -337,14 +337,15 @@ private void internalPrintln(Map<String, Object> options, Object object) { String style = (String) options.getOrDefault(Printer.STYLE, ""); options.put(Printer.STYLE, valueHighlighter(style)); int width = (int) options.get(Printer.WIDTH); + int maxrows = (int) options.get(Printer.MAXROWS); if (!style.isEmpty() && object instanceof String) { - highlightAndPrint(width, (SyntaxHighlighter) options.get(Printer.STYLE), (String) object, true); + highlightAndPrint(width, (SyntaxHighlighter) options.get(Printer.STYLE), (String) object, true, maxrows); } else if (style.equalsIgnoreCase("JSON")) { if (engine == null) { throw new IllegalArgumentException("JSON style not supported!"); } String json = engine.toJson(object); - highlightAndPrint(width, (SyntaxHighlighter) options.get(Printer.STYLE), json, true); + highlightAndPrint(width, (SyntaxHighlighter) options.get(Printer.STYLE), json, true, maxrows); } else if (options.containsKey(Printer.SKIP_DEFAULT_OPTIONS)) { highlightAndPrint(options, object); } else if (object instanceof Exception) { @@ -354,7 +355,7 @@ private void internalPrintln(Map<String, Object> options, Object object) { } else if (object instanceof String || object instanceof Number) { String str = object.toString(); SyntaxHighlighter highlighter = (SyntaxHighlighter) options.getOrDefault(Printer.VALUE_STYLE, null); - highlightAndPrint(width, highlighter, str, doValueHighlight(options, str)); + highlightAndPrint(width, highlighter, str, doValueHighlight(options, str), maxrows); } else { highlightAndPrint(options, object); } @@ -464,14 +465,20 @@ private boolean doValueHighlight(Map<String, Object> options, String value) { } } - private void highlightAndPrint(int width, SyntaxHighlighter highlighter, String object, boolean doValueHighlight) { - for (String s : object.split("\\r?\\n")) { + private void highlightAndPrint( + int width, SyntaxHighlighter highlighter, String object, boolean doValueHighlight, int maxrows) { + String[] rows = object.split("\\r?\\n", maxrows); + int lastRowIdx = rows.length == maxrows ? rows.length - 1 : rows.length; + for (int i = 0; i < lastRowIdx; i++) { AttributedStringBuilder asb = new AttributedStringBuilder(); - List<AttributedString> sas = asb.append(s).columnSplitLength(width); + List<AttributedString> sas = asb.append(rows[i]).columnSplitLength(width); for (AttributedString as : sas) { highlight(width, highlighter, as.toString(), doValueHighlight).println(terminal()); } } + if (rows.length == maxrows) { + throw new TruncatedOutputException("Truncated output: " + maxrows); + } } private Map<String, Object> keysToString(Map<Object, Object> map) { @@ -749,6 +756,7 @@ private boolean isNumber(String str) { @SuppressWarnings("unchecked") private void highlightAndPrint(Map<String, Object> options, Object obj) { int width = (int) options.get(Printer.WIDTH); + int maxrows = (int) options.get(Printer.MAXROWS); totLines = 0; String message = null; RuntimeException runtimeException = null; @@ -758,10 +766,9 @@ private void highlightAndPrint(Map<String, Object> options, Object obj) { highlightMap(options, keysToString((Map<Object, Object>) obj), width); } else if (collectionObject(obj)) { List<Object> collection = objectToList(obj); - if (collection.size() > (int) options.get(Printer.MAXROWS)) { - message = "Truncated output: " + options.get(Printer.MAXROWS) + "/" + collection.size(); - collection = - collection.subList(collection.size() - (int) options.get(Printer.MAXROWS), collection.size()); + if (collection.size() > maxrows) { + message = "Truncated output: " + maxrows + "/" + collection.size(); + collection = collection.subList(collection.size() - maxrows, collection.size()); } if (!collection.isEmpty()) { if (collection.size() == 1 && !options.containsKey(Printer.ONE_ROW_TABLE)) { @@ -771,7 +778,8 @@ private void highlightAndPrint(Map<String, Object> options, Object obj) { } else if (canConvert(elem) && !options.containsKey(Printer.TO_STRING)) { highlightMap(options, objectToMap(options, elem), width); } else if (elem instanceof String && options.get(Printer.STYLE) != null) { - highlightAndPrint(width, (SyntaxHighlighter) options.get(Printer.STYLE), (String) elem, true); + highlightAndPrint( + width, (SyntaxHighlighter) options.get(Printer.STYLE), (String) elem, true, maxrows); } else { highlightValue(options, null, objectToString(options, obj)) .println(terminal());
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4News mentions
0No linked articles in our index yet.