VYPR
Moderate severityNVD Advisory· Published Apr 2, 2025· Updated Apr 2, 2025

CVE-2025-31720

CVE-2025-31720

Description

A missing permission check in Jenkins 2.503 and earlier, LTS 2.492.2 and earlier allows attackers with Computer/Create permission but without Computer/Extended Read permission to copy an agent, gaining access to its configuration.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Jenkins 2.503 and earlier, LTS 2.492.2 and earlier missing permission check allows attackers with Computer/Create permission to copy an agent and access its configuration.

Vulnerability

CVE-2025-31720 is a missing permission check in Jenkins core. The HTTP endpoint used to copy an agent did not verify that the user had the Computer/Extended Read permission, only requiring Computer/Create. This flaw exists in Jenkins 2.503 and earlier, and LTS 2.492.2 and earlier [1][2].

Exploitation

An attacker with Computer/Create permission, but without Computer/Extended Read, can send a request to copy an existing agent. The endpoint fails to enforce the extended read check, allowing the attacker to obtain the agent's configuration [1].

Impact

By copying an agent, the attacker gains access to its configuration, which may contain sensitive information such as credentials, node labels, and other settings. This could facilitate further compromise of the Jenkins environment [1][2].

Mitigation

The issue is fixed in Jenkins 2.504 and LTS 2.492.3, where the Computer/Extended Read permission is now required to copy an agent [1]. The fix adds a permission check as shown in the commit [3].

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.jenkins-ci.main:jenkins-coreMaven
>= 2.500, < 2.5042.504
org.jenkins-ci.main:jenkins-coreMaven
< 2.492.32.492.3

Affected products

12

Patches

1
bf32018bf075

[SECURITY-3512]

https://github.com/jenkinsci/jenkinsDaniel BeckMar 25, 2025via ghsa
2 files changed · +64 0
  • core/src/main/java/hudson/model/ComputerSet.java+2 0 modified
    @@ -291,6 +291,8 @@ public synchronized void doCreateItem(StaplerRequest2 req, StaplerResponse2 rsp,
                     }
                 }
     
    +            src.checkPermission(Computer.EXTENDED_READ);
    +
                 // copy through XStream
                 String xml = Jenkins.XSTREAM.toXML(src);
                 Node result = (Node) Jenkins.XSTREAM.fromXML(xml);
    
  • test/src/test/java/jenkins/security/Security3512Test.java+62 0 added
    @@ -0,0 +1,62 @@
    +package jenkins.security;
    +
    +import static org.hamcrest.MatcherAssert.assertThat;
    +import static org.hamcrest.Matchers.containsString;
    +import static org.junit.Assert.assertEquals;
    +
    +import hudson.model.Computer;
    +import hudson.slaves.DumbSlave;
    +import java.net.URL;
    +import jenkins.model.Jenkins;
    +import org.htmlunit.HttpMethod;
    +import org.htmlunit.WebRequest;
    +import org.htmlunit.WebResponse;
    +import org.junit.Rule;
    +import org.junit.Test;
    +import org.jvnet.hudson.test.Issue;
    +import org.jvnet.hudson.test.JenkinsRule;
    +import org.jvnet.hudson.test.MockAuthorizationStrategy;
    +
    +public class Security3512Test {
    +
    +    @Rule
    +    public JenkinsRule j = new JenkinsRule();
    +
    +    @Test
    +    @Issue("SECURITY-3512")
    +    public void copyAgentTest() throws Exception {
    +        Computer.EXTENDED_READ.setEnabled(true);
    +        j.jenkins.setSecurityRealm(j.createDummySecurityRealm());
    +        MockAuthorizationStrategy mockAuthorizationStrategy = new MockAuthorizationStrategy();
    +        mockAuthorizationStrategy.grant(Jenkins.READ, Computer.CREATE, Computer.EXTENDED_READ).everywhere().to("alice");
    +        mockAuthorizationStrategy.grant(Jenkins.READ, Computer.CREATE).everywhere().to("bob");
    +        j.jenkins.setAuthorizationStrategy(mockAuthorizationStrategy);
    +
    +        DumbSlave agent = j.createOnlineSlave();
    +
    +        assertEquals(2, j.getInstance().getComputers().length);
    +
    +        String agentCopyURL = j.getURL() + "/computer/createItem?mode=copy&from=" + agent.getNodeName() + "&name=";
    +
    +        { // with ExtendedRead permission you can copy a node
    +            try (JenkinsRule.WebClient wc = j.createWebClient().withThrowExceptionOnFailingStatusCode(false).login("alice")) {
    +                WebResponse rsp = wc.getPage(wc.addCrumb(new WebRequest(new URL(agentCopyURL + "aliceAgent"),
    +                        HttpMethod.POST))).getWebResponse();
    +
    +                assertEquals(200, rsp.getStatusCode());
    +                assertEquals(3, j.getInstance().getComputers().length);
    +            }
    +        }
    +
    +        { // without ExtendedRead permission you cannot copy a node
    +            try (JenkinsRule.WebClient wc = j.createWebClient().withThrowExceptionOnFailingStatusCode(false).login("bob")) {
    +                WebResponse rsp = wc.getPage(wc.addCrumb(new WebRequest(new URL(agentCopyURL + "bobAgent"),
    +                        HttpMethod.POST))).getWebResponse();
    +
    +                assertEquals(403, rsp.getStatusCode());
    +                assertThat(rsp.getContentAsString(), containsString("bob is missing the Agent/ExtendedRead permission"));
    +                assertEquals(3, j.getInstance().getComputers().length);
    +            }
    +        }
    +    }
    +}
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

1