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.
| Package | Affected versions | Patched versions |
|---|---|---|
org.jenkins-ci.main:jenkins-coreMaven | >= 2.500, < 2.504 | 2.504 |
org.jenkins-ci.main:jenkins-coreMaven | < 2.492.3 | 2.492.3 |
Affected products
12- Range: <=2.503, LTS <=2.492.2
- osv-coords10 versionspkg:apk/chainguard/jenkins-2.462pkg:apk/chainguard/jenkins-2.479pkg:apk/chainguard/jenkins-2.479-compatpkg:apk/chainguard/jenkins-2.479-remotingpkg:apk/chainguard/jenkins-2.492pkg:apk/wolfi/jenkins-2.479pkg:apk/wolfi/jenkins-2.479-compatpkg:apk/wolfi/jenkins-2.479-remotingpkg:bitnami/jenkinspkg:maven/org.jenkins-ci.main/jenkins-core
< 0+ 9 more
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 2.492.3-r4
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 2.492.3
- (no CPE)range: >= 2.500, < 2.504
- Jenkins Project/Jenkinsv5Range: 2.492.3
Patches
12 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- github.com/advisories/GHSA-565r-pf5q-45v6ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-31720ghsaADVISORY
- www.jenkins.io/security/advisory/2025-04-02/ghsavendor-advisoryWEB
- github.com/jenkinsci/jenkins/commit/bf32018bf075c06e5df649583557c82d42d8bb5cghsaWEB
News mentions
1- Jenkins Security Advisory 2025-04-02Jenkins Security Advisories · Apr 2, 2025