Skip to content

[backport jline-3.x] fix: guard regex matching against catastrophic backtracking (ReDoS)#2018

Merged
gnodet merged 1 commit into
jline:jline-3.xfrom
gnodet:backport/2012-to-jline-3.x
Jun 30, 2026
Merged

[backport jline-3.x] fix: guard regex matching against catastrophic backtracking (ReDoS)#2018
gnodet merged 1 commit into
jline:jline-3.xfrom
gnodet:backport/2012-to-jline-3.x

Conversation

@gnodet

@gnodet gnodet commented Jun 30, 2026

Copy link
Copy Markdown
Member

Backport of #2012

Cherry-pick of #2012 onto jline-3.x.

Original PR: #2012 - fix: guard regex matching against catastrophic backtracking (ReDoS)
Original author: @gnodet
Target branch: jline-3.x

Original description

Add SafeRegex utility that wraps regex input in a TimeoutCharSequence
to enforce a wall-clock deadline during matching. Java's backtracking
NFA engine can take exponential time on patterns with nested quantifiers
(e.g. (a+)+b); the wrapper checks System.nanoTime() every 1024 charAt()
calls and throws RegexTimeoutException if the deadline is exceeded.

Fixed 8 locations where user-controlled input was matched as a regex
without protection:

  • Less: search and display-filter matching
  • Nano: regex search mode
  • grep: removed unsafe .* wrapping, use find() instead of matches()
  • Commands (history -m): glob pattern now uses SafeRegex.compileGlob()
  • DefaultHistory (HISTORY_IGNORE): glob patterns properly quoted
  • LineReaderImpl: Ctrl-R/Ctrl-S search and history suggestion matching
  • AttributedString.styleMatches: search highlight rendering

Addresses GHSA-r2xf-8xr9-62gw, GHSA-2v9w-34q6-wpqx,
GHSA-ph9c-7hw9-vhhw, GHSA-5q95-hrpc-m3w3.

Add SafeRegex utility that wraps regex input in a TimeoutCharSequence
to enforce a wall-clock deadline during matching. Java's backtracking
NFA engine can take exponential time on patterns with nested quantifiers
(e.g. (a+)+b); the wrapper checks System.nanoTime() every 1024 charAt()
calls and throws RegexTimeoutException if the deadline is exceeded.

Fixed 8 locations where user-controlled input was matched as a regex
without protection:
- Less: search and display-filter matching
- Nano: regex search mode
- grep: removed unsafe .* wrapping, use find() instead of matches()
- Commands (history -m): glob pattern now uses SafeRegex.compileGlob()
- DefaultHistory (HISTORY_IGNORE): glob patterns properly quoted
- LineReaderImpl: Ctrl-R/Ctrl-S search and history suggestion matching
- AttributedString.styleMatches: search highlight rendering

Addresses GHSA-r2xf-8xr9-62gw, GHSA-2v9w-34q6-wpqx,
GHSA-ph9c-7hw9-vhhw, GHSA-5q95-hrpc-m3w3.

Closes jline#2012
@gnodet gnodet added the bug label Jun 30, 2026
@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 59622cb7-0e1e-4126-a650-befda4cd7357

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sonarqubecloud

Copy link
Copy Markdown

@augmentcode

augmentcode Bot commented Jun 30, 2026

Copy link
Copy Markdown
🤖 Augment PR Summary

Summary: Backport of the jline-3.x security hardening for regex matching to mitigate catastrophic backtracking (ReDoS).

Changes:

  • Added SafeRegex utility that wraps inputs in a timeout-enforcing CharSequence and provides safe matcher/matches/find helpers.
  • Added RegexTimeoutException (unchecked) for signaling deadline expiration from within charAt.
  • Updated Less search + display-filter checks to use SafeRegex.find.
  • Updated Nano regex search to use SafeRegex.matcher and tolerate timeouts (returning partial matches).
  • Updated grep to avoid unsafe .* wrapping and to use SafeRegex for matching/highlighting.
  • Updated history matching (history -m, HISTORY_IGNORE, Ctrl-R/Ctrl-S, suggestions) to quote user input and/or use safe matching with timeouts.
  • Updated AttributedString.styleMatches to avoid UI hangs by applying styles with timeout protection.

Technical Notes: The timeout is enforced via a wall-clock deadline checked periodically during charAt() calls, preventing untrusted patterns/inputs from stalling interactive operations.

🤖 Was this summary useful? React with 👍 or 👎

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 1 suggestion posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

/**
* Compile a glob-style pattern into a {@link Pattern}.
*
* <p>Only {@code *} (match any string) and {@code \} (escape) are

@augmentcode augmentcode Bot Jun 30, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SafeRegex.compileGlob(..., flags) documents that “every other character is regex-quoted so it matches literally”, but if callers pass Pattern.COMMENTS then unescaped whitespace and # won’t be treated literally (which can change glob semantics). Consider documenting that COMMENTS isn’t supported here (or ensuring literals remain literal under that flag).

Severity: low

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

@gnodet gnodet merged commit 341ee69 into jline:jline-3.x Jun 30, 2026
13 checks passed
@gnodet gnodet deleted the backport/2012-to-jline-3.x branch June 30, 2026 19:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant