Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package jetty-minimal for openSUSE:Factory checked in at 2026-03-07 20:09:46 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/jetty-minimal (Old) and /work/SRC/openSUSE:Factory/.jetty-minimal.new.8177 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "jetty-minimal" Sat Mar 7 20:09:46 2026 rev:31 rq:1337383 version:9.4.58 Changes: -------- +++ only whitespace diff in changes, re-diffing jetty-http2.changes: same change --- /work/SRC/openSUSE:Factory/jetty-minimal/jetty-minimal.changes 2025-08-22 17:50:21.110318905 +0200 +++ /work/SRC/openSUSE:Factory/.jetty-minimal.new.8177/jetty-minimal.changes 2026-03-07 20:14:37.983539787 +0100 @@ -1,0 +2,8 @@ +Fri Mar 6 19:51:04 UTC 2026 - Fridrich Strba <[email protected]> + +- Added patch: + * jetty-CVE-2025-11143.patch + + upstream patch fixing bsc#1259242 (CVE-2025-11143): + Different parsing of invalid URIs + +------------------------------------------------------------------- +++ only whitespace diff in changes, re-diffing jetty-websocket.changes: same change New: ---- jetty-CVE-2025-11143.patch ----------(New B)---------- New:/work/SRC/openSUSE:Factory/.jetty-minimal.new.8177/jetty-minimal.changes-- Added patch: /work/SRC/openSUSE:Factory/.jetty-minimal.new.8177/jetty-minimal.changes: * jetty-CVE-2025-11143.patch /work/SRC/openSUSE:Factory/.jetty-minimal.new.8177/jetty-minimal.changes- + upstream patch fixing bsc#1259242 (CVE-2025-11143): ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ jetty-http2.spec: same change ++++++ jetty-minimal.spec ++++++ --- /var/tmp/diff_new_pack.i7qMUU/_old 2026-03-07 20:14:39.063584466 +0100 +++ /var/tmp/diff_new_pack.i7qMUU/_new 2026-03-07 20:14:39.075584962 +0100 @@ -29,6 +29,7 @@ URL: https://www.eclipse.org/jetty/ Source0: https://github.com/eclipse/%{base_name}.project/archive/%{base_name}-%{version}%{addver}.tar.gz#/%{src_name}.tar.gz Patch0: jetty-port-to-servlet-4.0.patch +Patch1: jetty-CVE-2025-11143.patch BuildRequires: fdupes BuildRequires: java-devel >= 1.8 BuildRequires: maven-local @@ -280,6 +281,7 @@ %prep %setup -q -n %{src_name} %patch -P 0 -p1 +%patch -P 1 -p1 find . -name "*.?ar" -exec rm {} \; find . -name "*.class" -exec rm {} \; jetty-websocket.spec: same change ++++++ _scmsync.obsinfo ++++++ --- /var/tmp/diff_new_pack.i7qMUU/_old 2026-03-07 20:14:39.183589430 +0100 +++ /var/tmp/diff_new_pack.i7qMUU/_new 2026-03-07 20:14:39.199590092 +0100 @@ -1,6 +1,6 @@ -mtime: 1757496743 -commit: e6f2dec02f7718dd849b0e17ce5f5d893fda223a993c280980397c29bad815dc +mtime: 1772826880 +commit: 64bb734a4ee0ad81241daf40660ce4a9bf318a05b767e68f7be27498e1869cc1 url: https://src.opensuse.org/java-packages/jetty-minimal.git -revision: e6f2dec02f7718dd849b0e17ce5f5d893fda223a993c280980397c29bad815dc +revision: 64bb734a4ee0ad81241daf40660ce4a9bf318a05b767e68f7be27498e1869cc1 projectscmsync: https://src.opensuse.org/java-packages/_ObsPrj ++++++ build.specials.obscpio ++++++ ++++++ build.specials.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/.gitignore new/.gitignore --- old/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/.gitignore 2026-03-06 20:55:21.000000000 +0100 @@ -0,0 +1 @@ +.osc ++++++ jetty-CVE-2025-11143.patch ++++++ --- a/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpSenderOverHTTP.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpSenderOverHTTP.java @@ -198,7 +198,9 @@ public HeadersCallback(HttpExchange exchange, HttpContent content, Callback call String query = request.getQuery(); if (query != null) path += "?" + query; - metaData = new MetaData.Request(request.getMethod(), new HttpURI(path), request.getVersion(), request.getHeaders(), contentLength); + HttpURI uri = new HttpURI(); + uri.parseRequestTarget(request.getMethod(), path); + metaData = new MetaData.Request(request.getMethod(), uri, request.getVersion(), request.getHeaders(), contentLength); metaData.setTrailerSupplier(request.getTrailers()); if (!expects100Continue(request)) --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java @@ -433,7 +433,8 @@ private void parse(State state, final String uri, final int offset, final int en switch (c) { case '/': - mark = i; + pathMark = mark = i; + segment = mark + 1; state = State.HOST_OR_PATH; break; case ';': @@ -471,6 +472,8 @@ private void parse(State state, final String uri, final int offset, final int en pathMark = segment = i; state = State.PATH; break; + case ':': + throw new IllegalArgumentException("Bad Scheme"); default: mark = i; if (_scheme == null) @@ -491,7 +494,7 @@ private void parse(State state, final String uri, final int offset, final int en { case ':': // must have been a scheme - _scheme = uri.substring(mark, i); + _scheme = URIUtil.validateScheme(uri.substring(mark, i)); // Start again with scheme set state = State.START; break; @@ -596,8 +599,19 @@ private void parse(State state, final String uri, final int offset, final int en encoded = true; break; case '#': + case '?': case ';': - throw new IllegalArgumentException("Bad authority"); + if (encodedCharacters > 0) + throw new IllegalArgumentException("Bad authority"); + _host = uri.substring(mark, i); + if (_host.isEmpty()) + throw new IllegalArgumentException("Bad authority"); + encoded = false; + pathMark = mark = i; + segment = mark + 1; + state = State.PATH; + i--; + break; default: if (encodedCharacters > 0) @@ -621,8 +635,13 @@ else if (!isUnreservedPctEncodedOrSubDelim(c)) case '/': throw new IllegalArgumentException("No closing ']' for ipv6 in " + uri); case ']': - c = uri.charAt(++i); - _host = uri.substring(mark, i); + i++; + String host = uri.substring(mark, i); + URIUtil.validateInetAddress(host); + _host = host; + if (i == end) + break; + c = uri.charAt(i); if (c == ':') { mark = i + 1; @@ -637,7 +656,7 @@ else if (!isUnreservedPctEncodedOrSubDelim(c)) case ':': break; default: - if (!isHexDigit(c)) + if (!isHexDigit(c) && c != '.') throw new IllegalArgumentException("Bad authority"); break; } @@ -805,6 +824,7 @@ else if (c == '/') break; case SCHEME_OR_PATH: case HOST_OR_PATH: + checkSegment(uri, segment, end, false); _path = uri.substring(mark, end); break; case HOST: --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java @@ -38,6 +38,8 @@ import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; @@ -158,6 +160,19 @@ public void testAt() throws Exception assertEquals("/@foo/bar", uri.getPath()); } + /** + * Test of an HttpURI of just a "/". + */ + @Test + public void testFromSlash() + { + HttpURI uri = new HttpURI("/"); + assertFalse(uri.hasViolations()); + assertNull(uri.getScheme()); + assertNull(uri.getAuthority()); + assertEquals("/", uri.getPath()); + } + @Test public void testParams() throws Exception { @@ -684,6 +699,8 @@ public static Stream<Arguments> parseData() // Simple IPv6 host no port (default path) Arguments.of("http://[2001:db8::1]/", "http", "[2001:db8::1]", null, "/", null, null, null), + Arguments.of("http://[0:0:0:0:0:ffff:127.0.0.1]/", "http", "[0:0:0:0:0:ffff:127.0.0.1]", null, "/", null, null, null), + Arguments.of("http://[::ffff:127.0.0.1]/", "http", "[::ffff:127.0.0.1]", null, "/", null, null, null), // Scheme-less IPv6, host with port (default path) Arguments.of("//[2001:db8::1]:8080/", null, "[2001:db8::1]", "8080", "/", null, null, null), @@ -725,7 +742,8 @@ public void testParseString(String input, String scheme, String host, Integer po assertThat("[" + input + "] .param", httpUri.getParam(), is(param)); assertThat("[" + input + "] .query", httpUri.getQuery(), is(query)); assertThat("[" + input + "] .fragment", httpUri.getFragment(), is(fragment)); - assertThat("[" + input + "] .toString", httpUri.toString(), is(input)); + if (!input.contains(":ffff:127.0.0.1")) + assertThat("[" + input + "] .toString", httpUri.toString(), is(input)); } catch (URISyntaxException e) { @@ -758,7 +776,8 @@ public void testParseURI(String input, String scheme, String host, Integer port, HttpURI httpUri = new HttpURI(input); assertThat("[" + input + "] .scheme", httpUri.getScheme(), is(scheme)); - assertThat("[" + input + "] .host", httpUri.getHost(), is(host)); + if (!input.contains(":ffff:127.0.0.1")) + assertThat("[" + input + "] .host", httpUri.getHost(), is(host)); assertThat("[" + input + "] .port", httpUri.getPort(), is(port == null ? -1 : port)); assertThat("[" + input + "] .path", httpUri.getPath(), is(path)); assertThat("[" + input + "] .param", httpUri.getParam(), is(param)); @@ -871,6 +890,24 @@ public void testRelativePathWithAuthority() assertEquals("//host", uri.toString()); } + public static Stream<String> badSchemes() + { + return Stream.of( + "://host/path", + "\t://host/path", + " ://host/path", + "unknown^://host/path", + "http^://host/path" + ); + } + + @ParameterizedTest + @MethodSource("badSchemes") + public void testBadSchemes(String uri) + { + assertThrows(IllegalArgumentException.class, () -> new HttpURI(uri)); + } + public static Stream<String> badAuthorities() { return Stream.of( @@ -890,9 +927,11 @@ public static Stream<String> badAuthorities() "https://user@host:notport/path", "https://user:password@host:notport/path", "https://user @host.com/", - "https://user#@host.com/", "https://[notIpv6]/", - "https://bad[0::1::2::3::4]/" + "https://bad[0::1::2::3::4]/", + "http://[normal.com@]vulndetector.com/", + "http://normal.com[user@vulndetector].com/", + "http://normal.com[@]vulndetector.com/" ); } @@ -902,4 +941,41 @@ public void testBadAuthority(String uri) { assertThrows(IllegalArgumentException.class, () -> new HttpURI(uri)); } + + public static Stream<Arguments> authoritiesNoPath() + { + return Stream.of( + Arguments.of("http://good.com#@evil.com", "good.com", null, "@evil.com"), + Arguments.of("http://[email protected]", "good.com", "@evil.com", null) + ); + } + + @ParameterizedTest + @MethodSource("authoritiesNoPath") + public void testAuthorityNoPath(String uri, String authority, String query, String fragment) + { + HttpURI httpURI = new HttpURI(uri); + assertThat(httpURI.getAuthority(), is(authority)); + assertThat(httpURI.getPath(), is("")); + assertThat(httpURI.getQuery(), is(query)); + assertThat(httpURI.getFragment(), is(fragment)); + } + + public static Stream<Arguments> connectURIs() + { + return Stream.of( + Arguments.of("localhost:8080"), + Arguments.of("127.0.0.1:8080"), + Arguments.of("[::1]:8080") + ); + } + + @ParameterizedTest + @MethodSource("connectURIs") + public void testConnect(String authority) + { + HttpURI httpURI = new HttpURI(); + httpURI.parseRequestTarget(HttpMethod.CONNECT.asString(), authority); + assertThat(httpURI.getAuthority(), is(authority)); + } } --- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/NcsaRequestLogTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/NcsaRequestLogTest.java @@ -358,9 +358,9 @@ public void testUseragentWithout(String logType) throws Exception setup(logType); testHandlerServerStart(); - _connector.getResponse("GET http://[:1]/foo HTTP/1.1\nReferer: http://other.site\n\n"); + _connector.getResponse("GET http://[::1]/foo HTTP/1.1\nReferer: http://other.site\n\n"); String log = _entries.poll(5, TimeUnit.SECONDS); - assertThat(log, containsString("GET http://[:1]/foo ")); + assertThat(log, containsString("GET http://[::1]/foo ")); assertThat(log, containsString(" 400 50 \"http://other.site\" \"-\"")); } @@ -371,9 +371,9 @@ public void testUseragentWith(String logType) throws Exception setup(logType); testHandlerServerStart(); - _connector.getResponse("GET http://[:1]/foo HTTP/1.1\nReferer: http://other.site\nUser-Agent: Mozilla/5.0 (test)\n\n"); + _connector.getResponse("GET http://[::1]/foo HTTP/1.1\nReferer: http://other.site\nUser-Agent: Mozilla/5.0 (test)\n\n"); String log = _entries.poll(5, TimeUnit.SECONDS); - assertThat(log, containsString("GET http://[:1]/foo ")); + assertThat(log, containsString("GET http://[::1]/foo ")); assertThat(log, containsString(" 400 50 \"http://other.site\" \"Mozilla/5.0 (test)\"")); } --- a/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java @@ -18,6 +18,7 @@ package org.eclipse.jetty.util; +import java.net.InetAddress; import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.Charset; @@ -1345,6 +1346,74 @@ public static URI addPath(URI uri, String path) return URI.create(buf.toString()); } + private static boolean isHexDigit(char c) + { + return (((c >= 'a') && (c <= 'f')) || // ALPHA (lower) + ((c >= 'A') && (c <= 'F')) || // ALPHA (upper) + ((c >= '0') && (c <= '9'))); + } + + /** + * Validate an IPv4 or IPv6 address. + * @param inetAddress the address to validate + * @throws IllegalArgumentException if the address is not valid + */ + public static void validateInetAddress(String inetAddress) + { + try + { + InetAddress ignored = InetAddress.getByName(inetAddress); + } + catch (Throwable e) + { + throw new IllegalArgumentException("Bad [IPv6] address", e); + } + } + + /** + * Validate and normalize the scheme, + * + * @param scheme The scheme to normalize + * @return The normalized version of the scheme + * @throws IllegalArgumentException If the scheme is not valid + */ + public static String validateScheme(String scheme) + { + if (scheme == null || scheme.isEmpty()) + throw new IllegalArgumentException("Bad scheme"); + + // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + StringBuilder toLowerCase = null; + for (int i = 0; i < scheme.length(); i++) + { + char c = scheme.charAt(i); + if (c >= 'A' && c <= 'Z') + { + if (toLowerCase == null) + { + toLowerCase = new StringBuilder(scheme.length()); + toLowerCase.append(scheme, 0, i); + } + toLowerCase.append(Character.toLowerCase(c)); + } + else if (c >= 'a' && c <= 'z' || + (i > 0 && (c >= '0' && c <= '9' || + c == '.' || + c == '+' || + c == '-'))) + { + if (toLowerCase != null) + toLowerCase.append(c); + } + else + { + throw new IllegalArgumentException("Bad scheme"); + } + } + + return toLowerCase == null ? scheme : toLowerCase.toString(); + } + /** * Combine two query strings into one. Each query string should not contain the beginning '?' character, but * may contain multiple parameters separated by the '{@literal &}' character.
