VYPR
High severityNVD Advisory· Published Apr 12, 2022· Updated Aug 3, 2024

CVE-2022-29050

CVE-2022-29050

Description

CSRF in Jenkins Publish Over FTP Plugin 1.16 and earlier allows attackers to make Jenkins connect to an attacker-specified FTP server.

AI Insight

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

CSRF in Jenkins Publish Over FTP Plugin 1.16 and earlier allows attackers to make Jenkins connect to an attacker-specified FTP server.

Vulnerability

The Jenkins Publish Over FTP Plugin versions 1.16 and earlier do not require a POST request or permission check for the doTestConnection function, making it vulnerable to cross-site request forgery (CSRF) [1]. This function connects to an FTP server using attacker-specified credentials without proper validation [4].

Exploitation

An attacker can craft a malicious web page or form that, when visited by a Jenkins user with overall admin/configure permissions, triggers a request to the doTestConnection endpoint with attacker-controlled parameters [1]. The attacker must convince the user to interact with the malicious link, e.g., via phishing [1].

Impact

On successful exploitation, the attacker makes Jenkins connect to an FTP server controlled by the attacker using the provided credentials [1]. This can lead to information disclosure if the FTP server responds with unexpected data, or be leveraged for further attacks [1].

Mitigation

The vulnerability is fixed in Publish Over FTP Plugin version 1.17, released on 2022-04-12 [1]. The fix adds the @RequirePOST annotation and a permission check (Jenkins.ADMINISTER) to the doTestConnection method [4]. Users should upgrade to version 1.17 or later [1].

AI Insight generated on May 21, 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.plugins:publish-over-ftpMaven
< 1.171.17

Affected products

2

Patches

1
b26520142855

SECURITY-2321

4 files changed · +17 2
  • pom.xml+1 0 modified
    @@ -41,6 +41,7 @@
     
         <properties>
             <findbugs.failOnError>false</findbugs.failOnError>
    +        <spotbugs.skip>true</spotbugs.skip>
             <jenkins.version>2.289.1</jenkins.version>
             <java.level>8</java.level>
         </properties>
    
  • src/main/java/jenkins/plugins/publish_over_ftp/descriptor/BapFtpCredentialsDescriptor.java+11 2 modified
    @@ -26,13 +26,16 @@
     
     import hudson.Extension;
     import hudson.model.Descriptor;
    +import hudson.model.Item;
     import hudson.util.FormValidation;
     import jenkins.model.Jenkins;
     import jenkins.plugins.publish_over.BPBuildInfo;
     import jenkins.plugins.publish_over_ftp.BapFtpCredentials;
     import jenkins.plugins.publish_over_ftp.BapFtpHostConfiguration;
     import jenkins.plugins.publish_over_ftp.BapFtpPublisherPlugin;
     import org.kohsuke.stapler.QueryParameter;
    +import org.kohsuke.stapler.interceptor.RequirePOST;
    +import org.kohsuke.stapler.AncestorInPath;
     
     @Extension
     public class BapFtpCredentialsDescriptor extends Descriptor<BapFtpCredentials> {
    @@ -54,8 +57,14 @@ public FormValidation doCheckPassword(@QueryParameter final String value) {
             return FormValidation.validateRequired(value);
         }
     
    +    @RequirePOST
         public FormValidation doTestConnection(@QueryParameter final String configName, @QueryParameter final String username,
    -                                           @QueryParameter final String password) {
    +                                           @QueryParameter final String password, @AncestorInPath Item item) {
    +            if (item == null) {
    +                Jenkins.get().checkPermission(Jenkins.ADMINISTER);
    +            } else {
    +                item.checkPermission(Item.CONFIGURE);
    +            }
             final BapFtpCredentials credentials = new BapFtpCredentials(username, password);
             final BPBuildInfo buildInfo = BapFtpPublisherPluginDescriptor.createDummyBuildInfo();
             buildInfo.put(BPBuildInfo.OVERRIDE_CREDENTIALS_CONTEXT_KEY, credentials);
    @@ -69,4 +78,4 @@ public jenkins.plugins.publish_over.view_defaults.HostConfiguration.Messages get
             return new jenkins.plugins.publish_over.view_defaults.HostConfiguration.Messages();
         }
     
    -}
    \ No newline at end of file
    +}
    
  • src/main/java/jenkins/plugins/publish_over_ftp/descriptor/BapFtpHostConfigurationDescriptor.java+2 0 modified
    @@ -33,6 +33,7 @@
     import jenkins.plugins.publish_over_ftp.BapFtpPublisherPlugin;
     import jenkins.plugins.publish_over_ftp.Messages;
     import org.kohsuke.stapler.QueryParameter;
    +import org.kohsuke.stapler.interceptor.RequirePOST;
     
     @Extension
     public class BapFtpHostConfigurationDescriptor extends Descriptor<BapFtpHostConfiguration> {
    @@ -70,6 +71,7 @@ public FormValidation doCheckTimeout(@QueryParameter final String value) {
             return FormValidation.validateNonNegativeInteger(value);
         }
     
    +    @RequirePOST
         public FormValidation doTestConnection(@QueryParameter final String name, @QueryParameter final String hostname,
                 @QueryParameter final String username, @QueryParameter final String encryptedPassword,
                 @QueryParameter final String remoteRootDir, @QueryParameter final int port,
    
  • src/main/java/jenkins/plugins/publish_over_ftp/descriptor/BapFtpPublisherPluginDescriptor.java+3 0 modified
    @@ -43,6 +43,7 @@
     import jenkins.plugins.publish_over_ftp.options.FtpPluginDefaults;
     import net.sf.json.JSONObject;
     import org.kohsuke.stapler.StaplerRequest;
    +import org.kohsuke.stapler.interceptor.RequirePOST;
     
     import java.util.List;
     
    @@ -128,11 +129,13 @@ public jenkins.plugins.publish_over.view_defaults.manage_jenkins.Messages getCom
             return new jenkins.plugins.publish_over.view_defaults.manage_jenkins.Messages();
         }
     
    +    @RequirePOST
         public FormValidation doTestConnection(final String name, final String hostname, final String username,
                 final String encryptedPassword, final String remoteRootDir, final int port, final int timeout,
                 final boolean useActiveData, final String controlEncoding, final boolean disableMakeNestedDirs,
                 final boolean disableRemoteVerification, final boolean useFtpOverTls, final boolean useImplicitTls,
                 final String trustedCertificate) {
    +        Jenkins.get().checkPermission(Jenkins.ADMINISTER);
             final BapFtpHostConfiguration hostConfig = new BapFtpHostConfiguration(name, hostname, username,
                     encryptedPassword, remoteRootDir, port, timeout, useActiveData, controlEncoding,
                     disableMakeNestedDirs, disableRemoteVerification);
    

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