VYPR
High severityNVD Advisory· Published Oct 16, 2019· Updated Aug 4, 2024

CVE-2019-10437

CVE-2019-10437

Description

CSRF in Jenkins CRX Content Package Deployer Plugin allowed attackers to capture stored credentials by tricking users into submitting malicious requests.

AI Insight

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

CSRF in Jenkins CRX Content Package Deployer Plugin allowed attackers to capture stored credentials by tricking users into submitting malicious requests.

Vulnerability

Description

A cross-site request forgery (CSRF) vulnerability exists in Jenkins CRX Content Package Deployer Plugin versions 1.8.1 and earlier. The plugin's form validation method did not require POST requests and lacked proper permission checks, allowing attackers to perform unauthorized actions on behalf of authenticated users [1][2].

Exploitation

Attackers can craft a malicious link or form that, when clicked by an authenticated Jenkins user with Overall/Read access, triggers a request to connect to an attacker-specified URL using attacker-specified credentials IDs. The credentials IDs can be obtained through another method (e.g., by exploiting a separate vulnerability) [1][2].

Impact

Successful exploitation enables the attacker to capture credentials stored in Jenkins, such as API tokens, passwords, or other secrets. This can lead to further compromise of Jenkins and connected systems, potentially allowing unauthorized access to sensitive resources [1][2].

Mitigation

The issue is fixed in CRX Content Package Deployer Plugin version 1.9.0. The fix adds the @RequirePOST annotation to the form validation method and implements proper permission checks to prevent CSRF and unauthorized access [3]. Users are strongly advised to upgrade to the latest version immediately.

AI Insight generated on May 22, 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:crx-content-package-deployerMaven
< 1.91.9

Affected products

2

Patches

1
1313c422170a

add @RequirePOST annotation and checkPermission configure

