Skip to content

Commit 417c502

Browse files
committed
fix: authenticate checksum fetching from remote
1 parent 180bb76 commit 417c502

1 file changed

Lines changed: 48 additions & 10 deletions

File tree

maven_plugin/src/main/java/io/github/chains_project/maven_lockfile/checksum/RemoteChecksumCalculator.java

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
import java.net.http.HttpClient;
99
import java.net.http.HttpRequest;
1010
import java.net.http.HttpResponse;
11+
import java.nio.charset.StandardCharsets;
1112
import java.security.MessageDigest;
1213
import java.util.ArrayList;
14+
import java.util.Base64;
1315
import java.util.Collection;
1416
import java.util.List;
1517
import java.util.Locale;
@@ -91,8 +93,8 @@ private Optional<String> calculateChecksumInternal(Artifact artifact, ProjectBui
9193

9294
PluginLogManager.getLog().debug(String.format("Checking: %s", checksumUrl));
9395

94-
HttpRequest checksumRequest =
95-
HttpRequest.newBuilder().uri(URI.create(checksumUrl)).build();
96+
HttpRequest checksumRequest = addAuth(HttpRequest.newBuilder().uri(URI.create(checksumUrl)), repository)
97+
.build();
9698
HttpResponse<String> checksumResponse =
9799
httpClient.send(checksumRequest, HttpResponse.BodyHandlers.ofString());
98100

@@ -103,8 +105,8 @@ private Optional<String> calculateChecksumInternal(Artifact artifact, ProjectBui
103105
}
104106

105107
if (checksumResponse.statusCode() == 404) {
106-
HttpRequest artifactRequest = HttpRequest.newBuilder()
107-
.uri(URI.create(artifactUrl))
108+
HttpRequest artifactRequest = addAuth(
109+
HttpRequest.newBuilder().uri(URI.create(artifactUrl)), repository)
108110
.build();
109111
HttpResponse<byte[]> artifactResponse =
110112
httpClient.send(artifactRequest, HttpResponse.BodyHandlers.ofByteArray());
@@ -137,8 +139,9 @@ private Optional<String> calculateChecksumInternal(Artifact artifact, ProjectBui
137139
"Falling back to HTTP to find download integrity sha1 for %s",
138140
artifact.getId()));
139141
try {
140-
HttpRequest artifactVerificationRequest = HttpRequest.newBuilder()
141-
.uri(URI.create(artifactUrl + ".sha1"))
142+
HttpRequest artifactVerificationRequest = addAuth(
143+
HttpRequest.newBuilder().uri(URI.create(artifactUrl + ".sha1")),
144+
repository)
142145
.build();
143146
HttpResponse<String> artifactVerificationResponse = httpClient.send(
144147
artifactVerificationRequest, HttpResponse.BodyHandlers.ofString());
@@ -194,11 +197,16 @@ private Optional<String> calculateChecksumInternal(Artifact artifact, ProjectBui
194197
checksumCache.put(cacheKey, checksum);
195198
return Optional.of(checksum);
196199
}
200+
// Non-2xx, non-404: likely an authentication or server error — do not silently skip
201+
PluginLogManager.getLog()
202+
.warn(String.format(
203+
"HTTP %d fetching checksum from %s — verify credentials in settings.xml for repository '%s'",
204+
checksumResponse.statusCode(), checksumUrl, repository.getId()));
197205
}
198206

199207
PluginLogManager.getLog()
200208
.warn(String.format(
201-
"Artifact checksum `%s.%s` not found among remote repositories.",
209+
"Artifact checksum `%s.%s` not found in any configured remote repository.",
202210
artifact, checksumAlgorithm));
203211
checksumCache.put(cacheKey, "");
204212
return Optional.empty();
@@ -238,9 +246,11 @@ private Optional<RepositoryInformation> getResolvedFieldInternal(
238246

239247
PluginLogManager.getLog().debug(String.format("Checking: %s", url));
240248

241-
HttpRequest request = HttpRequest.newBuilder()
242-
.uri(URI.create(url))
243-
.method("HEAD", HttpRequest.BodyPublishers.noBody())
249+
HttpRequest request = addAuth(
250+
HttpRequest.newBuilder()
251+
.uri(URI.create(url))
252+
.method("HEAD", HttpRequest.BodyPublishers.noBody()),
253+
repository)
244254
.build();
245255
HttpResponse<Void> response = httpClient.send(request, HttpResponse.BodyHandlers.discarding());
246256

@@ -263,6 +273,34 @@ private Optional<RepositoryInformation> getResolvedFieldInternal(
263273
}
264274
}
265275

276+
/**
277+
* Adds HTTP Basic authentication credentials to the request builder if the repository has
278+
* authentication configured. Maven decrypts settings.xml server passwords before plugin
279+
* execution, so {@code repository.getAuthentication()} already contains plaintext credentials.
280+
*
281+
* @throws IllegalStateException if credentials are configured but the repository URL does not
282+
* use HTTPS, to prevent credential exposure over an unencrypted connection.
283+
*/
284+
private HttpRequest.Builder addAuth(HttpRequest.Builder builder, ArtifactRepository repository) {
285+
var auth = repository.getAuthentication();
286+
if (auth != null && auth.getUsername() != null && !auth.getUsername().isEmpty()) {
287+
if (!repository.getUrl().toLowerCase(Locale.ROOT).startsWith("https://")) {
288+
throw new IllegalStateException(
289+
"Repository '" + repository.getId() + "' has credentials configured but uses a plain HTTP URL ("
290+
+ repository.getUrl()
291+
+ "). Refusing to send credentials over an unencrypted connection. "
292+
+ "Change the repository URL to HTTPS.");
293+
}
294+
String password = auth.getPassword() != null ? auth.getPassword() : "";
295+
String encoded = Base64.getEncoder()
296+
.encodeToString((auth.getUsername() + ":" + password).getBytes(StandardCharsets.UTF_8));
297+
PluginLogManager.getLog()
298+
.debug(String.format("Using Basic auth credentials for repository: %s", repository.getId()));
299+
return builder.header("Authorization", "Basic " + encoded);
300+
}
301+
return builder;
302+
}
303+
266304
@Override
267305
public void prewarmArtifactCache(Collection<Artifact> artifacts) {
268306
if (artifacts.isEmpty()) {

0 commit comments

Comments
 (0)