From 417c502b0053feb954873bf4751476f4b016e1de Mon Sep 17 00:00:00 2001 From: Juga Paazmaya Date: Mon, 25 May 2026 13:26:53 +0300 Subject: [PATCH] fix: authenticate checksum fetching from remote --- .../checksum/RemoteChecksumCalculator.java | 58 +++++++++++++++---- 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/maven_plugin/src/main/java/io/github/chains_project/maven_lockfile/checksum/RemoteChecksumCalculator.java b/maven_plugin/src/main/java/io/github/chains_project/maven_lockfile/checksum/RemoteChecksumCalculator.java index 59dae8b55..e15dc1f3a 100644 --- a/maven_plugin/src/main/java/io/github/chains_project/maven_lockfile/checksum/RemoteChecksumCalculator.java +++ b/maven_plugin/src/main/java/io/github/chains_project/maven_lockfile/checksum/RemoteChecksumCalculator.java @@ -8,8 +8,10 @@ import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.util.ArrayList; +import java.util.Base64; import java.util.Collection; import java.util.List; import java.util.Locale; @@ -91,8 +93,8 @@ private Optional calculateChecksumInternal(Artifact artifact, ProjectBui PluginLogManager.getLog().debug(String.format("Checking: %s", checksumUrl)); - HttpRequest checksumRequest = - HttpRequest.newBuilder().uri(URI.create(checksumUrl)).build(); + HttpRequest checksumRequest = addAuth(HttpRequest.newBuilder().uri(URI.create(checksumUrl)), repository) + .build(); HttpResponse checksumResponse = httpClient.send(checksumRequest, HttpResponse.BodyHandlers.ofString()); @@ -103,8 +105,8 @@ private Optional calculateChecksumInternal(Artifact artifact, ProjectBui } if (checksumResponse.statusCode() == 404) { - HttpRequest artifactRequest = HttpRequest.newBuilder() - .uri(URI.create(artifactUrl)) + HttpRequest artifactRequest = addAuth( + HttpRequest.newBuilder().uri(URI.create(artifactUrl)), repository) .build(); HttpResponse artifactResponse = httpClient.send(artifactRequest, HttpResponse.BodyHandlers.ofByteArray()); @@ -137,8 +139,9 @@ private Optional calculateChecksumInternal(Artifact artifact, ProjectBui "Falling back to HTTP to find download integrity sha1 for %s", artifact.getId())); try { - HttpRequest artifactVerificationRequest = HttpRequest.newBuilder() - .uri(URI.create(artifactUrl + ".sha1")) + HttpRequest artifactVerificationRequest = addAuth( + HttpRequest.newBuilder().uri(URI.create(artifactUrl + ".sha1")), + repository) .build(); HttpResponse artifactVerificationResponse = httpClient.send( artifactVerificationRequest, HttpResponse.BodyHandlers.ofString()); @@ -194,11 +197,16 @@ private Optional calculateChecksumInternal(Artifact artifact, ProjectBui checksumCache.put(cacheKey, checksum); return Optional.of(checksum); } + // Non-2xx, non-404: likely an authentication or server error — do not silently skip + PluginLogManager.getLog() + .warn(String.format( + "HTTP %d fetching checksum from %s — verify credentials in settings.xml for repository '%s'", + checksumResponse.statusCode(), checksumUrl, repository.getId())); } PluginLogManager.getLog() .warn(String.format( - "Artifact checksum `%s.%s` not found among remote repositories.", + "Artifact checksum `%s.%s` not found in any configured remote repository.", artifact, checksumAlgorithm)); checksumCache.put(cacheKey, ""); return Optional.empty(); @@ -238,9 +246,11 @@ private Optional getResolvedFieldInternal( PluginLogManager.getLog().debug(String.format("Checking: %s", url)); - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(url)) - .method("HEAD", HttpRequest.BodyPublishers.noBody()) + HttpRequest request = addAuth( + HttpRequest.newBuilder() + .uri(URI.create(url)) + .method("HEAD", HttpRequest.BodyPublishers.noBody()), + repository) .build(); HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.discarding()); @@ -263,6 +273,34 @@ private Optional getResolvedFieldInternal( } } + /** + * Adds HTTP Basic authentication credentials to the request builder if the repository has + * authentication configured. Maven decrypts settings.xml server passwords before plugin + * execution, so {@code repository.getAuthentication()} already contains plaintext credentials. + * + * @throws IllegalStateException if credentials are configured but the repository URL does not + * use HTTPS, to prevent credential exposure over an unencrypted connection. + */ + private HttpRequest.Builder addAuth(HttpRequest.Builder builder, ArtifactRepository repository) { + var auth = repository.getAuthentication(); + if (auth != null && auth.getUsername() != null && !auth.getUsername().isEmpty()) { + if (!repository.getUrl().toLowerCase(Locale.ROOT).startsWith("https://")) { + throw new IllegalStateException( + "Repository '" + repository.getId() + "' has credentials configured but uses a plain HTTP URL (" + + repository.getUrl() + + "). Refusing to send credentials over an unencrypted connection. " + + "Change the repository URL to HTTPS."); + } + String password = auth.getPassword() != null ? auth.getPassword() : ""; + String encoded = Base64.getEncoder() + .encodeToString((auth.getUsername() + ":" + password).getBytes(StandardCharsets.UTF_8)); + PluginLogManager.getLog() + .debug(String.format("Using Basic auth credentials for repository: %s", repository.getId())); + return builder.header("Authorization", "Basic " + encoded); + } + return builder; + } + @Override public void prewarmArtifactCache(Collection artifacts) { if (artifacts.isEmpty()) {