CVE-2019-1003050
Description
Jenkins fails to escape job URLs in the f:validateButton form control, leading to a stored XSS vulnerability exploitable by users who can control job names.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Jenkins fails to escape job URLs in the f:validateButton form control, leading to a stored XSS vulnerability exploitable by users who can control job names.
Vulnerability
Details
CVE-2019-1003050 is a cross-site scripting (XSS) vulnerability in Jenkins core affecting versions 2.171 and earlier of the weekly release line and versions 2.164.1 and earlier of the LTS release line. The flaw resides in the f:validateButton form control, which is used to validate job configuration parameters. This control did not properly escape job URLs before rendering them in the Jenkins UI, allowing an attacker to inject arbitrary JavaScript into the page [2].
Exploitation
The vulnerability is exploitable by any Jenkins user who has the ability to control job names. This typically includes users with Job/Create or Job/Configure permissions. By creating or renaming a job with a crafted name containing malicious script content, the attacker can cause the script to execute in the context of any user who views the job configuration page, including administrators [1][2]. No authentication bypass or network-level attack is required; the attacker only needs a valid Jenkins account with sufficient privileges to create or modify jobs.
Impact
Successful exploitation leads to stored XSS, meaning the injected script becomes a permanent part of the affected page and executes for every subsequent visitor. Depending on the privileges of the victim, an attacker could perform administrative actions, exfiltrate session tokens, or deploy malicious plugins. The vulnerability is particularly severe in shared Jenkins environments where multiple users manage jobs, as it can be used to escalate privileges from a low-privileged job creator to a higher-privileged administrator [2][3].
Mitigation
Jenkins has released fixed versions: Jenkins 2.172 (weekly) and Jenkins LTS 2.164.2. Users are strongly advised to upgrade immediately. As part of the fix, the f:validateButton component properly escapes job URLs using htmlEncode to prevent script injection [3]. No workaround exists for unpatched versions. Red Hat's OpenShift Container Platform also included the fix in advisory RHBA-2019:1605 [1]. This CVE is not currently listed in CISA's Known Exploited Vulnerabilities catalog.
AI Insight generated on May 22, 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.164.2 | 2.164.2 |
org.jenkins-ci.main:jenkins-coreMaven | >= 2.165, < 2.172 | 2.172 |
Affected products
2- Range: 2.171 and earlier, LTS 2.164.1 and earlier
Patches
2d393c7e9ba3e[SECURITY-1327] Adapt test to new HTML Unit
1 file changed · +4 −2
test/src/test/java/lib/form/ValidateButtonSEC1327Test.java+4 −2 modified@@ -24,7 +24,9 @@ package lib.form; import com.gargoylesoftware.htmlunit.html.HtmlButton; +import com.gargoylesoftware.htmlunit.html.HtmlElement; import com.gargoylesoftware.htmlunit.html.HtmlPage; +import com.gargoylesoftware.htmlunit.html.DomNodeList; import hudson.model.FreeStyleProject; import hudson.model.Job; import hudson.model.JobProperty; @@ -72,8 +74,8 @@ private void checkValidateButtonWork(String projectName) throws Exception { HtmlPage htmlPage = wc.goTo(p.getUrl() + "/configure"); assertThat(htmlPage.getWebResponse().getStatusCode(), is(200)); - List<HtmlButton> inputs = htmlPage.getDocumentElement().getHtmlElementsByTagName("button"); - HtmlButton validateButton = inputs.stream() + DomNodeList<HtmlElement> inputs = htmlPage.getDocumentElement().getElementsByTagName("button"); + HtmlButton validateButton = (HtmlButton) inputs.stream() .filter(i -> i.getTextContent().contains("testInjection")) .findFirst() .orElseThrow(() -> new AssertionError("Validate button not found"));
4 files changed · +160 −1
core/src/main/resources/lib/form/validateButton.jelly+5 −1 modified@@ -48,7 +48,11 @@ THE SOFTWARE. </st:documentation> <f:entry> <div style="float:right"> - <input type="button" value="${title}" class="yui-button validate-button" onclick="validateButton('${descriptor.descriptorFullUrl}/${h.jsStringEscape(method)}','${h.jsStringEscape(with)}',this)" /> + <input type="button" value="${title}" class="yui-button validate-button" + data-validate-button-descriptor-url="${descriptor.descriptorFullUrl}" + data-validate-button-method="${method}" + data-validate-button-with="${with}" + onclick="safeValidateButton(this)" /> </div> <div style="display:none;"> <img src="${imagesURL}/spinner.gif" /> ${attrs.progress}
test/src/test/java/lib/form/ValidateButtonSEC1327Test.java+102 −0 added@@ -0,0 +1,102 @@ +/* + * The MIT License + * + * Copyright (c) 2004-2009, Sun Microsystems, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lib.form; + +import com.gargoylesoftware.htmlunit.html.HtmlButton; +import com.gargoylesoftware.htmlunit.html.HtmlPage; +import hudson.model.FreeStyleProject; +import hudson.model.Job; +import hudson.model.JobProperty; +import hudson.model.JobPropertyDescriptor; +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.TestExtension; +import org.kohsuke.stapler.StaplerRequest; + +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; + +//TODO merge with ValidateButtonTest once security release done +public class ValidateButtonSEC1327Test { + @Rule + public JenkinsRule j = new JenkinsRule(); + + @Test + public void regularUsageOfUsingDescriptorUrl() throws Exception { + checkValidateButtonWork("okName"); + } + + @Test + @Issue("SECURITY-1327") + public void xssUsingDescriptorUrl() throws Exception { + checkValidateButtonWork("TESTawsCC','a',this)+alert(1)+validateButton('aaa"); + } + + private void checkValidateButtonWork(String projectName) throws Exception { + FreeStyleProject p = j.createFreeStyleProject(projectName); + JenkinsRule.WebClient wc = j.createWebClient(); + ValidateProperty.DescriptorImpl descriptor = j.jenkins.getDescriptorByType(ValidateProperty.DescriptorImpl.class); + + AtomicReference<String> alertReceived = new AtomicReference<>(); + wc.setAlertHandler((page, s) -> alertReceived.set(s)); + + assertThat(alertReceived.get(), nullValue()); + + HtmlPage htmlPage = wc.goTo(p.getUrl() + "/configure"); + assertThat(htmlPage.getWebResponse().getStatusCode(), is(200)); + + List<HtmlButton> inputs = htmlPage.getDocumentElement().getHtmlElementsByTagName("button"); + HtmlButton validateButton = inputs.stream() + .filter(i -> i.getTextContent().contains("testInjection")) + .findFirst() + .orElseThrow(() -> new AssertionError("Validate button not found")); + + assertThat(alertReceived.get(), nullValue()); + assertThat(descriptor.called, is(false)); + + validateButton.click(); + + assertThat(alertReceived.get(), nullValue()); + + wc.waitForBackgroundJavaScript(5000); + assertThat(descriptor.called, is(true)); + } + + public static class ValidateProperty extends JobProperty<Job<?,?>> { + @TestExtension({"regularUsageOfUsingDescriptorUrl", "xssUsingDescriptorUrl"}) + public static class DescriptorImpl extends JobPropertyDescriptor { + public boolean called = false; + + public void doSomething(StaplerRequest req) { + called = true; + } + } + } +}
test/src/test/resources/lib/form/ValidateButtonSEC1327Test/ValidateProperty/config.jelly+29 −0 added@@ -0,0 +1,29 @@ +<!-- +The MIT License + +Copyright (c) 2019, CloudBees, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +--> +<?jelly escape-by-default='true'?> +<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout" xmlns:f="/lib/form"> + <div id="test-panel"> + <f:validateButton title="testInjection" method="something" /> + </div> +</j:jelly>
war/src/main/webapp/scripts/hudson-behavior.js+24 −0 modified@@ -529,6 +529,16 @@ function makeButton(e,onclick) { Element.addClassName(be,clsName); if(n) // copy the name be.setAttribute("name",n); + + // keep the data-* attributes from the source + var length = e.attributes.length; + for (var i = 0; i < length; i++) { + var attribute = e.attributes[i]; + var attributeName = attribute.name; + if (attributeName.startsWith('data-')) { + btn._button.setAttribute(attributeName, attribute.value); + } + } return btn; } @@ -2876,6 +2886,20 @@ function applySafeRedirector(url) { } // logic behind <f:validateButton /> +function safeValidateButton(yuiButton) { + var button = yuiButton._button; + var descriptorUrl = button.getAttribute('data-validate-button-descriptor-url'); + var method = button.getAttribute('data-validate-button-method'); + var checkUrl = descriptorUrl + "/" + method; + + // optional, by default = empty string + var paramList = button.getAttribute('data-validate-button-with') || ''; + + validateButton(checkUrl, paramList, yuiButton); +} + +// this method should not be called directly, only get called by safeValidateButton +// kept "public" for legacy compatibility function validateButton(checkUrl,paramList,button) { button = button._button;
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
8- access.redhat.com/errata/RHBA-2019:1605ghsavendor-advisoryx_refsource_REDHATWEB
- github.com/advisories/GHSA-qpg9-83fv-x9chghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2019-1003050ghsaADVISORY
- www.securityfocus.com/bid/107889ghsavdb-entryx_refsource_BIDWEB
- github.com/jenkinsci/jenkins/commit/8eb632dda219ec8796420ce58d9564cddf8f8f93ghsaWEB
- github.com/jenkinsci/jenkins/commit/d393c7e9ba3ec44953ef1f8b11839421e2649ee7ghsaWEB
- jenkins.io/security/advisory/2019-04-10/ghsax_refsource_CONFIRMWEB
- www.oracle.com/security-alerts/cpuapr2022.htmlghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.