GHSA-5Q95-HRPC-M3W3

Vulnerability from github – Published: 2026-09-23 18:12 – Updated: 2026-09-23 18:12
VLAI
Summary
JLine: ReDoS via `HISTORY_IGNORE` Configuration Variable
Details

Summary

The JLine3 HISTORY_IGNORE variable is converted into a Java regular expression with only partial escaping. As a result, regex metacharacters other than * and : are passed through to the regex engine. A crafted value such as (a+)+b can cause catastrophic backtracking each time a command line is added to history, hanging the reader thread at high CPU.

Details

In reader/src/main/java/org/jline/reader/impl/history/DefaultHistory.java, matchPatterns() converts HISTORY_IGNORE into a regex:

for (int i = 0; i < patterns.length(); i++) {
    char ch = patterns.charAt(i);
    if (ch == '\\') {
        ch = patterns.charAt(++i);
        sb.append(ch);
    } else if (ch == ':') {
        sb.append('|');
    } else if (ch == '*') {
        sb.append('.').append('*');
    } else {
        sb.append(ch);
    }
}
return line.matches(sb.toString());

This logic translates wildcard syntax but does not escape regex metacharacters such as (, ), +, ?, {, }, [, and ]. Those characters therefore reach the Java regex engine unchanged.

Affected source location: - reader/src/main/java/org/jline/reader/impl/history/DefaultHistory.java - matchPatterns(String patterns, String line)

PoC

  1. Configure HISTORY_IGNORE to a malicious pattern, for example:
set history-ignore "(a+)+b"
  1. At the JLine prompt, enter a long non-matching line:
aaaaaaaaaaaaaaaaaaaaaaaaaaax
  1. Press Enter.

Expected result: - The prompt does not return. - The reader 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. Applications embedding org.jline:jline-reader are impacted if they allow HISTORY_IGNORE to be configured through user configuration or application settings. The issue is lower severity than the interactive editor findings because the attacker must control configuration, but it can still reliably hang a reader session.

Suggested Fix

The safest fix for the current git head is to stop treating arbitrary HISTORY_IGNORE content as a regex. Instead, escape all characters by default and translate only the intended JLine wildcard syntax (*) and separator syntax (:).

Suggested patch:

diff --git a/reader/src/main/java/org/jline/reader/impl/history/DefaultHistory.java b/reader/src/main/java/org/jline/reader/impl/history/DefaultHistory.java
--- a/reader/src/main/java/org/jline/reader/impl/history/DefaultHistory.java
+++ b/reader/src/main/java/org/jline/reader/impl/history/DefaultHistory.java
@@
         StringBuilder sb = new StringBuilder();
         for (int i = 0; i < patterns.length(); i++) {
             char ch = patterns.charAt(i);
             if (ch == '\\') {
                 ch = patterns.charAt(++i);
-                sb.append(ch);
+                sb.append(Pattern.quote(Character.toString(ch)));
             } else if (ch == ':') {
                 sb.append('|');
             } else if (ch == '*') {
                 sb.append('.').append('*');
             } else {
-                sb.append(ch);
+                sb.append(Pattern.quote(Character.toString(ch)));
             }
         }
         return line.matches(sb.toString());

Credits

