Skip to content

Commit 0f8f5a2

Browse files
daniel-beckjenkinsci-cert-ci
authored andcommitted
[SECURITY-3501]
1 parent 8acdf20 commit 0f8f5a2

File tree

3 files changed

+39
-2
lines changed

3 files changed

+39
-2
lines changed

core/src/main/java/hudson/Util.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1663,7 +1663,7 @@ public static boolean isAbsoluteUri(@NonNull String uri) {
16631663
* @since 2.3 / 1.651.2
16641664
*/
16651665
public static boolean isSafeToRedirectTo(@NonNull String uri) {
1666-
return !isAbsoluteUri(uri) && !uri.startsWith("//");
1666+
return !isAbsoluteUri(uri) && !uri.startsWith("\\") && !uri.replace('\\', '/').startsWith("//");
16671667
}
16681668

16691669
/**

core/src/test/java/hudson/UtilTest.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -416,12 +416,16 @@ public void testIsAbsoluteUri() {
416416
}
417417

418418
@Test
419-
@Issue("SECURITY-276")
419+
@Issue({"SECURITY-276", "SECURITY-3501"})
420420
public void testIsSafeToRedirectTo() {
421421
assertFalse(Util.isSafeToRedirectTo("http://foobar/"));
422422
assertFalse(Util.isSafeToRedirectTo("mailto:[email protected]"));
423423
assertFalse(Util.isSafeToRedirectTo("d123://test/"));
424424
assertFalse(Util.isSafeToRedirectTo("//google.com"));
425+
assertFalse(Util.isSafeToRedirectTo("\\\\google.com"));
426+
assertFalse(Util.isSafeToRedirectTo("\\/google.com"));
427+
assertFalse(Util.isSafeToRedirectTo("/\\google.com"));
428+
assertFalse(Util.isSafeToRedirectTo("\\google.com"));
425429

426430
assertTrue(Util.isSafeToRedirectTo("foo/bar/abc:def"));
427431
assertTrue(Util.isSafeToRedirectTo("foo?abc:def"));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package jenkins.security;
2+
3+
import static org.hamcrest.MatcherAssert.assertThat;
4+
import static org.hamcrest.Matchers.is;
5+
6+
import java.util.List;
7+
import org.htmlunit.FailingHttpStatusCodeException;
8+
import org.junit.Assert;
9+
import org.junit.Rule;
10+
import org.junit.Test;
11+
import org.jvnet.hudson.test.JenkinsRule;
12+
import org.jvnet.hudson.test.RealJenkinsRule;
13+
14+
public class Security3501Test {
15+
@Rule
16+
public RealJenkinsRule jj = new RealJenkinsRule();
17+
18+
@Test
19+
public void testRedirects() throws Throwable {
20+
jj.then(Security3501Test::_testRedirects);
21+
}
22+
23+
public static void _testRedirects(JenkinsRule j) throws Exception {
24+
List<String> prohibitedPaths = List.of("%5C%5Cexample.org", "%5C/example.org", "/%5Cexample.org", "//example.org", "https://example.org", "\\example.org");
25+
for (String path : prohibitedPaths) {
26+
try (JenkinsRule.WebClient wc = j.createWebClient().withRedirectEnabled(false)) {
27+
final FailingHttpStatusCodeException fhsce = Assert.assertThrows(FailingHttpStatusCodeException.class, () -> wc.goTo("userContent?path=" + path));
28+
assertThat(fhsce.getStatusCode(), is(302));
29+
assertThat(fhsce.getResponse().getResponseHeaderValue("Location"), is(j.getURL().toExternalForm() + "userContent/"));
30+
}
31+
}
32+
}
33+
}

0 commit comments

Comments
 (0)