Skip to content

Commit 1a81cf2

Browse files
authored
Redact URL-encoded characters in userinfo of URLs (#289)
Signed-off-by: Jerome Prinet <jprinet@gradle.com>
1 parent e480f07 commit 1a81cf2

File tree

3 files changed

+43
-7
lines changed

3 files changed

+43
-7
lines changed

src/main/java/com/gradle/CustomBuildScanEnhancements.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ public void accept(BuildScanApiAdapter buildScan) {
373373
String gitStatus = execAndGetStdOut("git", "status", "--porcelain");
374374

375375
if (isNotEmpty(gitRepo)) {
376-
buildScan.value("Git repository", redactUserInfo(gitRepo));
376+
redactUserInfo(gitRepo).ifPresent(redactedGitRepo -> buildScan.value("Git repository", redactedGitRepo));
377377
}
378378
if (isNotEmpty(gitCommitId)) {
379379
buildScan.value("Git commit id", gitCommitId);

src/main/java/com/gradle/Utils.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,24 @@ static String urlEncode(String str) {
6262
}
6363
}
6464

65-
static String redactUserInfo(String url) {
65+
static Optional<String> redactUserInfo(String url) {
66+
if (!url.startsWith("http")) {
67+
return Optional.of(url);
68+
}
69+
6670
try {
67-
String userInfo = new URI(url).getUserInfo();
68-
return userInfo == null
69-
? url
70-
: url.replace(userInfo + '@', "******@");
71+
URI uri = new URI(url);
72+
URI redactedUri = new URI(
73+
uri.getScheme(),
74+
uri.getUserInfo() == null || uri.getUserInfo().isEmpty() ? null : "******",
75+
uri.getHost(),
76+
uri.getPort(),
77+
uri.getRawPath(),
78+
uri.getRawQuery(),
79+
uri.getRawFragment());
80+
return Optional.of(redactedUri.toString());
7181
} catch (URISyntaxException e) {
72-
return url;
82+
return Optional.empty();
7383
}
7484
}
7585

src/test/java/com/gradle/UtilsTest.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import org.junit.jupiter.params.provider.ArgumentsSource;
99

1010
import java.net.URI;
11+
import java.util.HashMap;
12+
import java.util.Map;
1113
import java.util.Optional;
1214
import java.util.Set;
1315
import java.util.stream.Collectors;
@@ -32,6 +34,12 @@ public void testToWebRepoUri_enterpriseUri(String repositoryHost, String reposit
3234
assertEquals(Optional.of(expectedWebRepoUri), toWebRepoUri(String.format(repositoryUri, repositoryHost)));
3335
}
3436

37+
@ParameterizedTest
38+
@ArgumentsSource(UserInfoArgumentsProvider.class)
39+
public void testUserInfoRedacted(String inputUrl, String expectedRedactedUrl) {
40+
assertEquals(expectedRedactedUrl, Utils.redactUserInfo(inputUrl).orElse(null));
41+
}
42+
3543
private static class WebRepoUriArgumentsProvider implements ArgumentsProvider {
3644

3745
@Override
@@ -41,6 +49,8 @@ public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
4149
"https://%s.com/acme-inc/my-project",
4250
"https://%s.com:443/acme-inc/my-project",
4351
"https://user:secret@%s.com/acme-inc/my-project",
52+
"https://user:secret%%1Fpassword@%s.com/acme-inc/my-project",
53+
"https://user:secret%%1password@%s.com/acme-inc/my-project",
4454
"ssh://git@%s.com/acme-inc/my-project.git",
4555
"ssh://git@%s.com:22/acme-inc/my-project.git",
4656
"git://%s.com/acme-inc/my-project.git",
@@ -62,4 +72,20 @@ public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
6272
return host.stream().flatMap(h -> remoteRepositoryUris.stream().map(r -> Arguments.arguments(h, r)));
6373
}
6474
}
75+
76+
private static class UserInfoArgumentsProvider implements ArgumentsProvider {
77+
78+
@Override
79+
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
80+
Map<String, String> cases = new HashMap<>();
81+
cases.put("https://user:password@acme.com/acme-inc/my-project", "https://******@acme.com/acme-inc/my-project");
82+
cases.put("https://user%1Fname:password@acme.com/acme-inc/my-project", "https://******@acme.com/acme-inc/my-project");
83+
cases.put("https://user:secret%1Fpassword@acme.com/acme-inc/my-project", "https://******@acme.com/acme-inc/my-project");
84+
cases.put("https://user:secret%1password@acme.com/acme-inc/my-project", null);
85+
cases.put("git@github.com:gradle/common-custom-user-data-gradle-plugin.git", "git@github.com:gradle/common-custom-user-data-gradle-plugin.git");
86+
87+
return cases.entrySet().stream()
88+
.map(entry -> Arguments.arguments(entry.getKey(), entry.getValue()));
89+
}
90+
}
6591
}

0 commit comments

Comments
 (0)