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.
| Package | Affected versions | Patched versions |
|---|---|---|
org.jenkins-ci.plugins:publish-over-ftpMaven | < 1.17 | 1.17 |
Affected products
2- Range: unspecified
Patches
1b26520142855SECURITY-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- github.com/advisories/GHSA-6w39-qhmq-g8cpghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-29050ghsaADVISORY
- github.com/jenkinsci/publish-over-ftp-plugin/commit/b265201428557ab91304e06199ad38221efc23e7ghsaWEB
- www.jenkins.io/security/advisory/2022-04-12/ghsax_refsource_CONFIRMWEB
News mentions
1- Jenkins Security Advisory 2022-04-12Jenkins Security Advisories · Apr 12, 2022