CVE-2026-77422: JLine: ReDoS in Built-in grep Command Amplified by Automatic `.*` Wrapping
Summary
The JLine3 built-in grep command wraps the user-supplied regular expression with . before compiling it with Java's backtracking regex engine. This amplifies catastrophic backtracking and allows a short pattern such as (a+)+b to hang the command thread on non-matching input. In environments that expose the JLine shell to remote users, this is a denial-of-service issue.
Details
In builtins/src/main/java/org/jline/builtins/PosixCommands.java, the grep implementation rewrites the user pattern before compilation:
java String regex = args.remove(0); String regexp = regex; if (opt.isSet("word-regexp")) { regexp = "\\b" + regexp + "\\b"; } if (opt.isSet("line-regexp")) { regexp = "^" + regexp + "$"; } else { regexp = "." + regexp + "."; }
The transformed pattern is compiled with Pattern.compile(...) and then used to test each input line. For a payload such as (a+)+b, the automatic . prefix and suffix increase the backtracking search space substantially.
Affected source location: - builtins/src/main/java/org/jline/builtins/PosixCommands.java - grep(...)
PoC
1. Create a file containing a long run of a characters:
sh printf 'aaaaaaaaaaaaaaaaaaaaaaa\n' > /tmp/testfile.txt
2. Run JLine3's built-in grep against that file:
sh grep '(a+)+b' /tmp/testfile.txt
Expected result: - The command stops responding. - The executing thread consumes high CPU.
Reproduction environment: - JLine3 on x8664 Linux - OpenJDK 25.0.2
Impact
This is a denial-of-service vulnerability caused by catastrophic regex backtracking. Any application embedding org.jline:jline-builtins and exposing the built-in grep command is impacted. In remote shell deployments, an attacker can occupy a worker thread indefinitely and repeat the attack across multiple sessions to reduce service availability for other users.
Suggested Fix
The preferred fix for the current git head is: - stop rewriting non-line-regexp searches as .... - use Matcher.find() for substring semantics - compile user patterns with a linear-time engine such as RE2/J
Suggested patch:
diff diff --git a/builtins/pom.xml b/builtins/pom.xml --- a/builtins/pom.xml +++ b/builtins/pom.xml @@ <dependency> + <groupId>com.google.re2j</groupId> + <artifactId>re2j</artifactId> + <version>1.8</version> + </dependency> + <dependency> <groupId>org.jline</groupId> <artifactId>jline-reader</artifactId> </dependency>
diff --git a/builtins/src/main/java/org/jline/builtins/PosixCommands.java b/builtins/src/main/java/org/jline/builtins/PosixCommands.java --- a/builtins/src/main/java/org/jline/builtins/PosixCommands.java +++ b/builtins/src/main/java/org/jline/builtins/PosixCommands.java @@ -import java.util.regex.Pattern; +import com.google.re2j.Pattern; @@ if (opt.isSet("line-regexp")) { regexp = "^" + regexp + "$"; - } else { - regexp = "." + regexp + "."; } @@ - boolean m = p.matcher(line).matches(); + boolean m = opt.isSet("line-regexp") + ? p.matcher(line).matches() + : p.matcher(line).find();
Credits
This issue was identified by Michał Majchrowicz and Marcin Wyczechowski, members of the AFINE Team.
Other sources
JLine is a Java library for handling console input. From 3.0.0 until 3.30.15 and 4.3.1, the JLine built-in grep command in builtins/src/main/java/org/jline/builtins/PosixCommands.java accepts a user-controlled regular expression in grep(...) and, unless line-regexp mode is used, automatically adds a dot-star prefix and suffix before compiling it with Java's backtracking regular expression engine. The wrapping expands the backtracking search space, so a short nested-quantifier expression evaluated against non-matching input can consume excessive CPU and indefinitely block a command worker, including in remotely exposed shell sessions. This issue is fixed in versions 3.30.15 and 4.3.1.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
maven/org.jline:jline-builtinsto a version that resolves this vulnerability.Fixed in 3.30.15 - Upgrade
Upgrade
maven/org.jline:jline-builtinsto a version that resolves this vulnerability.Fixed in 4.3.1 - Upgrade
Upgrade
org.jline:jline-builtinsto a version that resolves this vulnerability.Fixed in 3.30.15 - Upgrade
Upgrade
org.jline:jline-builtinsto a version that resolves this vulnerability.Fixed in 4.3.1
Event History
Frequently Asked Questions
Who is realistically exposed to this denial-of-service issue?
Deployments that expose a JLine shell to remote users are affected because an unauthenticated remote user can supply a malicious regular expression to the built-in grep command. The impact is a hung command thread when grep processes non-matching input.
What input is needed to trigger the issue?
An attacker needs to invoke the built-in grep command with a regex that causes catastrophic backtracking, such as `(a+)+b`, and provide input containing a long run of `a` characters that does not match. JLine's default grep behavior adds `.*` before and after the supplied expression unless the line-regexp option is used, substantially increasing the backtracking search space.
Does the issue depend on a special grep option?
No. In the normal mode, grep automatically transforms the supplied regex to `.*<regex>.*`; this is the behavior described as amplifying catastrophic backtracking. The word-regexp option adds word boundaries, while the line-regexp option instead anchors the expression to the start and end of the line.