Skip to content

Commit 50d2b8f

Browse files
author
Tim te Beek
committed
Validate checksum HTTP responses and hex input
`Checksum.fromUri()` did not check the HTTP response status before parsing the body as hex. When a proxy, CDN, or missing endpoint returned an HTML/XML error page, `fromHex()` threw a cryptic `NumberFormatException: For input string: "<?"`. - Check `response.isSuccessful()` in `fromUri()` before parsing - Trim response body to handle trailing newlines in checksum files - Validate hex characters in `fromHex()` with a clear error message - Catch failures in `DistributionInfos.fetchChecksum()` and return null so the recipe proceeds without checksum verification Fixes #6762
1 parent 8c01766 commit 50d2b8f

3 files changed

Lines changed: 23 additions & 3 deletions

File tree

rewrite-core/src/main/java/org/openrewrite/Checksum.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import java.io.IOException;
2727
import java.io.InputStream;
28+
import java.io.UncheckedIOException;
2829
import java.net.URI;
2930
import java.nio.charset.StandardCharsets;
3031
import java.nio.file.Files;
@@ -53,6 +54,15 @@ public static Checksum fromHex(String algorithm, String hex) {
5354
if (hex.length() % 2 != 0) {
5455
throw new IllegalArgumentException("Hex string must contain a set of hex pairs (length divisible by 2).");
5556
}
57+
for (int i = 0; i < hex.length(); i++) {
58+
char c = hex.charAt(i);
59+
if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) {
60+
throw new IllegalArgumentException(
61+
"Input is not valid hexadecimal at position " + i + ": '" +
62+
hex.substring(0, Math.min(hex.length(), 40)) +
63+
(hex.length() > 40 ? "..." : "") + "'");
64+
}
65+
}
5666

5767
byte[] value = new byte[hex.length() / 2];
5868
for (int i = 0; i < value.length; i++) {
@@ -83,7 +93,11 @@ public static Checksum fromUri(HttpSender httpSender, URI uri, String algorithm)
8393
.withMethod(HttpSender.Method.GET)
8494
.build();
8595
try (HttpSender.Response response = httpSender.send(request)) {
86-
String hexString = new String(response.getBodyAsBytes(), StandardCharsets.UTF_8);
96+
if (!response.isSuccessful()) {
97+
throw new UncheckedIOException(new IOException(
98+
"Failed to download checksum from " + uri + ": HTTP " + response.getCode()));
99+
}
100+
String hexString = new String(response.getBodyAsBytes(), StandardCharsets.UTF_8).trim();
87101
return Checksum.fromHex(algorithm, hexString);
88102
}
89103
}

rewrite-core/src/test/java/org/openrewrite/ChecksumTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ void fromHexWithValidInput() {
3636

3737
@Test
3838
void fromHexRejectsNonHexInput() {
39-
assertThatThrownBy(() -> Checksum.fromHex("SHA-256", "<?xml version"))
39+
assertThatThrownBy(() -> Checksum.fromHex("SHA-256", "<?"))
4040
.isInstanceOf(IllegalArgumentException.class)
4141
.hasMessageContaining("not valid hexadecimal");
4242
}

rewrite-gradle/src/main/java/org/openrewrite/gradle/util/DistributionInfos.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.openrewrite.ipc.http.HttpSender;
2424

2525
import java.io.IOException;
26+
import java.io.UncheckedIOException;
2627
import java.net.URI;
2728

2829
@Value
@@ -47,7 +48,12 @@ public static DistributionInfos fetch(GradleWrapper.GradleVersion gradleVersion,
4748
return new DistributionInfos(gradleVersion.getDownloadUrl(), checksum, jarChecksum);
4849
}
4950

51+
@Nullable
5052
private static Checksum fetchChecksum(HttpSender httpSender, String checksumUrl) {
51-
return Checksum.fromUri(httpSender, URI.create(checksumUrl));
53+
try {
54+
return Checksum.fromUri(httpSender, URI.create(checksumUrl));
55+
} catch (UncheckedIOException | IllegalArgumentException e) {
56+
return null;
57+
}
5258
}
5359
}

0 commit comments

Comments
 (0)