{"id":"GHSA-2r2c-cx56-8933","summary":"JLine3 Telnet server: Unauthenticated Remote DoS via Unbounded Telnet NAWS Terminal Geometry","details":"### Summary\n\nThe JLine3 Telnet server (`remote-telnet` module) does not apply an upper bound to\nterminal dimensions received via the Telnet NAWS (Negotiate About Window Size) option.\nAn unauthenticated remote attacker can send a NAWS subnegotiation advertising a\n65535×65535 terminal and repeatedly alternate values to trigger continuous, expensive\nrendering work on the server, causing CPU exhaustion and denial of service.\n\n### Details\n\n`TelnetIO.handleNAWS()` (TelnetIO.java:856-879) reads the client-supplied width and\nheight as 16-bit unsigned integers and passes them to `setTerminalGeometry()`:\n\n```java\n// TelnetIO.java:869-875\nprivate void setTerminalGeometry(int columns, int rows) {\n    if (columns \u003c SMALLEST_BELIEVABLE_WIDTH) columns = DEFAULT_WIDTH;  // lower bound only\n    if (rows    \u003c SMALLEST_BELIEVABLE_HEIGHT) rows    = DEFAULT_HEIGHT;\n    connectionData.setTerminalGeometry(columns, rows);\n    connection.processConnectionEvent(\n        new ConnectionEvent(connection, ConnectionEvent.Type.CONNECTION_TERMINAL_GEOMETRY_CHANGED));\n}\n```\n\nOnly a *lower* bound is enforced (minimum 20 columns / 6 rows). Values up to 65535 are\naccepted and stored. The geometry change event propagates to Telnet.java:153-158 where\nit calls:\n\n    terminal.setSize(new Size(65535, 65535));\n    terminal.raise(Signal.WINCH);\n\nThe WINCH signal triggers `LineReaderImpl.handleSignal()` → `redisplay()`. Inside\n`redisplay()`, multiple paths iterate up to `size.getColumns()` times:\n\n- `freshLine()` (LineReaderImpl.java:937,953): loops `size.getColumns()-1` = **65534\n  iterations**, building and writing a space-padding string across the network socket.\n- `columnSplitLength(terminal, size.getColumns(), ...)`: called multiple times,\n  each processing all characters against the 65535-wide line width.\n\nBecause WINCH only fires on *change*, the attacker alternates between two large values\n(e.g., 65535 and 65534) to trigger an unlimited stream of expensive render cycles.\nNo authentication is required; the NAWS option is negotiated before any login sequence.\n\nAffected source files:\n- `remote-telnet/src/main/java/org/jline/builtins/telnet/TelnetIO.java` lines 856-879\n- `remote-telnet/src/main/java/org/jline/builtins/telnet/Telnet.java` lines 140-175\n- `reader/src/main/java/org/jline/reader/impl/LineReaderImpl.java` lines 929-962, 1293-1313\n\n### PoC\n\nSend the following two raw Telnet packets in a loop to a running JLine Telnet server.\nNo login or authentication is required.\n\nPacket 1 — NAWS 65535 × 65535:\n  FF FA 1F FF FF FF FF FF F0\n  (IAC SB NAWS 0xFF 0xFF 0xFF 0xFF IAC SE)\n\nPacket 2 — NAWS 65534 × 65534:\n  FF FA 1F FF FE FF FE FF F0\n  (IAC SB NAWS 0xFF 0xFE 0xFF 0xFE IAC SE)\n\nSending these alternately at ~10 packets/second is sufficient to peg one CPU core on\nthe server. The server remains in this state for as long as the connection is open.\n\nReproduction environment:\n- JLine3 built from current master on x86_64 Linux, OpenJDK 25.0.2\n- `remote-telnet` module started with its default `Telnet` server configuration\n- Test confirmed by source-code analysis and tracing the call chain at runtime\n\n### Impact\n\n**Type**: Denial of Service (CPU exhaustion)\n**Who is affected**: Any application that embeds the JLine3 `remote-telnet` module and\nexposes its Telnet server on a network interface. The attacker requires no credentials.\nA single connection making ~10 alternating NAWS packets per second fully occupies the\nconnection-handling thread and produces continuous I/O on the server's output stream.\nBecause connection threads are re-used for the life of the session, one attacker per\navailable connection slot can deny service to all users of that slot.\n\n### Credits\nThis issue was identified by Michał Majchrowicz and Marcin Wyczechowski, members of the AFINE Team.","aliases":["CVE-2026-56741"],"modified":"2026-09-01T21:15:07.249392335Z","published":"2026-06-18T13:07:16Z","database_specific":{"severity":"HIGH","github_reviewed":true,"github_reviewed_at":"2026-06-18T13:07:16Z","nvd_published_at":"2026-07-17T22:17:57Z","cwe_ids":["CWE-400"]},"references":[{"type":"WEB","url":"https://github.com/jline/jline3/security/advisories/GHSA-2r2c-cx56-8933"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-56741"},{"type":"WEB","url":"https://github.com/jline/jline3/pull/2000"},{"type":"WEB","url":"https://github.com/jline/jline3/commit/3ea9cad8699714dc072fade29d36be0d1e23d708"},{"type":"WEB","url":"https://github.com/jline/jline3/commit/733eb353dca7b0ea0252e724445b6defa29c393e"},{"type":"WEB","url":"https://github.com/jline/jline3/commit/86b7ba7801988aadb1a67555629522a71d603bd3"},{"type":"PACKAGE","url":"https://github.com/jline/jline3"},{"type":"WEB","url":"https://github.com/jline/jline3/releases/tag/4.0.16"},{"type":"WEB","url":"https://github.com/jline/jline3/releases/tag/4.2.1"}],"affected":[{"package":{"name":"org.jline:jline-remote-telnet","ecosystem":"Maven","purl":"pkg:maven/org.jline/jline-remote-telnet"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.1.0"},{"fixed":"4.2.1"}]}],"versions":["4.1.0","4.1.1","4.1.2","4.1.3","4.2.0"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/06/GHSA-2r2c-cx56-8933/GHSA-2r2c-cx56-8933.json"}},{"package":{"name":"org.jline:jline-remote-telnet","ecosystem":"Maven","purl":"pkg:maven/org.jline/jline-remote-telnet"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.0.0"},{"fixed":"4.0.16"}]}],"versions":["4.0.0","4.0.10","4.0.11","4.0.12","4.0.13","4.0.14","4.0.15","4.0.2","4.0.3","4.0.4","4.0.5","4.0.6","4.0.7","4.0.8","4.0.9"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/06/GHSA-2r2c-cx56-8933/GHSA-2r2c-cx56-8933.json"}},{"package":{"name":"org.jline:jline-remote-telnet","ecosystem":"Maven","purl":"pkg:maven/org.jline/jline-remote-telnet"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.30.14"}]}],"versions":["3.10.0","3.11.0","3.12.0","3.12.1","3.13.0","3.13.1","3.13.2","3.13.3","3.14.0","3.14.1","3.15.0","3.16.0","3.17.0","3.17.1","3.18.0","3.19.0","3.2.0","3.20.0","3.21.0","3.22.0","3.23.0","3.24.0","3.24.1","3.25.0","3.25.1","3.26.0","3.26.1","3.26.2","3.26.3","3.27.0","3.27.1","3.28.0","3.29.0","3.3.0","3.3.1","3.30.0","3.30.1","3.30.10","3.30.11","3.30.12","3.30.13","3.30.2","3.30.3","3.30.4","3.30.5","3.30.6","3.30.7","3.30.8","3.30.9","3.4.0","3.5.0","3.5.1","3.5.2","3.6.0","3.6.1","3.6.2","3.7.0","3.7.1","3.8.0","3.8.1","3.8.2","3.9.0"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/06/GHSA-2r2c-cx56-8933/GHSA-2r2c-cx56-8933.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"}]}