VYPR
Low severityNVD Advisory· Published Jan 12, 2022· Updated Aug 3, 2024

CVE-2022-23114

CVE-2022-23114

Description

Jenkins Publish Over SSH Plugin 1.22 and earlier stores password unencrypted in its global configuration file on the Jenkins controller where it can be viewed by users with access to the Jenkins controller file system.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.jenkins-ci.plugins:publish-over-sshMaven
< 1.231.23

Affected products

1

Patches

2
2b4b9b2dfab5

Merge pull request #52 from olamy/SECURITY-2291

4 files changed · +49 31
  • src/main/java/jenkins/plugins/publish_over_ssh/BapSshHostConfiguration.java+39 20 modified
    @@ -30,8 +30,10 @@
     
     import java.io.IOException;
     import java.util.ArrayList;
    +import java.util.Objects;
     import java.util.Properties;
     
    +import hudson.util.Secret;
     import jenkins.model.Jenkins;
     import jenkins.plugins.publish_over.*;
     import jenkins.plugins.publish_over_ssh.descriptor.BapSshHostConfigurationDescriptor;
    @@ -70,7 +72,10 @@ public class BapSshHostConfiguration extends BPHostConfiguration<BapSshClient, B
         private String proxyHost;
         private int proxyPort;
         private String proxyUser;
    +
    +    @Deprecated
         private String proxyPassword;
    +    private Secret secretProxyPassword;
     
         public BapSshHostConfiguration() {
             // use this constructor instead of the default w/o parameters because there is some
    @@ -183,7 +188,13 @@ public void setEncryptedPassword(final String encryptedPassword) {
     
         public String getProxyUser() { return proxyUser; }
     
    -    public String getProxyPassword() {return proxyPassword; }
    +    public String getProxyPassword() {
    +        return Secret.toString(this.secretProxyPassword);
    +    }
    +
    +    public Secret getSecretProxyPassword() {
    +        return this.secretProxyPassword;
    +    }
     
         @DataBoundSetter
         public void setProxyType(String proxyType) {
    @@ -207,7 +218,21 @@ public void setProxyUser(String proxyUser) {
     
         @DataBoundSetter
         public void setProxyPassword(String proxyPassword) {
    -        this.proxyPassword = proxyPassword;
    +        this.secretProxyPassword = Secret.fromString(proxyPassword);
    +    }
    +
    +    @DataBoundSetter
    +    public void setSecretProxyPassword(Secret secretProxyPassword) {
    +        this.secretProxyPassword = secretProxyPassword;
    +    }
    +
    +    @Override
    +    public Object readResolve() {
    +        if(StringUtils.isNotEmpty(proxyPassword)) {
    +            this.secretProxyPassword = Secret.fromString(this.proxyPassword);
    +            this.proxyPassword = null;
    +        }
    +        return super.readResolve();
         }
     
         public boolean isEffectiveDisableExec() {
    @@ -251,13 +276,7 @@ public BapSshClient createClient(final BPBuildInfo buildInfo, final boolean conn
                 }
                 if (connectSftp)
                     setupSftp(bapClient);
    -        } catch (IOException e) {
    -            bapClient.disconnectQuietly();
    -            throw new BapPublisherException(Messages.exception_failedToCreateClient(e.getLocalizedMessage()), e);
    -        } catch (JSchException e) {
    -            bapClient.disconnectQuietly();
    -            throw new BapPublisherException(Messages.exception_failedToCreateClient(e.getLocalizedMessage()), e);
    -        } catch (BapPublisherException e) {
    +        } catch (IOException | JSchException | BapPublisherException e) {
                 bapClient.disconnectQuietly();
                 throw new BapPublisherException(Messages.exception_failedToCreateClient(e.getLocalizedMessage()), e);            
             }
    @@ -284,7 +303,7 @@ static String[] getHosts(String target, String jumpHosts) {
                     }
                 }
                 hosts.add(target);
    -            return hosts.toArray(new String[hosts.size()]);
    +            return hosts.toArray(new String[0]);
             }
         }
     
    @@ -395,24 +414,24 @@ private Session createSession(final BPBuildInfo buildInfo, final JSch ssh, Strin
                 if (StringUtils.isNotEmpty(proxyType) && StringUtils.isNotEmpty(proxyHost)) {
                     if (StringUtils.equals(HTTP_PROXY_TYPE, proxyType)) {
                         ProxyHTTP proxyHTTP = new ProxyHTTP(proxyHost, proxyPort);
    -                    if (StringUtils.isNotEmpty(proxyUser) && StringUtils.isNotEmpty(proxyPassword)) {
    -                        proxyHTTP.setUserPasswd(proxyUser, proxyPassword);
    +                    if (StringUtils.isNotEmpty(proxyUser) && StringUtils.isNotEmpty(secretProxyPassword.getPlainText())) {
    +                        proxyHTTP.setUserPasswd(proxyUser, secretProxyPassword.getPlainText());
                         } else {
                             proxyHTTP.setUserPasswd(null, null);
                         }
                         session.setProxy(proxyHTTP);
                     } else if (StringUtils.equals(SOCKS_4_PROXY_TYPE, proxyType)) {
                         ProxySOCKS4 proxySocks4 = new ProxySOCKS4(proxyHost, proxyPort);
    -                    if (StringUtils.isNotEmpty(proxyUser) && StringUtils.isNotEmpty(proxyPassword)) {
    -                        proxySocks4.setUserPasswd(proxyUser, proxyPassword);
    +                    if (StringUtils.isNotEmpty(proxyUser) && StringUtils.isNotEmpty(secretProxyPassword.getPlainText())) {
    +                        proxySocks4.setUserPasswd(proxyUser, secretProxyPassword.getPlainText());
                         } else {
                             proxySocks4.setUserPasswd(null, null);
                         }
                         session.setProxy(proxySocks4);
                     } else if (StringUtils.equals(SOCKS_5_PROXY_TYPE, proxyType)) {
                         ProxySOCKS5 proxySocks5 = new ProxySOCKS5(proxyHost, proxyPort);
    -                    if (StringUtils.isNotEmpty(proxyUser) && StringUtils.isNotEmpty(proxyPassword)) {
    -                        proxySocks5.setUserPasswd(proxyUser, proxyPassword);
    +                    if (StringUtils.isNotEmpty(proxyUser) && StringUtils.isNotEmpty(secretProxyPassword.getPlainText())) {
    +                        proxySocks5.setUserPasswd(proxyUser, secretProxyPassword.getPlainText());
                         } else {
                             proxySocks5.setUserPasswd(null, null);
                         }
    @@ -435,7 +454,7 @@ protected JSch createJSch() {
         }
     
         public BapSshHostConfigurationDescriptor getDescriptor() {
    -        return Jenkins.getInstance().getDescriptorByType(BapSshHostConfigurationDescriptor.class);
    +        return Jenkins.get().getDescriptorByType(BapSshHostConfigurationDescriptor.class);
         }
     
         protected EqualsBuilder addToEquals(final EqualsBuilder builder, final BapSshHostConfiguration that) {
    @@ -449,7 +468,7 @@ protected EqualsBuilder addToEquals(final EqualsBuilder builder, final BapSshHos
                     .append(proxyHost, that.proxyHost)
                     .append(proxyPort, that.proxyPort)
                     .append(proxyUser, that.proxyUser)
    -                .append(proxyPassword, that.proxyPassword);
    +                .append(secretProxyPassword, that.secretProxyPassword);
         }
     
         @Override
    @@ -464,7 +483,7 @@ protected HashCodeBuilder addToHashCode(final HashCodeBuilder builder) {
                     .append(proxyHost)
                     .append(proxyPort)
                     .append(proxyUser)
    -                .append(proxyPassword);
    +                .append(secretProxyPassword.getPlainText());
         }
     
         @Override
    @@ -479,7 +498,7 @@ protected ToStringBuilder addToToString(final ToStringBuilder builder) {
                     .append("proxyHost", proxyHost)
                     .append("proxyPort", proxyPort)
                     .append("proxyUser", proxyUser)
    -                .append("proxyPassword", proxyPassword);
    +                .append("proxyPassword", "xxxxxxx");
         }
     
         @Override
    
  • src/main/java/jenkins/plugins/publish_over_ssh/descriptor/BapSshHostConfigurationDescriptor.java+0 1 modified
    @@ -101,5 +101,4 @@ public FormValidation doTestConnection(final StaplerRequest request, final Stapl
         public jenkins.plugins.publish_over.view_defaults.HostConfiguration.Messages getCommonFieldNames() {
             return new jenkins.plugins.publish_over.view_defaults.HostConfiguration.Messages();
         }
    -
     }
    
  • src/main/java/jenkins/plugins/publish_over_ssh/descriptor/BapSshPublisherPluginDescriptor.java+9 9 modified
    @@ -29,6 +29,13 @@
     import java.util.Comparator;
     import java.util.List;
     
    +import hudson.Extension;
    +import hudson.ExtensionPoint;
    +import hudson.init.InitMilestone;
    +import hudson.init.Initializer;
    +import hudson.util.Secret;
    +import jenkins.plugins.publish_over.BPHostConfiguration;
    +import org.apache.commons.lang.StringUtils;
     import org.kohsuke.stapler.StaplerRequest;
     import org.kohsuke.stapler.StaplerResponse;
     
    @@ -67,7 +74,7 @@ public class BapSshPublisherPluginDescriptor extends BuildStepDescriptor<Publish
         /** null - prevent complaints from xstream */
         @SuppressFBWarnings(value = "URF_UNREAD_FIELD")
         private transient Class hostConfigClass;
    -    private final CopyOnWriteList<BapSshHostConfiguration> hostConfigurations = new CopyOnWriteList<BapSshHostConfiguration>();
    +    private final CopyOnWriteList<BapSshHostConfiguration> hostConfigurations = new CopyOnWriteList<>();
         private BapSshCommonConfiguration commonConfig;
         private SshDefaults defaults;
     
    @@ -101,14 +108,7 @@ public List<BapSshHostConfiguration> getHostConfigurations() {
                 retVal.add(current);
             }
     
    -        Collections.sort(retVal, new Comparator<BapSshHostConfiguration>() {
    -
    -            @Override
    -            public int compare(BapSshHostConfiguration p1, BapSshHostConfiguration p2) {
    -                return p1.getName().compareTo(p2.getName());
    -            }
    -
    -        });
    +        Collections.sort(retVal, Comparator.comparing(BPHostConfiguration::getName));
     
             return retVal;
         }
    
  • src/main/resources/jenkins/plugins/publish_over_ssh/BapSshHostConfiguration/config.jelly+1 1 modified
    @@ -86,7 +86,7 @@
             <f:entry title="${%proxyUser}" field="proxyUser">
                 <f:textbox/>
             </f:entry>
    -        <f:entry title="${%proxyPassword}" field="proxyPassword">
    +        <f:entry title="${%proxyPassword}" field="secretProxyPassword">
                 <f:password/>
             </f:entry>
             
    
70b7689bf6fc

[SECURITY-2291] Unprotected Storage of Credentials

4 files changed · +49 31
  • src/main/java/jenkins/plugins/publish_over_ssh/BapSshHostConfiguration.java+39 20 modified
    @@ -30,8 +30,10 @@
     
     import java.io.IOException;
     import java.util.ArrayList;
    +import java.util.Objects;
     import java.util.Properties;
     
    +import hudson.util.Secret;
     import jenkins.model.Jenkins;
     import jenkins.plugins.publish_over.*;
     import jenkins.plugins.publish_over_ssh.descriptor.BapSshHostConfigurationDescriptor;
    @@ -70,7 +72,10 @@ public class BapSshHostConfiguration extends BPHostConfiguration<BapSshClient, B
         private String proxyHost;
         private int proxyPort;
         private String proxyUser;
    +
    +    @Deprecated
         private String proxyPassword;
    +    private Secret secretProxyPassword;
     
         public BapSshHostConfiguration() {
             // use this constructor instead of the default w/o parameters because there is some
    @@ -183,7 +188,13 @@ public void setEncryptedPassword(final String encryptedPassword) {
     
         public String getProxyUser() { return proxyUser; }
     
    -    public String getProxyPassword() {return proxyPassword; }
    +    public String getProxyPassword() {
    +        return Secret.toString(this.secretProxyPassword);
    +    }
    +
    +    public Secret getSecretProxyPassword() {
    +        return this.secretProxyPassword;
    +    }
     
         @DataBoundSetter
         public void setProxyType(String proxyType) {
    @@ -207,7 +218,21 @@ public void setProxyUser(String proxyUser) {
     
         @DataBoundSetter
         public void setProxyPassword(String proxyPassword) {
    -        this.proxyPassword = proxyPassword;
    +        this.secretProxyPassword = Secret.fromString(proxyPassword);
    +    }
    +
    +    @DataBoundSetter
    +    public void setSecretProxyPassword(Secret secretProxyPassword) {
    +        this.secretProxyPassword = secretProxyPassword;
    +    }
    +
    +    @Override
    +    public Object readResolve() {
    +        if(StringUtils.isNotEmpty(proxyPassword)) {
    +            this.secretProxyPassword = Secret.fromString(this.proxyPassword);
    +            this.proxyPassword = null;
    +        }
    +        return super.readResolve();
         }
     
         public boolean isEffectiveDisableExec() {
    @@ -251,13 +276,7 @@ public BapSshClient createClient(final BPBuildInfo buildInfo, final boolean conn
                 }
                 if (connectSftp)
                     setupSftp(bapClient);
    -        } catch (IOException e) {
    -            bapClient.disconnectQuietly();
    -            throw new BapPublisherException(Messages.exception_failedToCreateClient(e.getLocalizedMessage()), e);
    -        } catch (JSchException e) {
    -            bapClient.disconnectQuietly();
    -            throw new BapPublisherException(Messages.exception_failedToCreateClient(e.getLocalizedMessage()), e);
    -        } catch (BapPublisherException e) {
    +        } catch (IOException | JSchException | BapPublisherException e) {
                 bapClient.disconnectQuietly();
                 throw new BapPublisherException(Messages.exception_failedToCreateClient(e.getLocalizedMessage()), e);            
             }
    @@ -284,7 +303,7 @@ static String[] getHosts(String target, String jumpHosts) {
                     }
                 }
                 hosts.add(target);
    -            return hosts.toArray(new String[hosts.size()]);
    +            return hosts.toArray(new String[0]);
             }
         }
     
    @@ -395,24 +414,24 @@ private Session createSession(final BPBuildInfo buildInfo, final JSch ssh, Strin
                 if (StringUtils.isNotEmpty(proxyType) && StringUtils.isNotEmpty(proxyHost)) {
                     if (StringUtils.equals(HTTP_PROXY_TYPE, proxyType)) {
                         ProxyHTTP proxyHTTP = new ProxyHTTP(proxyHost, proxyPort);
    -                    if (StringUtils.isNotEmpty(proxyUser) && StringUtils.isNotEmpty(proxyPassword)) {
    -                        proxyHTTP.setUserPasswd(proxyUser, proxyPassword);
    +                    if (StringUtils.isNotEmpty(proxyUser) && StringUtils.isNotEmpty(secretProxyPassword.getPlainText())) {
    +                        proxyHTTP.setUserPasswd(proxyUser, secretProxyPassword.getPlainText());
                         } else {
                             proxyHTTP.setUserPasswd(null, null);
                         }
                         session.setProxy(proxyHTTP);
                     } else if (StringUtils.equals(SOCKS_4_PROXY_TYPE, proxyType)) {
                         ProxySOCKS4 proxySocks4 = new ProxySOCKS4(proxyHost, proxyPort);
    -                    if (StringUtils.isNotEmpty(proxyUser) && StringUtils.isNotEmpty(proxyPassword)) {
    -                        proxySocks4.setUserPasswd(proxyUser, proxyPassword);
    +                    if (StringUtils.isNotEmpty(proxyUser) && StringUtils.isNotEmpty(secretProxyPassword.getPlainText())) {
    +                        proxySocks4.setUserPasswd(proxyUser, secretProxyPassword.getPlainText());
                         } else {
                             proxySocks4.setUserPasswd(null, null);
                         }
                         session.setProxy(proxySocks4);
                     } else if (StringUtils.equals(SOCKS_5_PROXY_TYPE, proxyType)) {
                         ProxySOCKS5 proxySocks5 = new ProxySOCKS5(proxyHost, proxyPort);
    -                    if (StringUtils.isNotEmpty(proxyUser) && StringUtils.isNotEmpty(proxyPassword)) {
    -                        proxySocks5.setUserPasswd(proxyUser, proxyPassword);
    +                    if (StringUtils.isNotEmpty(proxyUser) && StringUtils.isNotEmpty(secretProxyPassword.getPlainText())) {
    +                        proxySocks5.setUserPasswd(proxyUser, secretProxyPassword.getPlainText());
                         } else {
                             proxySocks5.setUserPasswd(null, null);
                         }
    @@ -435,7 +454,7 @@ protected JSch createJSch() {
         }
     
         public BapSshHostConfigurationDescriptor getDescriptor() {
    -        return Jenkins.getInstance().getDescriptorByType(BapSshHostConfigurationDescriptor.class);
    +        return Jenkins.get().getDescriptorByType(BapSshHostConfigurationDescriptor.class);
         }
     
         protected EqualsBuilder addToEquals(final EqualsBuilder builder, final BapSshHostConfiguration that) {
    @@ -449,7 +468,7 @@ protected EqualsBuilder addToEquals(final EqualsBuilder builder, final BapSshHos
                     .append(proxyHost, that.proxyHost)
                     .append(proxyPort, that.proxyPort)
                     .append(proxyUser, that.proxyUser)
    -                .append(proxyPassword, that.proxyPassword);
    +                .append(secretProxyPassword, that.secretProxyPassword);
         }
     
         @Override
    @@ -464,7 +483,7 @@ protected HashCodeBuilder addToHashCode(final HashCodeBuilder builder) {
                     .append(proxyHost)
                     .append(proxyPort)
                     .append(proxyUser)
    -                .append(proxyPassword);
    +                .append(secretProxyPassword.getPlainText());
         }
     
         @Override
    @@ -479,7 +498,7 @@ protected ToStringBuilder addToToString(final ToStringBuilder builder) {
                     .append("proxyHost", proxyHost)
                     .append("proxyPort", proxyPort)
                     .append("proxyUser", proxyUser)
    -                .append("proxyPassword", proxyPassword);
    +                .append("proxyPassword", "xxxxxxx");
         }
     
         @Override
    
  • src/main/java/jenkins/plugins/publish_over_ssh/descriptor/BapSshHostConfigurationDescriptor.java+0 1 modified
    @@ -99,5 +99,4 @@ public FormValidation doTestConnection(final StaplerRequest request, final Stapl
         public jenkins.plugins.publish_over.view_defaults.HostConfiguration.Messages getCommonFieldNames() {
             return new jenkins.plugins.publish_over.view_defaults.HostConfiguration.Messages();
         }
    -
     }
    
  • src/main/java/jenkins/plugins/publish_over_ssh/descriptor/BapSshPublisherPluginDescriptor.java+9 9 modified
    @@ -29,6 +29,13 @@
     import java.util.Comparator;
     import java.util.List;
     
    +import hudson.Extension;
    +import hudson.ExtensionPoint;
    +import hudson.init.InitMilestone;
    +import hudson.init.Initializer;
    +import hudson.util.Secret;
    +import jenkins.plugins.publish_over.BPHostConfiguration;
    +import org.apache.commons.lang.StringUtils;
     import org.kohsuke.stapler.StaplerRequest;
     import org.kohsuke.stapler.StaplerResponse;
     
    @@ -66,7 +73,7 @@ public class BapSshPublisherPluginDescriptor extends BuildStepDescriptor<Publish
         /** null - prevent complaints from xstream */
         @SuppressFBWarnings(value = "URF_UNREAD_FIELD")
         private transient Class hostConfigClass;
    -    private final CopyOnWriteList<BapSshHostConfiguration> hostConfigurations = new CopyOnWriteList<BapSshHostConfiguration>();
    +    private final CopyOnWriteList<BapSshHostConfiguration> hostConfigurations = new CopyOnWriteList<>();
         private BapSshCommonConfiguration commonConfig;
         private SshDefaults defaults;
     
    @@ -100,14 +107,7 @@ public List<BapSshHostConfiguration> getHostConfigurations() {
                 retVal.add(current);
             }
     
    -        Collections.sort(retVal, new Comparator<BapSshHostConfiguration>() {
    -
    -            @Override
    -            public int compare(BapSshHostConfiguration p1, BapSshHostConfiguration p2) {
    -                return p1.getName().compareTo(p2.getName());
    -            }
    -
    -        });
    +        Collections.sort(retVal, Comparator.comparing(BPHostConfiguration::getName));
     
             return retVal;
         }
    
  • src/main/resources/jenkins/plugins/publish_over_ssh/BapSshHostConfiguration/config.jelly+1 1 modified
    @@ -86,7 +86,7 @@
             <f:entry title="${%proxyUser}" field="proxyUser">
                 <f:textbox/>
             </f:entry>
    -        <f:entry title="${%proxyPassword}" field="proxyPassword">
    +        <f:entry title="${%proxyPassword}" field="secretProxyPassword">
                 <f:password/>
             </f:entry>
             
    

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

7

News mentions

0

No linked articles in our index yet.