Skip to content

Commit

Permalink
[SECURITY-3501]
Browse files Browse the repository at this point in the history
  • Loading branch information
daniel-beck authored and jenkinsci-cert-ci committed Feb 25, 2025
1 parent 84ef1a4 commit 4a9a3ec
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 2 deletions.
2 changes: 1 addition & 1 deletion core/src/main/java/hudson/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -1651,7 +1651,7 @@ public static boolean isAbsoluteUri(@NonNull String uri) {
* @since 2.3 / 1.651.2
*/
public static boolean isSafeToRedirectTo(@NonNull String uri) {
return !isAbsoluteUri(uri) && !uri.startsWith("//");
return !isAbsoluteUri(uri) && !uri.startsWith("\\") && !uri.replace('\\', '/').startsWith("//");
}

/**
Expand Down
6 changes: 5 additions & 1 deletion core/src/test/java/hudson/UtilTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -416,12 +416,16 @@ public void testIsAbsoluteUri() {
}

@Test
@Issue("SECURITY-276")
@Issue({"SECURITY-276", "SECURITY-3501"})
public void testIsSafeToRedirectTo() {
assertFalse(Util.isSafeToRedirectTo("http://foobar/"));
assertFalse(Util.isSafeToRedirectTo("mailto:[email protected]"));
assertFalse(Util.isSafeToRedirectTo("d123://test/"));
assertFalse(Util.isSafeToRedirectTo("//google.com"));
assertFalse(Util.isSafeToRedirectTo("\\\\google.com"));
assertFalse(Util.isSafeToRedirectTo("\\/google.com"));
assertFalse(Util.isSafeToRedirectTo("/\\google.com"));
assertFalse(Util.isSafeToRedirectTo("\\google.com"));

assertTrue(Util.isSafeToRedirectTo("foo/bar/abc:def"));
assertTrue(Util.isSafeToRedirectTo("foo?abc:def"));
Expand Down
33 changes: 33 additions & 0 deletions test/src/test/java/jenkins/security/Security3501Test.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package jenkins.security;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;

import java.util.List;
import org.htmlunit.FailingHttpStatusCodeException;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.RealJenkinsRule;

public class Security3501Test {
@Rule
public RealJenkinsRule jj = new RealJenkinsRule();

@Test
public void testRedirects() throws Throwable {
jj.then(Security3501Test::_testRedirects);
}

public static void _testRedirects(JenkinsRule j) throws Exception {
List<String> prohibitedPaths = List.of("%5C%5Cexample.org", "%5C/example.org", "/%5Cexample.org", "//example.org", "https://example.org", "\\example.org");
for (String path : prohibitedPaths) {
try (JenkinsRule.WebClient wc = j.createWebClient().withRedirectEnabled(false)) {
final FailingHttpStatusCodeException fhsce = Assert.assertThrows(FailingHttpStatusCodeException.class, () -> wc.goTo("userContent?path=" + path));
assertThat(fhsce.getStatusCode(), is(302));
assertThat(fhsce.getResponse().getResponseHeaderValue("Location"), is(j.getURL().toExternalForm() + "userContent/"));
}
}
}
}

0 comments on commit 4a9a3ec

Please sign in to comment.