VYPR
Moderate severityNVD Advisory· Published May 16, 2023· Updated Jan 23, 2025

CVE-2023-32982

CVE-2023-32982

Description

Jenkins Ansible Plugin stores extra variables unencrypted in job config.xml files, exposing secrets to users with Item/Extended Read or file system access.

AI Insight

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

Jenkins Ansible Plugin stores extra variables unencrypted in job config.xml files, exposing secrets to users with Item/Extended Read or file system access.

What the vulnerability is

The Jenkins Ansible Plugin, up to version 204.v8191fd551eb_f and earlier, stores extra variables (extraVars) for Ansible playbook jobs in plaintext within job config.xml files on the Jenkins controller [1][2]. This means that sensitive information such as passwords, API keys, or other secrets passed as extra variables are not encrypted or masked in the configuration file.

## How it's exploited An attacker needs either the Item/Extended Read permission for the affected job, or direct access to the Jenkins controller's file system to read the config.xml files [2]. No additional authentication or network position beyond those permissions is required. The vulnerability is in how the plugin serializes extra variable values; it previously used getValue() which returns the plaintext, while the fix changes to getSecretValue().getPlainText() indicating that the plugin now leverages Jenkins' secret handling to mask the value in XML output [3].

Impact

A successful exploitation allows an attacker to view all extra variables configured for any job using the Ansible Plugin, potentially revealing credentials or other sensitive data that can be used for further attacks [1][2].

Mitigation

Users should update the Jenkins Ansible Plugin to version 205.v4cb_c3a_48c0a_b or later, which includes the fix to store extra variables as masked secrets [1][3]. There is no mention of workarounds in the advisories.

AI Insight generated on May 20, 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:ansibleMaven
< 205.v4cb205.v4cb

Affected products

2

Patches

1
4cbc48657c21

SECURITY-3017