12 files changed · +100 72
  • src/main/java/org/jenkinsci/plugins/graniteclient/BuildPackageBuilder.java+12 7 modified
    @@ -27,10 +27,6 @@
     
     package org.jenkinsci.plugins.graniteclient;
     
    -import java.io.IOException;
    -import javax.annotation.Nonnull;
    -import javax.servlet.ServletException;
    -
     import com.cloudbees.plugins.credentials.common.AbstractIdCredentialsListBoxModel;
     import hudson.Extension;
     import hudson.FilePath;
    @@ -53,6 +49,11 @@
     import org.kohsuke.stapler.DataBoundConstructor;
     import org.kohsuke.stapler.DataBoundSetter;
     import org.kohsuke.stapler.QueryParameter;
    +import org.kohsuke.stapler.interceptor.RequirePOST;
    +
    +import javax.annotation.Nonnull;
    +import javax.servlet.ServletException;
    +import java.io.IOException;
     
     /**
      * Implementation of the "Build a Content Package on CRX" build step
    @@ -89,7 +90,7 @@ public BuildPackageBuilder(String packageId, String baseUrl, String credentialsI
         }
     
         public void perform(@Nonnull Run<?, ?> build, @Nonnull FilePath workspace, @Nonnull Launcher launcher,
    -                    @Nonnull TaskListener listener) throws InterruptedException, IOException {
    +                        @Nonnull TaskListener listener) throws InterruptedException, IOException {
     
             Result result = Result.SUCCESS;
             Result buildResult = build.getResult();
    @@ -269,18 +270,22 @@ public boolean isApplicable(Class<? extends AbstractProject> aClass) {
                 return true;
             }
     
    +        @RequirePOST
             public AbstractIdCredentialsListBoxModel doFillCredentialsIdItems(@AncestorInPath Item context,
                                                                               @QueryParameter("baseUrl") String baseUrl,
                                                                               @QueryParameter("value") String value) {
    +            context.checkPermission(Item.CONFIGURE);
                 return GraniteCredentialsListBoxModel.fillItems(value, context, baseUrl);
             }
     
    -        public FormValidation doTestConnection(@QueryParameter("baseUrl") final String baseUrl,
    +        @RequirePOST
    +        public FormValidation doTestConnection(@AncestorInPath Item context,
    +                                               @QueryParameter("baseUrl") final String baseUrl,
                                                    @QueryParameter("credentialsId") final String credentialsId,
                                                    @QueryParameter("requestTimeout") final long requestTimeout,
                                                    @QueryParameter("serviceTimeout") final long serviceTimeout)
                     throws IOException, ServletException {
    -
    +            context.checkPermission(Item.CONFIGURE);
                 return BaseUrlUtil.testOneConnection(baseUrl, credentialsId, requestTimeout, serviceTimeout);
             }
     
    
  • src/main/java/org/jenkinsci/plugins/graniteclient/DeployPackagesBuilder.java+35 30 modified
    @@ -27,23 +27,6 @@
     
     package org.jenkinsci.plugins.graniteclient;
     
    -import static org.jenkinsci.plugins.graniteclient.BaseUrlUtil.splitByNewline;
    -
    -import java.io.File;
    -import java.io.IOException;
    -import java.util.ArrayList;
    -import java.util.Arrays;
    -import java.util.Collections;
    -import java.util.Comparator;
    -import java.util.HashMap;
    -import java.util.HashSet;
    -import java.util.LinkedHashMap;
    -import java.util.List;
    -import java.util.Map;
    -import java.util.Set;
    -import javax.annotation.Nonnull;
    -import javax.servlet.ServletException;
    -
     import com.cloudbees.plugins.credentials.common.AbstractIdCredentialsListBoxModel;
     import hudson.Extension;
     import hudson.FilePath;
    @@ -70,6 +53,24 @@
     import org.kohsuke.stapler.DataBoundSetter;
     import org.kohsuke.stapler.QueryParameter;
     import org.kohsuke.stapler.StaplerRequest;
    +import org.kohsuke.stapler.interceptor.RequirePOST;
    +
    +import javax.annotation.Nonnull;
    +import javax.servlet.ServletException;
    +import java.io.File;
    +import java.io.IOException;
    +import java.util.ArrayList;
    +import java.util.Arrays;
    +import java.util.Collections;
    +import java.util.Comparator;
    +import java.util.HashMap;
    +import java.util.HashSet;
    +import java.util.LinkedHashMap;
    +import java.util.List;
    +import java.util.Map;
    +import java.util.Set;
    +
    +import static org.jenkinsci.plugins.graniteclient.BaseUrlUtil.splitByNewline;
     
     /**
      * Implementation of the "Deploy Content Packages to CRX" build step
    @@ -354,17 +355,17 @@ private Map<PackId, FilePath> selectPackages(@Nonnull final Run<?, ?> build,
     
                 Collections.sort(
                         listed, Collections.reverseOrder(
    -                    new Comparator<FilePath>() {
    -                        public int compare(FilePath left, FilePath right) {
    -                            try {
    -                                return Long.compare(left.lastModified(), right.lastModified());
    -                            } catch (Exception e) {
    -                                listener.error("Failed to compare a couple files: %s", e.getMessage());
    +                            new Comparator<FilePath>() {
    +                                public int compare(FilePath left, FilePath right) {
    +                                    try {
    +                                        return Long.compare(left.lastModified(), right.lastModified());
    +                                    } catch (Exception e) {
    +                                        listener.error("Failed to compare a couple files: %s", e.getMessage());
    +                                    }
    +                                    return 0;
    +                                }
                                 }
    -                            return 0;
    -                        }
    -                    }
    -            ));
    +                    ));
     
                 for (FilePath path : listed) {
                     PackId packId = path.act(new IdentifyPackageCallable());
    @@ -485,9 +486,11 @@ public boolean configure(StaplerRequest req, JSONObject json) throws FormExcepti
                 return true;
             }
     
    +        @RequirePOST
             public AbstractIdCredentialsListBoxModel doFillCredentialsIdItems(@AncestorInPath Item context,
                                                                               @QueryParameter("baseUrls") String baseUrls,
                                                                               @QueryParameter("value") String value) {
    +            context.checkPermission(Item.CONFIGURE);
                 List<String> _baseUrls = splitByNewline(baseUrls);
     
                 if (!_baseUrls.isEmpty()) {
    @@ -497,12 +500,14 @@ public AbstractIdCredentialsListBoxModel doFillCredentialsIdItems(@AncestorInPat
                 }
             }
     
    -        public FormValidation doTestConnection(@QueryParameter("baseUrls") final String baseUrls,
    +        @RequirePOST
    +        public FormValidation doTestConnection(@AncestorInPath Item context,
    +                                               @QueryParameter("baseUrls") final String baseUrls,
                                                    @QueryParameter("credentialsId") final String credentialsId,
                                                    @QueryParameter("requestTimeout") final long requestTimeout,
                                                    @QueryParameter("serviceTimeout") final long serviceTimeout)
                     throws IOException, ServletException {
    -
    +            context.checkPermission(Item.CONFIGURE);
                 return BaseUrlUtil.testManyConnections(baseUrls, credentialsId, requestTimeout, serviceTimeout);
             }
     
    @@ -515,7 +520,7 @@ public ListBoxModel doFillAcHandlingItems() {
                         ACHandling.MERGE,
                         ACHandling.OVERWRITE,
                         ACHandling.CLEAR)
    -                    ) {
    +            ) {
                     model.add(mode.getLabel(), mode.name());
                 }
                 return model;
    
  • src/main/java/org/jenkinsci/plugins/graniteclient/DownloadPackagesBuilder.java+14 9 modified
    @@ -27,13 +27,6 @@
     
     package org.jenkinsci.plugins.graniteclient;
     
    -import java.io.IOException;
    -import java.util.ArrayList;
    -import java.util.Collections;
    -import java.util.List;
    -import javax.annotation.Nonnull;
    -import javax.servlet.ServletException;
    -
     import com.cloudbees.plugins.credentials.common.AbstractIdCredentialsListBoxModel;
     import hudson.Extension;
     import hudson.FilePath;
    @@ -55,6 +48,14 @@
     import org.kohsuke.stapler.DataBoundConstructor;
     import org.kohsuke.stapler.DataBoundSetter;
     import org.kohsuke.stapler.QueryParameter;
    +import org.kohsuke.stapler.interceptor.RequirePOST;
    +
    +import javax.annotation.Nonnull;
    +import javax.servlet.ServletException;
    +import java.io.IOException;
    +import java.util.ArrayList;
    +import java.util.Collections;
    +import java.util.List;
     
     /**
      * Implementation of the "Download Content Packages from CRX" build step
    @@ -268,18 +269,22 @@ public boolean isApplicable(Class<? extends AbstractProject> aClass) {
                 return true;
             }
     
    +        @RequirePOST
             public AbstractIdCredentialsListBoxModel doFillCredentialsIdItems(@AncestorInPath Item context,
                                                                               @QueryParameter("baseUrl") String baseUrl,
                                                                               @QueryParameter("value") String value) {
    +            context.checkPermission(Item.CONFIGURE);
                 return GraniteCredentialsListBoxModel.fillItems(value, context, baseUrl);
             }
     
    -        public FormValidation doTestConnection(@QueryParameter("baseUrl") final String baseUrl,
    +        @RequirePOST
    +        public FormValidation doTestConnection(@AncestorInPath Item context,
    +                                               @QueryParameter("baseUrl") final String baseUrl,
                                                    @QueryParameter("credentialsId") final String credentialsId,
                                                    @QueryParameter("requestTimeout") final long requestTimeout,
                                                    @QueryParameter("serviceTimeout") final long serviceTimeout)
                     throws IOException, ServletException {
    -
    +            context.checkPermission(Item.CONFIGURE);
                 return BaseUrlUtil.testOneConnection(baseUrl, credentialsId, requestTimeout, serviceTimeout);
             }
     
    
  • src/main/java/org/jenkinsci/plugins/graniteclient/GraniteAHCFactory.java+3 0 modified
    @@ -55,6 +55,7 @@
     import org.kohsuke.stapler.AncestorInPath;
     import org.kohsuke.stapler.QueryParameter;
     import org.kohsuke.stapler.StaplerRequest;
    +import org.kohsuke.stapler.interceptor.RequirePOST;
     
     /**
      * Global extension and configurable factory for {@link AsyncHttpClient} instances
    @@ -144,8 +145,10 @@ public String getDisplayName() {
             return "CRX Content Package Deployer - HTTP Client";
         }
     
    +    @RequirePOST
         public AbstractIdCredentialsListBoxModel doFillCredentialsIdItems(@AncestorInPath Item context,
                                                                           @QueryParameter("value") String value) {
    +        context.checkPermission(Item.CONFIGURE);
             return GraniteCredentialsListBoxModel.fillItems(value, context);
         }
     
    
  • src/main/java/org/jenkinsci/plugins/graniteclient/PackageChoiceParameterDefinition.java+14 9 modified
    @@ -27,13 +27,6 @@
     
     package org.jenkinsci.plugins.graniteclient;
     
    -import java.io.IOException;
    -import java.util.ArrayList;
    -import java.util.Collections;
    -import java.util.Iterator;
    -import java.util.List;
    -import javax.servlet.ServletException;
    -
     import com.cloudbees.plugins.credentials.common.AbstractIdCredentialsListBoxModel;
     import hudson.Extension;
     import hudson.model.Item;
    @@ -52,6 +45,14 @@
     import org.kohsuke.stapler.DataBoundConstructor;
     import org.kohsuke.stapler.QueryParameter;
     import org.kohsuke.stapler.StaplerRequest;
    +import org.kohsuke.stapler.interceptor.RequirePOST;
    +
    +import javax.servlet.ServletException;
    +import java.io.IOException;
    +import java.util.ArrayList;
    +import java.util.Collections;
    +import java.util.Iterator;
    +import java.util.List;
     
     /**
      * Implementation of the "CRX Content Package Choice Parameter" type
    @@ -68,18 +69,22 @@ public String getDisplayName() {
                 return "CRX Content Package Choice Parameter";
             }
     
    -        public FormValidation doTestConnection(@QueryParameter("baseUrl") final String baseUrl,
    +        @RequirePOST
    +        public FormValidation doTestConnection(@AncestorInPath Item context,
    +                                               @QueryParameter("baseUrl") final String baseUrl,
                                                    @QueryParameter("credentialsId") final String credentialsId,
                                                    @QueryParameter("requestTimeout") final long requestTimeout,
                                                    @QueryParameter("serviceTimeout") final long serviceTimeout)
                     throws IOException, ServletException {
    -
    +            context.checkPermission(Item.CONFIGURE);
                 return BaseUrlUtil.testOneConnection(baseUrl, credentialsId, requestTimeout, serviceTimeout);
             }
     
    +        @RequirePOST
             public AbstractIdCredentialsListBoxModel doFillCredentialsIdItems(@AncestorInPath Item context,
                                                                               @QueryParameter("baseUrl") String baseUrl,
                                                                               @QueryParameter("value") String value) {
    +            context.checkPermission(Item.CONFIGURE);
                 return GraniteCredentialsListBoxModel.fillItems(value, context, baseUrl);
             }
     
    
  • src/main/java/org/jenkinsci/plugins/graniteclient/ReplicatePackagesBuilder.java+16 11 modified
    @@ -27,15 +27,6 @@
     
     package org.jenkinsci.plugins.graniteclient;
     
    -import static org.jenkinsci.plugins.graniteclient.BaseUrlUtil.splitByNewline;
    -
    -import java.io.IOException;
    -import java.util.ArrayList;
    -import java.util.Collections;
    -import java.util.List;
    -import javax.annotation.Nonnull;
    -import javax.servlet.ServletException;
    -
     import com.cloudbees.plugins.credentials.common.AbstractIdCredentialsListBoxModel;
     import hudson.Extension;
     import hudson.FilePath;
    @@ -57,6 +48,16 @@
     import org.kohsuke.stapler.DataBoundConstructor;
     import org.kohsuke.stapler.DataBoundSetter;
     import org.kohsuke.stapler.QueryParameter;
    +import org.kohsuke.stapler.interceptor.RequirePOST;
    +
    +import javax.annotation.Nonnull;
    +import javax.servlet.ServletException;
    +import java.io.IOException;
    +import java.util.ArrayList;
    +import java.util.Collections;
    +import java.util.List;
    +
    +import static org.jenkinsci.plugins.graniteclient.BaseUrlUtil.splitByNewline;
     
     /**
      * Implementation of the "Replicate Content Packages from CRX" build step
    @@ -240,9 +241,11 @@ public boolean isApplicable(Class<? extends AbstractProject> aClass) {
                 return true;
             }
     
    +        @RequirePOST
             public AbstractIdCredentialsListBoxModel doFillCredentialsIdItems(@AncestorInPath Item context,
                                                                               @QueryParameter("baseUrls") String baseUrls,
                                                                               @QueryParameter("value") String value) {
    +            context.checkPermission(Item.CONFIGURE);
                 List<String> _baseUrls = splitByNewline(baseUrls);
     
                 if (!_baseUrls.isEmpty()) {
    @@ -252,12 +255,14 @@ public AbstractIdCredentialsListBoxModel doFillCredentialsIdItems(@AncestorInPat
                 }
             }
     
    -        public FormValidation doTestConnection(@QueryParameter("baseUrls") final String baseUrls,
    +        @RequirePOST
    +        public FormValidation doTestConnection(@AncestorInPath Item context,
    +                                               @QueryParameter("baseUrls") final String baseUrls,
                                                    @QueryParameter("credentialsId") final String credentialsId,
                                                    @QueryParameter("requestTimeout") final long requestTimeout,
                                                    @QueryParameter("serviceTimeout") final long serviceTimeout)
                     throws IOException, ServletException {
    -
    +            context.checkPermission(Item.CONFIGURE);
                 return BaseUrlUtil.testManyConnections(baseUrls, credentialsId, requestTimeout, serviceTimeout);
             }
     
    
  • src/main/resources/org/jenkinsci/plugins/graniteclient/BuildPackageBuilder/config.jelly+1 1 modified
    @@ -54,7 +54,7 @@
     
         <f:advanced title="Connection Options">
             <f:entry title="Credentials" field="credentialsId">
    -            <creds:select />
    +            <creds:select checkMethod="post"/>
             </f:entry>
     
             <f:validateButton
    
  • src/main/resources/org/jenkinsci/plugins/graniteclient/DeployPackagesBuilder/config.jelly+1 1 modified
    @@ -69,7 +69,7 @@
         <f:advanced title="Connection Options">
     
             <f:entry title="Credentials" field="credentialsId">
    -            <creds:select />
    +            <creds:select checkMethod="post"/>
             </f:entry>
     
             <f:validateButton
    
  • src/main/resources/org/jenkinsci/plugins/graniteclient/DownloadPackagesBuilder/config.jelly+1 1 modified
    @@ -51,7 +51,7 @@
         <f:advanced title="Connection Options">
     
             <f:entry title="Credentials" field="credentialsId">
    -            <creds:select />
    +            <creds:select checkMethod="post"/>
             </f:entry>
     
             <f:validateButton
    
  • src/main/resources/org/jenkinsci/plugins/graniteclient/GraniteAHCFactory/global.jelly+1 1 modified
    @@ -30,7 +30,7 @@
         <f:section title="CRX Content Package Deployer - HTTP Client" name="GraniteAHCFactory">
     
             <f:entry title="Default Credentials" field="credentialsId">
    -            <creds:select />
    +            <creds:select checkMethod="post"/>
             </f:entry>
     
             <f:entry title="Preempt Login Base URL Patterns" field="preemptLoginForBaseUrls">
    
  • src/main/resources/org/jenkinsci/plugins/graniteclient/PackageChoiceParameterDefinition/config.jelly+1 1 modified
    @@ -68,7 +68,7 @@
         <f:advanced title="Connection Options">
     
             <f:entry title="Credentials" field="credentialsId">
    -            <creds:select />
    +            <creds:select checkMethod="post"/>
             </f:entry>
     
             <f:validateButton
    
  • src/main/resources/org/jenkinsci/plugins/graniteclient/ReplicatePackagesBuilder/config.jelly+1 1 modified
    @@ -43,7 +43,7 @@
         <f:advanced title="Connection Options">
     
             <f:entry title="Credentials" field="credentialsId">
    -            <creds:select />
    +            <creds:select checkMethod="post"/>
             </f:entry>
     
             <f:validateButton
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.