This issue was identified by Michał Majchrowicz and Marcin Wyczechowski, members of the AFINE Team.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Maven",
        "name": "org.jline:jline-reader"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "4.0.0"
            },
            {
              "fixed": "4.3.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Maven",
        "name": "org.jline:jline-reader"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "3.0.0"
            },
            {
              "fixed": "3.30.15"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-77420"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1333"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-09-23T18:12:05Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "### Summary\n\nThe JLine3 `HISTORY_IGNORE` variable is converted into a Java regular expression with\nonly partial escaping. As a result, regex metacharacters other than `*` and `:` are\npassed through to the regex engine. A crafted value such as `(a+)+b` can cause\ncatastrophic backtracking each time a command line is added to history, hanging the\nreader thread at high CPU.\n\n### Details\n\nIn `reader/src/main/java/org/jline/reader/impl/history/DefaultHistory.java`,\n`matchPatterns()` converts `HISTORY_IGNORE` into a regex:\n\n```java\nfor (int i = 0; i \u003c patterns.length(); i++) {\n    char ch = patterns.charAt(i);\n    if (ch == \u0027\\\\\u0027) {\n        ch = patterns.charAt(++i);\n        sb.append(ch);\n    } else if (ch == \u0027:\u0027) {\n        sb.append(\u0027|\u0027);\n    } else if (ch == \u0027*\u0027) {\n        sb.append(\u0027.\u0027).append(\u0027*\u0027);\n    } else {\n        sb.append(ch);\n    }\n}\nreturn line.matches(sb.toString());\n```\n\nThis logic translates wildcard syntax but does not escape regex metacharacters such as\n`(`, `)`, `+`, `?`, `{`, `}`, `[`, and `]`. Those characters therefore reach the Java\nregex engine unchanged.\n\nAffected source location:\n- `reader/src/main/java/org/jline/reader/impl/history/DefaultHistory.java`\n- `matchPatterns(String patterns, String line)`\n\n### PoC\n\n1. Configure `HISTORY_IGNORE` to a malicious pattern, for example:\n\n```sh\nset history-ignore \"(a+)+b\"\n```\n\n2. At the JLine prompt, enter a long non-matching line:\n\n```text\naaaaaaaaaaaaaaaaaaaaaaaaaaax\n```\n\n3. Press Enter.\n\nExpected result:\n- The prompt does not return.\n- The reader 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.\nApplications embedding `org.jline:jline-reader` are impacted if they allow\n`HISTORY_IGNORE` to be configured through user configuration or application settings.\nThe issue is lower severity than the interactive editor findings because the attacker\nmust control configuration, but it can still reliably hang a reader session.\n\n### Suggested Fix\n\nThe safest fix for the current git head is to stop treating arbitrary `HISTORY_IGNORE`\ncontent as a regex. Instead, escape all characters by default and translate only the\nintended JLine wildcard syntax (`*`) and separator syntax (`:`).\n\nSuggested patch:\n\n```diff\ndiff --git a/reader/src/main/java/org/jline/reader/impl/history/DefaultHistory.java b/reader/src/main/java/org/jline/reader/impl/history/DefaultHistory.java\n--- a/reader/src/main/java/org/jline/reader/impl/history/DefaultHistory.java\n+++ b/reader/src/main/java/org/jline/reader/impl/history/DefaultHistory.java\n@@\n         StringBuilder sb = new StringBuilder();\n         for (int i = 0; i \u003c patterns.length(); i++) {\n             char ch = patterns.charAt(i);\n             if (ch == \u0027\\\\\u0027) {\n                 ch = patterns.charAt(++i);\n-                sb.append(ch);\n+                sb.append(Pattern.quote(Character.toString(ch)));\n             } else if (ch == \u0027:\u0027) {\n                 sb.append(\u0027|\u0027);\n             } else if (ch == \u0027*\u0027) {\n                 sb.append(\u0027.\u0027).append(\u0027*\u0027);\n             } else {\n-                sb.append(ch);\n+                sb.append(Pattern.quote(Character.toString(ch)));\n             }\n         }\n         return line.matches(sb.toString());\n```\n\n### Credits\n\nThis issue was identified by Micha\u0142 Majchrowicz and Marcin Wyczechowski, members of the AFINE Team.",
  "id": "GHSA-5q95-hrpc-m3w3",
  "modified": "2026-09-23T18:12:06Z",
  "published": "2026-09-23T18:12:05Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/jline/jline3/security/advisories/GHSA-5q95-hrpc-m3w3"
    },
    {
      "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:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "JLine: ReDoS via `HISTORY_IGNORE` Configuration Variable"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

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.

Loading…

Loading…

Loading…

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.


Loading…