GHSA-R2XF-8XR9-62GW
Vulnerability from github – Published: 2026-09-23 18:12 – Updated: 2026-09-23 18:12Summary
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:
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
- Create a file containing a long run of
acharacters:
printf 'aaaaaaaaaaaaaaaaaaaaaaa\n' > /tmp/testfile.txt
- Run JLine3's built-in
grepagainst that file:
grep '(a+)+b' /tmp/testfile.txt
Expected result: - The command stops responding. - The executing thread consumes high CPU.
Reproduction environment: - JLine3 on x86_64 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 --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.
{
"affected": [
{
"package": {
"ecosystem": "Maven",
"name": "org.jline:jline-builtins"
},
"ranges": [
{
"events": [
{
"introduced": "4.0.0"
},
{
"fixed": "4.3.1"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "org.jline:jline-builtins"
},
"ranges": [
{
"events": [
{
"introduced": "3.0.0"
},
{
"fixed": "3.30.15"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-77422"
],
"database_specific": {
"cwe_ids": [
"CWE-1333"
],
"github_reviewed": true,
"github_reviewed_at": "2026-09-23T18:12:35Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "### Summary\n\nThe JLine3 built-in `grep` command wraps the user-supplied regular expression with\n`.*` before compiling it with Java\u0027s backtracking regex engine. This amplifies\ncatastrophic backtracking and allows a short pattern such as `(a+)+b` to hang the\ncommand thread on non-matching input. In environments that expose the JLine shell to\nremote users, this is a denial-of-service issue.\n\n### Details\n\nIn `builtins/src/main/java/org/jline/builtins/PosixCommands.java`, the grep\nimplementation rewrites the user pattern before compilation:\n\n```java\nString regex = args.remove(0);\nString regexp = regex;\nif (opt.isSet(\"word-regexp\")) {\n regexp = \"\\\\b\" + regexp + \"\\\\b\";\n}\nif (opt.isSet(\"line-regexp\")) {\n regexp = \"^\" + regexp + \"$\";\n} else {\n regexp = \".*\" + regexp + \".*\";\n}\n```\n\nThe transformed pattern is compiled with `Pattern.compile(...)` and then used to test\neach input line. For a payload such as `(a+)+b`, the automatic `.*` prefix and suffix\nincrease the backtracking search space substantially.\n\nAffected source location:\n- `builtins/src/main/java/org/jline/builtins/PosixCommands.java`\n- `grep(...)`\n\n### PoC\n\n1. Create a file containing a long run of `a` characters:\n\n```sh\nprintf \u0027aaaaaaaaaaaaaaaaaaaaaaa\\n\u0027 \u003e /tmp/testfile.txt\n```\n\n2. Run JLine3\u0027s built-in `grep` against that file:\n\n```sh\ngrep \u0027(a+)+b\u0027 /tmp/testfile.txt\n```\n\nExpected result:\n- The command stops responding.\n- The executing thread consumes high CPU.\n\nReproduction environment:\n- JLine3 on x86_64 Linux\n- OpenJDK 25.0.2\n\n### Impact\n\nThis is a denial-of-service vulnerability caused by catastrophic regex backtracking.\nAny application embedding `org.jline:jline-builtins` and exposing the built-in `grep`\ncommand is impacted. In remote shell deployments, an attacker can occupy a worker\nthread indefinitely and repeat the attack across multiple sessions to reduce service\navailability for other users.\n\n### Suggested Fix\n\nThe preferred fix for the current git head is:\n- stop rewriting non-line-regexp searches as `.*...*`\n- use `Matcher.find()` for substring semantics\n- compile user patterns with a linear-time engine such as RE2/J\n\nSuggested patch:\n\n```diff\ndiff --git a/builtins/pom.xml b/builtins/pom.xml\n--- a/builtins/pom.xml\n+++ b/builtins/pom.xml\n@@\n \u003cdependency\u003e\n+ \u003cgroupId\u003ecom.google.re2j\u003c/groupId\u003e\n+ \u003cartifactId\u003ere2j\u003c/artifactId\u003e\n+ \u003cversion\u003e1.8\u003c/version\u003e\n+ \u003c/dependency\u003e\n+ \u003cdependency\u003e\n \u003cgroupId\u003eorg.jline\u003c/groupId\u003e\n \u003cartifactId\u003ejline-reader\u003c/artifactId\u003e\n \u003c/dependency\u003e\n\ndiff --git a/builtins/src/main/java/org/jline/builtins/PosixCommands.java b/builtins/src/main/java/org/jline/builtins/PosixCommands.java\n--- a/builtins/src/main/java/org/jline/builtins/PosixCommands.java\n+++ b/builtins/src/main/java/org/jline/builtins/PosixCommands.java\n@@\n-import java.util.regex.Pattern;\n+import com.google.re2j.Pattern;\n@@\n if (opt.isSet(\"line-regexp\")) {\n regexp = \"^\" + regexp + \"$\";\n- } else {\n- regexp = \".*\" + regexp + \".*\";\n }\n@@\n- boolean m = p.matcher(line).matches();\n+ boolean m = opt.isSet(\"line-regexp\")\n+ ? p.matcher(line).matches()\n+ : p.matcher(line).find();\n```\n\n### Credits\n\nThis issue was identified by Micha\u0142 Majchrowicz and Marcin Wyczechowski, members of the AFINE Team.",
"id": "GHSA-r2xf-8xr9-62gw",
"modified": "2026-09-23T18:12:36Z",
"published": "2026-09-23T18:12:35Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/jline/jline3/security/advisories/GHSA-r2xf-8xr9-62gw"
},
{
"type": "WEB",
"url": "https://github.com/jline/jline3/pull/2012"
},
{
"type": "WEB",
"url": "https://github.com/jline/jline3/pull/2018"
},
{
"type": "WEB",
"url": "https://github.com/jline/jline3/commit/1d5fc3099e77938b971e197211cad2d4fbb17541"
},
{
"type": "WEB",
"url": "https://github.com/jline/jline3/commit/341ee69ccc57b7733c1b40d6993219b64b3206ae"
},
{
"type": "PACKAGE",
"url": "https://github.com/jline/jline3"
},
{
"type": "WEB",
"url": "https://github.com/jline/jline3/releases/tag/4.3.1"
},
{
"type": "WEB",
"url": "https://github.com/jline/jline3/releases/tag/jline-3.30.15"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
],
"summary": "JLine: ReDoS in Built-in grep Command Amplified by Automatic `.*` Wrapping"
}
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
Related by attack behaviour
Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.