https://github.com/jenkinsci/ansible-pluginValentin DelayeMay 15, 2023via ghsa
7 files changed · +34 20
  • src/main/java/org/jenkinsci/plugins/ansible/AbstractAnsibleInvocation.java+1 1 modified
    @@ -121,7 +121,7 @@ public ArgumentListBuilder appendExtraVars(ArgumentListBuilder args) {
             if (extraVars != null && ! extraVars.isEmpty()) {
                 for (ExtraVar var : extraVars) {
                     args.add("-e");
    -                String value = envVars.expand(var.getValue());
    +                String value = envVars.expand(var.getSecretValue().getPlainText());
                     if (Pattern.compile("\\s").matcher(value).find()) {
                         value = Util.singleQuote(value);
                     }
    
  • src/main/java/org/jenkinsci/plugins/ansible/ExtraVar.java+19 8 modified
    @@ -18,42 +18,53 @@
     import hudson.Extension;
     import hudson.model.AbstractDescribableImpl;
     import hudson.model.Descriptor;
    +import hudson.util.Secret;
    +
     import org.kohsuke.stapler.DataBoundConstructor;
     import org.kohsuke.stapler.DataBoundSetter;
     
     public class ExtraVar extends AbstractDescribableImpl<ExtraVar> {
     
         public String key;
     
    -    public String value;
    +    public transient String value;
    +
    +    public Secret secretValue;
     
    -    public boolean hidden;
    +    public boolean hidden = true;
     
         @DataBoundConstructor
         public ExtraVar() {
         }
     
    +    protected Object readResolve() {
    +        if (value != null) {
    +            this.setSecretValue(Secret.fromString(value));
    +        }
    +        return this;
    +    }
    +
         @DataBoundSetter
         public void setKey(String key) {
             this.key = key;
         }
     
         @DataBoundSetter
    -    public void setValue(String value) {
    -        this.value = value;
    +    public void setHidden(boolean hidden) {
    +        this.hidden = hidden;
         }
     
         @DataBoundSetter
    -    public void setHidden(boolean hidden) {
    -        this.hidden = hidden;
    +    public void setSecretValue(Secret value) {
    +        this.secretValue = value;
         }
     
         public String getKey() {
             return key;
         }
     
    -    public String getValue() {
    -        return value;
    +    public Secret getSecretValue() {
    +        return this.secretValue;
         }
     
         public boolean isHidden() {
    
  • src/main/java/org/jenkinsci/plugins/ansible/jobdsl/context/ExtraVarsContext.java+3 1 modified
    @@ -6,6 +6,8 @@
     import javaposse.jobdsl.dsl.Context;
     import org.jenkinsci.plugins.ansible.ExtraVar;
     
    +import hudson.util.Secret;
    +
     /**
      * @author pawbur (Pawel Burchard)
      */
    @@ -15,7 +17,7 @@ public class ExtraVarsContext implements Context {
         public void extraVar(String key, String value, boolean hidden) {
             ExtraVar extraVar = new ExtraVar();
             extraVar.setKey(key);
    -        extraVar.setValue(value);
    +        extraVar.setSecretValue(Secret.fromString(value));
             extraVar.setHidden(hidden);
             this.extraVars.add(extraVar);
         }
    
  • src/main/java/org/jenkinsci/plugins/ansible/workflow/AnsiblePlaybookStep.java+3 2 modified
    @@ -38,6 +38,7 @@
     import hudson.model.Run;
     import hudson.model.TaskListener;
     import hudson.util.ListBoxModel;
    +import hudson.util.Secret;
     import jenkins.model.Jenkins;
     import org.apache.commons.lang.StringUtils;
     import org.jenkinsci.plugins.ansible.AnsibleInstallation;
    @@ -383,10 +384,10 @@ private List<ExtraVar> convertExtraVars(Map<String, Object> extraVars) {
                     var.setKey(entry.getKey());
                     Object o = entry.getValue();
                     if (o instanceof Map) {
    -                    var.setValue(((Map)o).get("value").toString());
    +                    var.setSecretValue((Secret)((Map)o).get("value"));
                         var.setHidden((Boolean)((Map)o).get("hidden"));
                     } else {
    -                    var.setValue(o.toString());
    +                    var.setSecretValue((Secret)o);
                         var.setHidden(false);
                     }
                     extraVarList.add(var);
    
  • src/main/resources/org/jenkinsci/plugins/ansible/AnsibleAdHocCommandBuilder/config.jelly+3 3 modified
    @@ -71,11 +71,11 @@
               <f:entry title="${%Key}" field="key">
                 <f:textbox  clazz="required" />
               </f:entry>
    -          <f:entry title="${%Value}" field="value">
    -            <f:textbox clazz="required" />
    +          <f:entry title="${%Value}" field="secretValue">
    +            <f:password clazz="required" />
               </f:entry>
               <f:entry title="${%Hidden variable in build log}" field="hidden">
    -            <f:checkbox default="false" />
    +            <f:checkbox default="true" />
               </f:entry>
               <f:entry>
                 <div align="right" class="repeatable-delete show-if-only">
    
  • src/main/resources/org/jenkinsci/plugins/ansible/AnsiblePlaybookBuilder/config.jelly+3 3 modified
    @@ -80,11 +80,11 @@
               <f:entry title="${%Key}" field="key">
                 <f:textbox  clazz="required" />
               </f:entry>
    -          <f:entry title="${%Value}" field="value">
    -            <f:textbox clazz="required" />
    +          <f:entry title="${%Value}" field="secretValue">
    +            <f:password clazz="required" />
               </f:entry>
               <f:entry title="${%Hidden variable in build log}" field="hidden">
    -            <f:checkbox default="false" />
    +            <f:checkbox default="true" />
               </f:entry>
               <f:entry>
                 <div align="right" class="repeatable-delete show-if-only">
    
  • src/test/java/org/jenkinsci/plugins/ansible/jobdsl/JobDslIntegrationTest.java+2 2 modified
    @@ -64,7 +64,7 @@ public void shouldCreateJobWithPlaybookDsl() throws Exception {
             assertThat("disableHostKeyChecking", step.disableHostKeyChecking, is(false));
             assertThat("additionalParameters", step.additionalParameters, is("params"));
             assertThat("extraVar.key", step.extraVars.get(0).getKey(), is("key"));
    -        assertThat("extraVar.value", step.extraVars.get(0).getValue(), is("value"));
    +        assertThat("extraVar.value", step.extraVars.get(0).getSecretValue().getPlainText(), is("value"));
             assertThat("extraVar.hidden", step.extraVars.get(0).isHidden(), is(true));
     
         }
    @@ -93,7 +93,7 @@ public void shouldCreateJobWithLegacyPlaybookDsl() throws Exception {
             assertThat("disableHostKeyChecking", step.disableHostKeyChecking, is(true));
             assertThat("additionalParameters", step.additionalParameters, is("params"));
             assertThat("extraVar.key", step.extraVars.get(0).getKey(), is("key"));
    -        assertThat("extraVar.value", step.extraVars.get(0).getValue(), is("value"));
    +        assertThat("extraVar.value", step.extraVars.get(0).getSecretValue().getPlainText(), is("value"));
             assertThat("extraVar.hidden", step.extraVars.get(0).isHidden(), is(true));
     
         }
    

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