CVE-2022-36888
Description
Missing permission check in Jenkins HashiCorp Vault Plugin allows attackers with Overall/Read to retrieve arbitrary Vault credentials.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Missing permission check in Jenkins HashiCorp Vault Plugin allows attackers with Overall/Read to retrieve arbitrary Vault credentials.
Vulnerability
Overview
The Jenkins HashiCorp Vault Plugin versions 354.vdb_858fd6b_f48 and earlier contain a missing permission check in multiple doTestConnection methods. These methods are used to test connectivity to Vault and retrieve secrets. Specifically, the methods did not verify that the user has the Administer permission, allowing any user with Overall/Read permission to invoke them [1][2].
Exploitation
An attacker with Overall/Read permission (typically granted to all authenticated users) can call the vulnerable doTestConnection endpoints by providing arbitrary path and keys parameters. The plugin would then fetch the specified secrets from Vault and return them in the response, without any authorization check. No other special privileges or network access are required beyond Jenkins access [1][3].
Impact
Successful exploitation allows an attacker to read any credential stored in Vault that the Jenkins-Vault configuration can access. This includes passwords, API tokens, SSH keys, and other sensitive data. The impact is high as it compromises the confidentiality of secrets managed by Vault, potentially leading to further lateral movement or privilege escalation [1][2].
Mitigation
The issue is fixed in HashiCorp Vault Plugin version 355.v3b_38d767a_b_a_8 and later. Administrators should update immediately. The fix adds a permission check Jenkins.get().checkPermission(Jenkins.ADMINISTER) to all affected doTestConnection methods, ensuring only administrators can test connections [4]. No workarounds are available; upgrading is the only remediation.
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 |
|---|---|---|
com.datapipe.jenkins.plugins:hashicorp-vault-pluginMaven | < 355.v3b_38d767a_b_a_8 | 355.v3b_38d767a_b_a_8 |
Affected products
2- ghsa-coordsRange: < 355.v3b_38d767a_b_a_8
- Range: unspecified
Patches
13b38d767aba8[SECURITY-2593]
12 files changed · +46 −18
src/main/java/com/datapipe/jenkins/vault/credentials/common/VaultCertificateCredentialsImpl.java+3 −0 modified@@ -22,6 +22,7 @@ import java.util.logging.LogRecord; import java.util.logging.Logger; import java.util.regex.Pattern; +import jenkins.model.Jenkins; import org.kohsuke.stapler.AncestorInPath; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; @@ -145,6 +146,8 @@ public FormValidation doTestConnection( @QueryParameter("namespace") String namespace, @QueryParameter("engineVersion") Integer engineVersion) { + Jenkins.get().checkPermission(Jenkins.ADMINISTER); + try { getVaultSecretKey(path, defaultIfBlank(keyStoreKey, DEFAULT_KEYSTORE_KEY), prefixPath, namespace, engineVersion, context); } catch (Exception e) {
src/main/java/com/datapipe/jenkins/vault/credentials/common/VaultFileCredentialImpl.java+2 −0 modified@@ -12,6 +12,7 @@ import java.nio.charset.StandardCharsets; import java.util.Map; import java.util.UUID; +import jenkins.model.Jenkins; import net.sf.json.JSONObject; import org.kohsuke.stapler.AncestorInPath; import org.kohsuke.stapler.DataBoundConstructor; @@ -97,6 +98,7 @@ public FormValidation doTestConnection( @QueryParameter("namespace") String namespace, @QueryParameter("engineVersion") Integer engineVersion) { + Jenkins.get().checkPermission(Jenkins.ADMINISTER); String okMessage = "Successfully retrieved secret " + path;
src/main/java/com/datapipe/jenkins/vault/credentials/common/VaultGCRLoginImpl.java+2 −0 modified@@ -10,6 +10,7 @@ import hudson.util.Secret; import java.util.Map; import java.util.logging.Logger; +import jenkins.model.Jenkins; import net.sf.json.JSONObject; import org.kohsuke.stapler.AncestorInPath; import org.kohsuke.stapler.DataBoundConstructor; @@ -64,6 +65,7 @@ public FormValidation doTestConnection( @QueryParameter("namespace") String namespace, @QueryParameter("engineVersion") Integer engineVersion) { + Jenkins.get().checkPermission(Jenkins.ADMINISTER); String okMessage = "Successfully retrieved secret " + path;
src/main/java/com/datapipe/jenkins/vault/credentials/common/VaultSSHUserPrivateKeyImpl.java+3 −0 modified@@ -11,6 +11,7 @@ import java.util.Collections; import java.util.List; import java.util.logging.Logger; +import jenkins.model.Jenkins; import org.kohsuke.stapler.AncestorInPath; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; @@ -122,6 +123,8 @@ public FormValidation doTestConnection( @QueryParameter("namespace") String namespace, @QueryParameter("engineVersion") Integer engineVersion) { + Jenkins.get().checkPermission(Jenkins.ADMINISTER); + String username; try { username = getVaultSecretKey(path, defaultIfBlank(usernameKey, DEFAULT_USERNAME_KEY), prefixPath, namespace, engineVersion, context);
src/main/java/com/datapipe/jenkins/vault/credentials/common/VaultStringCredentialImpl.java+3 −0 modified@@ -8,6 +8,7 @@ import hudson.util.FormValidation; import hudson.util.ListBoxModel; import hudson.util.Secret; +import jenkins.model.Jenkins; import org.kohsuke.stapler.AncestorInPath; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; @@ -64,6 +65,8 @@ public FormValidation doTestConnection( @QueryParameter("namespace") String namespace, @QueryParameter("engineVersion") Integer engineVersion) { + Jenkins.get().checkPermission(Jenkins.ADMINISTER); + try { getVaultSecretKey(path, defaultIfBlank(vaultKey, DEFAULT_VAULT_KEY), prefixPath, namespace, engineVersion, context); } catch (Exception e) {
src/main/java/com/datapipe/jenkins/vault/credentials/common/VaultUsernamePasswordCredentialImpl.java+3 −0 modified@@ -8,6 +8,7 @@ import hudson.util.FormValidation; import hudson.util.ListBoxModel; import hudson.util.Secret; +import jenkins.model.Jenkins; import org.kohsuke.stapler.AncestorInPath; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; @@ -87,6 +88,8 @@ public FormValidation doTestConnection( @QueryParameter("namespace") String namespace, @QueryParameter("engineVersion") Integer engineVersion) { + Jenkins.get().checkPermission(Jenkins.ADMINISTER); + String username = null; try { username = getVaultSecretKey(path, defaultIfBlank(usernameKey, DEFAULT_USERNAME_KEY), prefixPath, namespace, engineVersion, context);
src/main/resources/com/datapipe/jenkins/vault/credentials/common/VaultCertificateCredentialsImpl/credentials.jelly+5 −3 modified@@ -1,6 +1,6 @@ <?jelly escape-by-default='true'?> -<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:st="jelly:stapler"> +<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:l="/lib/layout" xmlns:st="jelly:stapler"> <f:entry title="${%Namespace}" field="namespace"> <f:textbox/> </f:entry> @@ -21,7 +21,9 @@ </f:entry> <st:include page="id-and-description" class="${descriptor.clazz}"/> - <f:validateButton title="${%Test Vault Secrets retrieval}" progress="${%Testing retrieval of certificate...}" - method="testConnection" with="path,keyStoreKey,passwordKey,prefixPath,namespace,engineVersion" /> + <l:isAdmin> + <f:validateButton title="${%Test Vault Secrets retrieval}" progress="${%Testing retrieval of certificate...}" + method="testConnection" with="path,keyStoreKey,passwordKey,prefixPath,namespace,engineVersion" /> + </l:isAdmin> </j:jelly>
src/main/resources/com/datapipe/jenkins/vault/credentials/common/VaultFileCredentialImpl/credentials.jelly+5 −3 modified@@ -1,6 +1,6 @@ <?jelly escape-by-default='true'?> -<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:st="jelly:stapler"> +<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:l="/lib/layout" xmlns:st="jelly:stapler"> <f:entry title="${%Namespace}" field="namespace"> <f:textbox/> </f:entry> @@ -24,7 +24,9 @@ </f:entry> <st:include page="id-and-description" class="${descriptor.clazz}"/> - <f:validateButton title="${%Test Vault Secrets retrieval}" progress="${%Testing retrieval of key...}" - method="testConnection" with="path,useKey,vaultKey,prefixPath,namespace,engineVersion" /> + <l:isAdmin> + <f:validateButton title="${%Test Vault Secrets retrieval}" progress="${%Testing retrieval of key...}" + method="testConnection" with="path,useKey,vaultKey,prefixPath,namespace,engineVersion" /> + </l:isAdmin> </j:jelly>
src/main/resources/com/datapipe/jenkins/vault/credentials/common/VaultGCRLoginImpl/credentials.jelly+5 −3 modified@@ -1,6 +1,6 @@ <?jelly escape-by-default='true'?> -<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:st="jelly:stapler"> +<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:l="/lib/layout" xmlns:st="jelly:stapler"> <f:entry title="${%Namespace}" field="namespace"> <f:textbox/> </f:entry> @@ -15,7 +15,9 @@ </f:entry> <st:include page="id-and-description" class="${descriptor.clazz}"/> - <f:validateButton title="${%Test Vault Secrets retrieval}" progress="${%Testing retrieval of key...}" - method="testConnection" with="path,prefixPath,namespace,engineVersion" /> + <l:isAdmin> + <f:validateButton title="${%Test Vault Secrets retrieval}" progress="${%Testing retrieval of key...}" + method="testConnection" with="path,prefixPath,namespace,engineVersion" /> + </l:isAdmin> </j:jelly>
src/main/resources/com/datapipe/jenkins/vault/credentials/common/VaultSSHUserPrivateKeyImpl/credentials.jelly+5 −3 modified@@ -1,6 +1,6 @@ <?jelly escape-by-default='true'?> -<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:st="jelly:stapler"> +<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:l="/lib/layout" xmlns:st="jelly:stapler"> <f:entry title="${%Namespace}" field="namespace"> <f:textbox/> </f:entry> @@ -24,7 +24,9 @@ </f:entry> <st:include page="id-and-description" class="${descriptor.clazz}"/> - <f:validateButton title="${%Test Vault Secrets retrieval}" progress="${%Testing retrieval of username key...}" - method="testConnection" with="path,usernameKey,privateKeyKey,passphraseKey,prefixPath,namespace,engineVersion" /> + <l:isAdmin> + <f:validateButton title="${%Test Vault Secrets retrieval}" progress="${%Testing retrieval of username key...}" + method="testConnection" with="path,usernameKey,privateKeyKey,passphraseKey,prefixPath,namespace,engineVersion" /> + </l:isAdmin> </j:jelly>
src/main/resources/com/datapipe/jenkins/vault/credentials/common/VaultStringCredentialImpl/credentials.jelly+5 −3 modified@@ -1,6 +1,6 @@ <?jelly escape-by-default='true'?> -<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:st="jelly:stapler"> +<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:l="/lib/layout" xmlns:st="jelly:stapler"> <f:entry title="${%Namespace}" field="namespace"> <f:textbox/> </f:entry> @@ -18,7 +18,9 @@ </f:entry> <st:include page="id-and-description" class="${descriptor.clazz}"/> - <f:validateButton title="${%Test Vault Secrets retrieval}" progress="${%Testing retrieval of key...}" - method="testConnection" with="path,vaultKey,prefixPath,namespace,engineVersion" /> + <l:isAdmin> + <f:validateButton title="${%Test Vault Secrets retrieval}" progress="${%Testing retrieval of key...}" + method="testConnection" with="path,vaultKey,prefixPath,namespace,engineVersion" /> + </l:isAdmin> </j:jelly>
src/main/resources/com/datapipe/jenkins/vault/credentials/common/VaultUsernamePasswordCredentialImpl/credentials.jelly+5 −3 modified@@ -1,6 +1,6 @@ <?jelly escape-by-default='true'?> -<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:st="jelly:stapler"> +<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:l="/lib/layout" xmlns:st="jelly:stapler"> <f:entry title="${%Namespace}" field="namespace"> <f:textbox/> </f:entry> @@ -21,7 +21,9 @@ </f:entry> <st:include page="id-and-description" class="${descriptor.clazz}"/> - <f:validateButton title="${%Test Vault Secrets retrieval}" progress="${%Testing retrieval of username key...}" - method="testConnection" with="path,usernameKey,passwordKey,prefixPath,namespace,engineVersion" /> + <l:isAdmin> + <f:validateButton title="${%Test Vault Secrets retrieval}" progress="${%Testing retrieval of username key...}" + method="testConnection" with="path,usernameKey,passwordKey,prefixPath,namespace,engineVersion" /> + </l:isAdmin> </j:jelly>
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-vpf7-q2rx-26mhghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-36888ghsaADVISORY
- www.openwall.com/lists/oss-security/2022/07/27/1ghsamailing-listx_refsource_MLISTWEB
- github.com/jenkinsci/hashicorp-vault-plugin/commit/3b38d767aba8bd98d6f4fb53c1f1678d95b5e752ghsaWEB
- www.jenkins.io/security/advisory/2022-07-27/ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.