CVE-2022-29051
Description
Jenkins Publish Over FTP Plugin 1.16 and earlier allows attackers with Overall/Read permission to connect to an FTP server with attacker-specified credentials due to missing permission checks.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Jenkins Publish Over FTP Plugin 1.16 and earlier allows attackers with Overall/Read permission to connect to an FTP server with attacker-specified credentials due to missing permission checks.
Vulnerability
Missing permission checks in Jenkins Publish Over FTP Plugin 1.16 and earlier allow attackers with Overall/Read permission to connect to an FTP server using attacker-specified credentials. The doTestConnection method in the plugin lacked the necessary Jenkins.ADMINISTER permission check, which should have been required before allowing a connection test to an arbitrary FTP server. [1][4]
Exploitation
An attacker needs only Overall/Read permission (a low-privilege role in Jenkins) and network access to the Jenkins controller. By sending a crafted POST request to the doTestConnection endpoint with attacker-controlled parameters (hostname, username, password, etc.), the attacker can initiate a connection from the Jenkins server to an arbitrary FTP server they control. No further authentication or user interaction is required. [1][4]
Impact
A successful exploit allows the attacker to use the Jenkins controller as a proxy to connect to an FTP server with credentials of their choosing. This could be leveraged for information disclosure (e.g., verifying that the target FTP server is reachable, probing internal network hosts) or to perform reconnaissance. The attacker does not gain code execution or direct access to Jenkins credentials, but the Jenkins server's network position could be abused to confirm reachable FTP services. [1]
Mitigation
Jenkins Publish Over FTP Plugin version 1.17 includes the fix by adding the @RequirePOST annotation and a permission check for Jenkins.ADMINISTER on the doTestConnection method. Users should update to version 1.17 or later, released with the April 12, 2022 security advisory. No workarounds are documented; the recommended mitigation is to upgrade immediately. [1][4]
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-5pv7-hx9m-8jh3ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-29051ghsaADVISORY
- 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