Skip to content

Commit 5fe9a44

Browse files
[JENKINS-73422] Add escape hatch for Authenticated user access to Resource URL (jenkinsci#9644)
Co-authored-by: Daniel Beck <[email protected]>
1 parent 15e045f commit 5fe9a44

File tree

2 files changed

+14
-2
lines changed

2 files changed

+14
-2
lines changed

core/src/main/java/jenkins/security/ResourceDomainRootAction.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ public Object getDynamic(String id, StaplerRequest req, StaplerResponse rsp) thr
117117
return null;
118118
}
119119

120-
if (!ACL.isAnonymous2(Jenkins.getAuthentication2())) {
120+
if (!ALLOW_AUTHENTICATED_USER && !ACL.isAnonymous2(Jenkins.getAuthentication2())) {
121121
rsp.sendError(400);
122122
return null;
123123
}
@@ -327,4 +327,8 @@ private static Token decode(String value) {
327327
// Not @Restricted because the entire class is
328328
@SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "for script console")
329329
public static /* not final for Groovy */ int VALID_FOR_MINUTES = SystemProperties.getInteger(ResourceDomainRootAction.class.getName() + ".validForMinutes", 30);
330+
331+
/* Escape hatch for a security hardening preventing one of the known ways to elevate arbitrary file read to RCE */
332+
@SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "for script console")
333+
public static /* not final for Groovy */ boolean ALLOW_AUTHENTICATED_USER = SystemProperties.getBoolean(ResourceDomainRootAction.class.getName() + ".allowAuthenticatedUser", false);
330334
}

test/src/test/java/jenkins/security/ResourceDomainTest.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ public HttpResponse doDynamic() throws Exception {
399399
}
400400

401401
@Test
402-
public void authenticatedCannotAccessResourceDomain() throws Exception {
402+
public void authenticatedCannotAccessResourceDomainUnlessAllowedBySystemProperty() throws Exception {
403403
j.jenkins.setSecurityRealm(j.createDummySecurityRealm());
404404
final MockAuthorizationStrategy authorizationStrategy = new MockAuthorizationStrategy();
405405
authorizationStrategy.grant(Jenkins.ADMINISTER).everywhere().to("admin").grant(Jenkins.READ).everywhere().toEveryone();
@@ -416,5 +416,13 @@ public void authenticatedCannotAccessResourceDomain() throws Exception {
416416
try (JenkinsRule.WebClient wc = j.createWebClient().withBasicCredentials("admin")) {
417417
assertThat(assertThrows(FailingHttpStatusCodeException.class, () -> wc.getPage(new URL(resourceUrl))).getStatusCode(), is(400));
418418
}
419+
420+
ResourceDomainRootAction.ALLOW_AUTHENTICATED_USER = true;
421+
try (JenkinsRule.WebClient wc = j.createWebClient().withBasicApiToken("admin")) {
422+
assertThat(wc.getPage(new URL(resourceUrl)).getWebResponse().getStatusCode(), is(200));
423+
}
424+
try (JenkinsRule.WebClient wc = j.createWebClient().withBasicCredentials("admin")) {
425+
assertThat(wc.getPage(new URL(resourceUrl)).getWebResponse().getStatusCode(), is(200));
426+
}
419427
}
420428
}

0 commit comments

Comments
 (0)