JLine3 Telnet server: Unauthenticated Remote Memory Exhaustion via Unbounded Telnet NEW-ENVIRON VariablesGHSA-47qp-hqvx-6r3f
HIGHFix: jline/jline3#2000GHSA-47qp-hqvx-6r3f is a high-severity (CVSS 7.5) Uncontrolled Resource Consumption vulnerability in org.jline:jline-remote-telnet. A fix is available for org.jline:jline-remote-telnet — see the affected versions and patch details below.
Exploitation Status
Proof-of-concept exploit code exists
- CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
- CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.
Exploitation and automatability from CISA’s SSVC triage for GHSA-47qp-hqvx-6r3f.
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
How urgent is this, really
GHSA-47qp-hqvx-6r3f by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.
Where this sits among everything scored
Of 390,400 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.
Real-World Exposure
org.jline:jline-remote-telnet☕org.jline:jline-remote-telnet☕org.jline:jline-remote-telnetReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects Maven packages — download data is not available via public APIs for these ecosystems.
Description
Summary
The JLine3 Telnet server (remote-telnet module) does not limit the number of
environment variables a client may inject via the Telnet NEW-ENVIRON option. An
unauthenticated attacker can flood the server with a large number of unique
variable pairs before sending the terminating IAC SE byte, exhausting JVM heap
memory and causing an OutOfMemoryError (denial of service). Approximately 3–4 MB of
network traffic is sufficient to consume a 512 MB JVM heap.
Details
TelnetIO.readNEVariables() (TelnetIO.java:1127-1180) processes incoming NEW-ENVIRON
variable pairs in a loop and stores each pair in a HashMap held by ConnectionData:
// TelnetIO.java:1139-1178
boolean cont = true;
if (i == NE_VAR || i == NE_USERVAR) {
do {
switch (readNEVariableName(sbuf)) {
case NE_VAR_OK:
TelnetIO.this.connectionData.getEnvironment().put(str, sbuf.toString());
// ← no per-connection count limit
break;
case NE_VAR_UNDEFINED:
break; // cont remains true, loop continues
}
} while (cont); // cont is never set to false; only exits via return
}
The variable accumulator map is a plain HashMap initialized with capacity 20 and
no maximum size:
// ConnectionData.java:98
environment = new HashMap<String, String>(20);
Per-variable limits exist (name: max 50 chars, value: max 1000 chars), but there is no
cap on the count of variables. Each map entry occupies approximately 2 KB of heap
(String headers + Map.Entry + backing char arrays). On a JVM with a 512 MB heap,
approximately 250,000 unique entries trigger an OutOfMemoryError.
Network cost: using sequential 1-byte names (e.g., \x01, \x02, ...) and 1-byte
values, each variable pair requires roughly 13 protocol bytes. Sending 250,000 pairs
requires only ~3.25 MB of network traffic — feasible in seconds over any reasonable
network connection.
No authentication is required. NEW-ENVIRON negotiation occurs before login.
Affected source files:
remote-telnet/src/main/java/org/jline/builtins/telnet/TelnetIO.javalines 1127-1180remote-telnet/src/main/java/org/jline/builtins/telnet/ConnectionData.javaline 98
PoC
Connect to the JLine3 Telnet server and, after completing WILL/DO option negotiation, send a NEW-ENVIRON SEND subneg followed by a single large IS subneg containing thousands of unique variable pairs before the final IAC SE.
Protocol structure (no authentication required):
- Standard Telnet option negotiation (IAC DO NEW-ENVIRON, IAC WILL NEW-ENVIRON)
- Server sends IAC SB NEW-ENVIRON SEND IAC SE
- Client responds with: IAC SB NEW-ENVIRON IS [NE_VAR 0x01 NE_VALUE 0x01] ← variable pair 1 [NE_VAR 0x02 NE_VALUE 0x01] ← variable pair 2 ... repeated N times ... IAC SE ← only sent after N pairs
Each iteration adds one entry to the per-connection environment map. The connection thread blocks reading from the socket while accumulating pairs, so the attacker controls the timing of the OOM.
Reproduction environment:
- JLine3 built from current master on x86_64 Linux, OpenJDK 25.0.2
remote-telnetmodule started with its default configuration- Confirmed by source-code analysis; loop exit condition and missing count guard
verified by inspection of
readNEVariables()andConnectionDataconstructor
Impact
Type: Denial of Service (heap memory exhaustion / OutOfMemoryError)
Who is affected: Any application embedding the JLine3 remote-telnet module and
exposing its Telnet server. No credentials are required. A single connection can exhaust
the entire JVM heap, crashing the host process or triggering JVM out-of-memory
handling that impacts all users sharing that JVM instance.
Credits
This issue was identified by Michał Majchrowicz and Marcin Wyczechowski, members of the AFINE Team.
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| ☕Maven | org.jline:jline-remote-telnet | ≥ 4.1.0&&< 4.2.1 | 4.2.1org.jline:jline-remote-telnet:4.2.1 |
| ☕Maven | org.jline:jline-remote-telnet | ≥ 4.0.0&&< 4.0.16 | 4.0.16org.jline:jline-remote-telnet:4.0.16 |
| ☕Maven | org.jline:jline-remote-telnet | all versions | 3.30.14org.jline:jline-remote-telnet:3.30.14 |
Affected Products
jlinejlineDetection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for org.jline:jline-remote-telnet, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update org.jline:jline-remote-telnet to 4.2.1 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-47qp-hqvx-6r3f is resolved across your whole dependency graph.
Workarounds
Cap what an attacker can consume: apply request size, rate and timeout limits in front of the affected component, and run it with memory and CPU limits so exhaustion degrades one worker rather than the whole service.
Fixing This On Your OS
If you run this on a Linux distribution, patch through your package manager against the distro's own security advisory below — it tracks the exact backported fix for your release, which can ship on a different timeline (and sometimes a different severity) than the upstream project.
This is a denial of service vulnerability in the JLine3 Telnet server module. An unauthenticated remote attacker can exploit this flaw by injecting excessive environment variables, leading to JVM heap memory exhaustion and a denial of service in applications that expose this vulnerable Telnet server functionality.
To mitigate this issue, restrict network access to applications that expose the JLine3 Telnet server module. If the Telnet server functionality is not required, consider disabling the JLine3 remote-telnet module within the affected application's configuration. Consult application-specific documentation for instructions on disabling or configuring the Telnet server. A restart of the affected application or service may be required for changes to take effect.Source: Red Hat security advisory for GHSA-47qp-hqvx-6r3f (CC BY 4.0)
Frequently Asked Questions
Is GHSA-47qp-hqvx-6r3f in your dependencies?
Find it across Maven, including transitive dependencies.