Low severityNVD Advisory· Published Sep 12, 2019· Updated Aug 4, 2024
CVE-2019-10398
CVE-2019-10398
Description
Jenkins Beaker Builder Plugin 1.9 and earlier stored credentials unencrypted in its global configuration file on the Jenkins master where they could be viewed by users with access to the master file system.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.jenkins-ci.plugins:beaker-builderMaven | < 1.10 | 1.10 |
Affected products
1- Range: 1.9 and earlier
Patches
1be0101f3541a[FIX SECURITY-1545] Store credentials in encrypted form
4 files changed · +96 −10
src/main/java/org/jenkinsci/plugins/beakerbuilder/BeakerBuilder.java+29 −9 modified@@ -1,8 +1,10 @@ package org.jenkinsci.plugins.beakerbuilder; +import com.google.common.annotations.VisibleForTesting; import hudson.Extension; import hudson.FilePath; import hudson.Launcher; +import hudson.XmlFile; import hudson.model.BuildListener; import hudson.model.Result; import hudson.model.AbstractBuild; @@ -12,6 +14,7 @@ import hudson.util.FormValidation; import java.io.IOException; +import java.io.ObjectStreamException; import java.net.URL; import java.util.ArrayList; import java.util.Map; @@ -20,7 +23,9 @@ import java.util.logging.Logger; import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; +import hudson.util.Secret; import net.sf.json.JSONObject; import org.apache.xmlrpc.XmlRpcException; @@ -266,7 +271,6 @@ public static class DescriptorImpl extends BuildStepDescriptor<Builder> { */ private String beakerURL; - // TODO provide a way to store the credential in Jenkins authentication center. /** * Beaker login */ @@ -275,7 +279,8 @@ public static class DescriptorImpl extends BuildStepDescriptor<Builder> { /** * Beaker password */ - private String password; + private @Nonnull Secret secret; + @Deprecated private String password; private transient BeakerClient beakerClient; private transient Identity identity; @@ -284,6 +289,15 @@ public DescriptorImpl() { load(); } + private Object readResolve() { + if (password != null) { + secret = Secret.fromString(password); + password = null; + save(); + } + return this; + } + @Override public boolean isApplicable(@SuppressWarnings("rawtypes")Class<? extends AbstractProject> aClass) { return true; @@ -318,8 +332,8 @@ public void setLogin(String login) { } @Restricted(DoNotUse.class) // Databinding - public void setPassword(String password) { - this.password = password; + public void setPassword(Secret secret) { + this.secret = secret; } /** @@ -331,7 +345,7 @@ private void setupClient() { beakerClient = BeakerServer.getXmlRpcClient(beakerURL); try { - identity = beakerClient.authenticate(new Identity(login, password)); + identity = beakerClient.authenticate(new Identity(login, secret.getPlainText())); } catch (XmlRpcException e) { beakerClient = null; LOGGER.log(Level.WARNING, "Unable to create beaker client", e); @@ -346,12 +360,12 @@ private void setupClient() { public FormValidation doTestConnection( @QueryParameter("beakerURL") final String beakerURL, @QueryParameter("login") final String login, - @QueryParameter("password") final String password + @QueryParameter("password") final Secret password ) { LOGGER.fine("Trying to get client for " + beakerURL); BeakerClient bc = BeakerServer.getXmlRpcClient(beakerURL); try { - Identity ident = bc.authenticate(new Identity(login, password)); + Identity ident = bc.authenticate(new Identity(login, password.getPlainText())); return FormValidation.ok("Connected as " + ident.whoAmI()); } catch (Exception e) { @@ -367,8 +381,8 @@ public String getLogin() { return login; } - public String getPassword() { - return password; + public Secret getPassword() { + return secret; } /** @@ -391,6 +405,12 @@ public String getPassword() { setupClient(); return identity; } + + @Override + @VisibleForTesting + protected XmlFile getConfigFile() { + return super.getConfigFile(); + } } private static final Logger LOGGER = Logger.getLogger(BeakerBuilder.class.getName());
src/test/java/org/jenkinsci/plugins/beakerbuilder/ConfigRoundtripTest.java+19 −1 modified@@ -32,11 +32,15 @@ import org.jenkinsci.plugins.beakerbuilder.BeakerBuilder.DescriptorImpl; 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.JenkinsRule.WebClient; import com.gargoylesoftware.htmlunit.html.HtmlForm; import com.gargoylesoftware.htmlunit.html.HtmlPage; +import org.jvnet.hudson.test.recipes.LocalData; + +import java.io.IOException; public class ConfigRoundtripTest { @@ -77,6 +81,20 @@ public void connectionRoundtrip() throws Exception { assertEquals("URL", descriptor.getBeakerURL()); assertEquals("USERNAME", descriptor.getLogin()); - assertEquals("PASSWD", descriptor.getPassword()); + assertEquals("PASSWD", descriptor.getPassword().getPlainText()); + } + + @Test + @LocalData + @Issue("SECURITY-1545") + public void migratePasswordToSecret() throws IOException { + DescriptorImpl descriptor = (DescriptorImpl) j.jenkins.getDescriptorOrDie(BeakerBuilder.class); + + assertEquals("URL", descriptor.getBeakerURL()); + assertEquals("USERNAME", descriptor.getLogin()); + assertEquals("PASSWD", descriptor.getPassword().getPlainText()); + + String text = descriptor.getConfigFile().asString(); + assertFalse(text, text.contains("PASSWD")); } }
src/test/resources/org/jenkinsci/plugins/beakerbuilder/ConfigRoundtripTest/migratePasswordToSecret/config.xml+42 −0 added@@ -0,0 +1,42 @@ +<?xml version='1.0' encoding='UTF-8'?> +<hudson> + <disabledAdministrativeMonitors/> + <version>1.609.3</version> + <numExecutors>2</numExecutors> + <mode>NORMAL</mode> + <useSecurity>true</useSecurity> + <authorizationStrategy class="hudson.security.AuthorizationStrategy$Unsecured"/> + <securityRealm class="hudson.security.SecurityRealm$None"/> + <disableRememberMe>false</disableRememberMe> + <projectNamingStrategy class="jenkins.model.ProjectNamingStrategy$DefaultProjectNamingStrategy"/> + <workspaceDir>${JENKINS_HOME}/workspace/${ITEM_FULLNAME}</workspaceDir> + <buildsDir>${ITEM_ROOTDIR}/builds</buildsDir> + <jdks> + <jdk> + <name>default</name> + <home>/usr/lib/jvm/java-7-openjdk/jre</home> + <properties/> + </jdk> + </jdks> + <viewsTabBar class="hudson.views.DefaultViewsTabBar"/> + <myViewsTabBar class="hudson.views.DefaultMyViewsTabBar"/> + <clouds/> + <quietPeriod>5</quietPeriod> + <scmCheckoutRetryCount>0</scmCheckoutRetryCount> + <views> + <hudson.model.AllView> + <owner class="hudson" reference="../../.."/> + <name>All</name> + <filterExecutors>false</filterExecutors> + <filterQueue>false</filterQueue> + <properties class="hudson.model.View$PropertyList"/> + </hudson.model.AllView> + </views> + <primaryView>All</primaryView> + <slaveAgentPort>0</slaveAgentPort> + <label></label> + <crumbIssuer class="org.jvnet.hudson.test.TestCrumbIssuer"/> + <nodeProperties/> + <globalNodeProperties/> + <noUsageStatistics>true</noUsageStatistics> +</hudson> \ No newline at end of file
src/test/resources/org/jenkinsci/plugins/beakerbuilder/ConfigRoundtripTest/migratePasswordToSecret/org.jenkinsci.plugins.beakerbuilder.BeakerBuilder.xml+6 −0 added@@ -0,0 +1,6 @@ +<?xml version='1.0' encoding='UTF-8'?> +<org.jenkinsci.plugins.beakerbuilder.BeakerBuilder_-DescriptorImpl> + <beakerURL>URL</beakerURL> + <login>USERNAME</login> + <password>PASSWD</password> +</org.jenkinsci.plugins.beakerbuilder.BeakerBuilder_-DescriptorImpl> \ No newline at end of file
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-9678-5f6f-wp3fghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2019-10398ghsaADVISORY
- www.openwall.com/lists/oss-security/2019/09/12/2ghsamailing-listx_refsource_MLISTWEB
- github.com/jenkinsci/beaker-builder-plugin/commit/be0101f3541a5d2c28cf226c8b2e55cd4cfc94daghsaWEB
- jenkins.io/security/advisory/2019-09-12/ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.