Skip to content

Commit d5ecddb

Browse files
Ignore casing in AvatarContributor#extractDomainFromUrl (#23865)
* Ignore casing in AvatarContributor#extractDomainFromUrl * Extend test to check for correct handling of duplicates
1 parent 6731b97 commit d5ecddb

File tree

3 files changed

+20
-2
lines changed

3 files changed

+20
-2
lines changed

core/src/main/java/jenkins/security/csp/AvatarContributor.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import hudson.ExtensionList;
3030
import java.net.URI;
3131
import java.net.URISyntaxException;
32+
import java.util.Locale;
3233
import java.util.Set;
3334
import java.util.concurrent.ConcurrentHashMap;
3435
import java.util.logging.Level;
@@ -106,9 +107,10 @@ public static String extractDomainFromUrl(@CheckForNull String url) {
106107
LOGGER.log(Level.FINER, "Ignoring URI without host: " + url);
107108
return null;
108109
}
109-
String domain = host;
110-
final String scheme = uri.getScheme();
110+
String domain = host.toLowerCase(Locale.ROOT);
111+
String scheme = uri.getScheme();
111112
if (scheme != null) {
113+
scheme = scheme.toLowerCase(Locale.ROOT);
112114
if (scheme.equals("http") || scheme.equals("https")) {
113115
domain = scheme + "://" + domain;
114116
} else {

core/src/test/java/jenkins/security/csp/AvatarContributorTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,9 @@ void testExtractDomainFromUrl_Ipv4Address() {
8080
void testExtractDomainFromUrl_Ipv4WithPort() {
8181
assertThat(extractDomainFromUrl("https://192.168.1.1:8080/avatar.png"), is("https://192.168.1.1:8080"));
8282
}
83+
84+
@Test
85+
void testExtractDomainFromUrl_CaseInsensitivity() {
86+
assertThat(extractDomainFromUrl("hTTps://EXAMPLE.com/path/to/avatar.png"), is("https://example.com"));
87+
}
8388
}

test/src/test/java/jenkins/security/csp/AvatarContributorTest.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,15 @@ void testAllow_UnsupportedSchemeDoesNotAddToCsp(JenkinsRule j) {
139139
assertThat(loggerRule, recorded(Level.FINER, is("Ignoring URI with unsupported scheme: ftp://files.example.com/avatar.png")));
140140
assertThat(loggerRule, recorded(Level.FINER, is("Ignoring URI without host: data:image/png;base64,iVBORw0KG...")));
141141
}
142+
143+
@Test
144+
void testAllow_CaseInsensitivity(JenkinsRule j) {
145+
LoggerRule loggerRule = new LoggerRule().record(AvatarContributor.class, Level.FINEST).capture(100);
146+
AvatarContributor.allow("hTTps://AVATARS.example.com/user/avatar.png");
147+
AvatarContributor.allow("HttPS://avatars.EXAMPLE.com/user/avatar.png");
148+
String csp = new CspBuilder().withDefaultContributions().build();
149+
assertThat(csp, is("base-uri 'none'; default-src 'self'; form-action 'self'; frame-ancestors 'self'; img-src 'self' data: https://avatars.example.com; script-src 'report-sample' 'self'; style-src 'report-sample' 'self' 'unsafe-inline';"));
150+
assertThat(loggerRule, recorded(Level.CONFIG, is("Adding domain 'https://avatars.example.com' from avatar URL: hTTps://AVATARS.example.com/user/avatar.png")));
151+
assertThat(loggerRule, recorded(Level.FINEST, is("Skipped adding duplicate domain 'https://avatars.example.com' from avatar URL: HttPS://avatars.EXAMPLE.com/user/avatar.png")));
152+
}
142153
}

0 commit comments

Comments
 (0)