VYPR
Moderate severityNVD Advisory· Published Apr 2, 2025· Updated Apr 3, 2025

CVE-2025-31724

CVE-2025-31724

Description

Jenkins Cadence vManager Plugin 4.0.0-282.v5096a_c2db_275 and earlier stores Verisium Manager vAPI keys unencrypted in job config.xml files on the Jenkins controller where they can be viewed by users with Extended Read permission, or access to the Jenkins controller file system.

AI Insight

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

Jenkins Cadence vManager Plugin stores Verisium Manager vAPI keys unencrypted in job config.xml, allowing users with Extended Read permission or file system access to view them.

Vulnerability

Description

The Jenkins Cadence vManager Plugin, up to version 4.0.0-282.v5096a_c2db_275, stores Verisium Manager vAPI keys unencrypted in job config.xml files on the Jenkins controller [1][2][3]. This means the sensitive credentials are persisted in plain text, contrary to the Jenkins security best practice of using the Secret class to encrypt such values.

Exploitation

Prerequisites

An attacker can exploit this vulnerability if they have either Extended Read permission on a job or direct access to the Jenkins controller's file system [2][3]. Extended Read permission allows users to view job configurations, including the unencrypted vAPI key. Alternatively, any user with file system access (e.g., through a compromised account or physical access) can read the config.xml files directly.

Impact

If an attacker obtains the vAPI key, they can make unauthorized API calls to the Verisium Manager service, potentially accessing or modifying test data, coverage reports, and other sensitive information managed by Cadence Verisium Manager [2]. This could lead to data breaches or manipulation of verification results.

Mitigation

The vulnerability has been addressed in a commit that changes the vAPIPassword field type from String to Secret (using hudson.util.Secret) and removes the plain-text getter method [4]. Users should update to a fixed version of the plugin once released. As of the advisory date, users are advised to ensure that only trusted users have Extended Read permission and to restrict file system access to the Jenkins controller [2].

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:vmanager-pluginMaven
< 4.0.14.0.1

Affected products

2

Patches

1
9e25a740ba48

Addressing deprecations has enhanced security.

13 files changed · +197 159
  • pom.xml+1 1 modified
    @@ -22,7 +22,7 @@
       </licenses>
    
       
    
       <properties>
    
    -    <revision>4.0.0</revision>
    
    +    <revision>4.0.1</revision>
    
         <changelist>999999-SNAPSHOT</changelist>
    
         <gitHubRepo>jenkinsci/vmanager-plugin</gitHubRepo>
    
         <findbugs.failOnError>false</findbugs.failOnError>
    
    
  • README.md+5 0 modified
    @@ -554,6 +554,11 @@ the following format within the job working directory: 
     
    
     ## Change Log
    
     
    
    +##### Version 4.0.1 (March 31, 2025)
    
    +-	Fixed deprecations in 3rd party libraries
    
    +-   Security fix - Now using Jenkins Secret Object to Encrypt saved passwords
    
    +-   Breaking Change - You may need to reconfigure the passwords saved within the job.
    
    +
    
     ##### Version 4.0.0 (Feb 18, 2025)
    
     -	Breaking Change - Only compatible with Jenkins version 2.479 and higher
    
     -	Added Support in Java 17
    
    
  • src/main/java/org/jenkinsci/plugins/vmanager/dsl/post/DSLBuildAction.java+1 1 modified
    @@ -19,7 +19,7 @@
     
     public class DSLBuildAction extends PostActionBase implements Serializable, RunAction2,  SimpleBuildStep.LastBuildAction  {
     
    -    private static final long serialVersionUID = 2000009076155338046L;
    +    private static final long serialVersionUID = 2000009076155338047L;
         
         private String message;
         private transient Run<?, ?> build;
    
  • src/main/java/org/jenkinsci/plugins/vmanager/dsl/post/DSLProjectAction.java+1 1 modified
    @@ -14,7 +14,7 @@
     
     public class DSLProjectAction extends PostActionBase implements Serializable, Action {
     
    -    private static final long serialVersionUID = 3000009076155338046L;
    +    private static final long serialVersionUID = 3000009076155338047L;
         private transient  Job<?, ?> project;
     
         @Override
    
  • src/main/java/org/jenkinsci/plugins/vmanager/dsl/post/DSLPublisher.java+35 31 modified
    @@ -19,6 +19,7 @@
     import hudson.security.ACL;
    
     import hudson.util.FormValidation;
    
     import hudson.util.ListBoxModel;
    
    +import hudson.util.Secret;
    
     import net.sf.json.JSONObject;
    
     import org.kohsuke.stapler.DataBoundConstructor;
    
     import org.kohsuke.stapler.StaplerRequest2;
    
    @@ -40,14 +41,14 @@
     
    
     public class DSLPublisher extends Recorder implements SimpleBuildStep, Serializable {
    
     
    
    -    private static final long serialVersionUID = 4000009076155338046L;
    
    +    private static final long serialVersionUID = 4000009076155338047L;
    
         private transient Run<?, ?> build;
    
     
    
         private String vAPIUrl;
    
         private boolean authRequired;
    
         private boolean advConfig;
    
         private String vAPIUser;
    
    -    private String vAPIPassword;
    
    +    private Secret vAPIPassword;
    
         private boolean dynamicUserId;
    
         private int connTimeout = 1;
    
         private int readTimeout = 30;
    
    @@ -93,7 +94,7 @@ public class DSLPublisher extends Recorder implements SimpleBuildStep, Serializa
     
    
         // Fields in config.jelly must match the parameter names in the "DataBoundConstructor"
    
         @DataBoundConstructor
    
    -    public DSLPublisher(String vAPIUrl, String vAPIUser, String vAPIPassword, boolean authRequired, boolean advConfig, boolean dynamicUserId, int connTimeout, int readTimeout, boolean advancedFunctions,
    
    +    public DSLPublisher(String vAPIUrl, String vAPIUser, Secret vAPIPassword, boolean authRequired, boolean advConfig, boolean dynamicUserId, int connTimeout, int readTimeout, boolean advancedFunctions,
    
                 boolean retrieveSummaryReport, boolean runReport, boolean metricsReport, boolean vPlanReport, String testsViewName, String metricsViewName, String vplanViewName, int testsDepth, int metricsDepth,
    
                 int vPlanDepth, String metricsInputType, String metricsAdvanceInput, String vPlanInputType, String vPlanAdvanceInput, String vPlanxFileName, String summaryType, boolean ctxInput,
    
                 String ctxAdvanceInput, String freeVAPISyntax, boolean deleteReportSyntaxInputFile, String vManagerVersion, boolean sendEmail, String emailList, String emailType, String emailInputFile, boolean deleteEmailInputFile, String summaryMode, boolean ignoreSSLError, String vAPICredentials, String credentialType) {
    
    @@ -144,7 +145,6 @@ public DSLPublisher(String vAPIUrl, String vAPIUser, String vAPIPassword, boolea
             vAPIConnectionParam.authRequired = authRequired;
    
             vAPIConnectionParam.advConfig = advConfig;
    
             vAPIConnectionParam.vAPIUser = vAPIUser;
    
    -        vAPIConnectionParam.vAPIPassword = vAPIPassword;
    
             vAPIConnectionParam.connTimeout = connTimeout;
    
             vAPIConnectionParam.readTimeout = readTimeout;
    
     
    
    @@ -317,10 +317,6 @@ public String getVAPIUser() {
             return vAPIUser;
    
         }
    
     
    
    -    public String getVAPIPassword() {
    
    -        return vAPIPassword;
    
    -    }
    
    -
    
         public boolean isDynamicUserId() {
    
             return dynamicUserId;
    
         }
    
    @@ -341,9 +337,17 @@ public String getCredentialType() {
             return credentialType;
    
         }
    
     
    
    +    public Secret getVAPIPassword() {
    
    +        return vAPIPassword;
    
    +    }
    
    +
    
         @Override
    
         public void perform(@Nonnull Run<?, ?> run, @Nonnull FilePath fp, @Nonnull Launcher launcher, @Nonnull TaskListener tl) throws InterruptedException, IOException {
    
     
    
    +        
    
    +        String vAPIPassword = getVAPIPassword().getPlainText();  
    
    +
    
    +        
    
             this.build = run;
    
             DSLBuildAction buildAction = new DSLBuildAction("NA", run);
    
             List<DSLBuildAction> buildActionList = run.getActions(DSLBuildAction.class);
    
    @@ -361,6 +365,8 @@ public void perform(@Nonnull Run<?, ?> run, @Nonnull FilePath fp, @Nonnull Launc
                         vAPIConnectionParam.vAPIUser = c.getUsername();
    
                         vAPIConnectionParam.vAPIPassword = c.getPassword().getPlainText();
    
                     }
    
    +            } else {
    
    +                vAPIConnectionParam.vAPIPassword = vAPIPassword;
    
                 }
    
     
    
                 if (retrieveSummaryReport) {
    
    @@ -428,20 +434,19 @@ public boolean configure(StaplerRequest2 req, JSONObject formData) throws FormEx
                 return super.configure(req, formData);
    
             }
    
     
    
    -        public FormValidation doTestConnection(@QueryParameter("vAPIUser") final String vAPIUser, @QueryParameter("vAPIPassword") final String vAPIPassword,
    
    +        public FormValidation doTestConnection(@QueryParameter("vAPIUser") final String vAPIUser, @QueryParameter("vAPIPassword") final Secret vAPIPassword,
    
                     @QueryParameter("vAPIUrl") final String vAPIUrl, @QueryParameter("authRequired") final boolean authRequired,
    
                     @QueryParameter("credentialType") final String credentialType, @QueryParameter("vAPICredentials") final String vAPICredentials, @AncestorInPath Item item)
    
                     throws IOException, ServletException {
    
                 try {
    
     
    
                     String tempUser = vAPIUser;
    
    -                String tempPassword = vAPIPassword;
    
    +                String tempPassword = vAPIPassword.getPlainText();;
    
    +               
    
    +
    
                     boolean foundMatchUserPassword = false;
    
                     if ("credential".equals(credentialType)) {
    
    -                    //System.out.println("Trying to find the credential...");
    
    -                    //overwrite the plain text with the credentials
    
    -                    //StandardUsernamePasswordCredentials c = CredentialsProvider.findCredentialById(vAPICredentials, StandardUsernamePasswordCredentials.class, item, Collections.<DomainRequirement>emptyList());
    
    -                    List<StandardUsernamePasswordCredentials> listOfC = CredentialsProvider.lookupCredentials(StandardUsernamePasswordCredentials.class, item, ACL.SYSTEM, Collections.<DomainRequirement>emptyList());
    
    +                    List<StandardUsernamePasswordCredentials> listOfC = CredentialsProvider.lookupCredentialsInItem(StandardUsernamePasswordCredentials.class, item, ACL.SYSTEM2, Collections.<DomainRequirement>emptyList());
    
                         Iterator<StandardUsernamePasswordCredentials> cIterator = listOfC.iterator();
    
                         StandardUsernamePasswordCredentials tmpHolder = null;
    
                         while (cIterator.hasNext()) {
    
    @@ -491,47 +496,46 @@ public ListBoxModel doFillVAPICredentialsItems(
             ) {
    
                 StandardListBoxModel result = new StandardListBoxModel();
    
                 if (item == null) {
    
    -                if (!Jenkins.getInstance().hasPermission(Jenkins.ADMINISTER)) {
    
    -                    return result.includeCurrentValue(vAPICredentials); // (2)
    
    +                if (!Jenkins.get().hasPermission(Jenkins.ADMINISTER)) {
    
    +                    return result.includeCurrentValue(vAPICredentials); 
    
                     }
    
                 } else {
    
                     if (!item.hasPermission(Item.EXTENDED_READ)
    
                             && !item.hasPermission(CredentialsProvider.USE_ITEM)) {
    
    -                    return result.includeCurrentValue(vAPICredentials); // (2)
    
    +                    return result.includeCurrentValue(vAPICredentials); 
    
                     }
    
                 }
    
                 return result
    
                         .includeEmptyValue()
    
    -                    .includeMatchingAs(ACL.SYSTEM, Jenkins.getInstance(), StandardUsernamePasswordCredentials.class, Collections.<DomainRequirement>emptyList(), CredentialsMatchers.always())
    
    -                    .includeCurrentValue(vAPICredentials); // (5)
    
    +                    .includeMatchingAs(ACL.SYSTEM2, Jenkins.get(), StandardUsernamePasswordCredentials.class, Collections.<DomainRequirement>emptyList(), CredentialsMatchers.always())
    
    +                    .includeCurrentValue(vAPICredentials); 
    
     
    
             }
    
     
    
             public FormValidation doCheckVAPICredentials(
    
    -                @AncestorInPath Item item, // (2)
    
    -                @QueryParameter String value // (1)
    
    +                @AncestorInPath Item item, 
    
    +                @QueryParameter String value 
    
     
    
             ) {
    
                 if (item == null) {
    
    -                if (!Jenkins.getInstance().hasPermission(Jenkins.ADMINISTER)) {
    
    -                    return FormValidation.ok(); // (3)
    
    +                if (!Jenkins.get().hasPermission(Jenkins.ADMINISTER)) {
    
    +                    return FormValidation.ok(); 
    
                     }
    
                 } else {
    
                     if (!item.hasPermission(Item.EXTENDED_READ)
    
                             && !item.hasPermission(CredentialsProvider.USE_ITEM)) {
    
    -                    return FormValidation.ok(); // (3)
    
    +                    return FormValidation.ok(); 
    
                     }
    
                 }
    
    -            if (StringUtils.isBlank(value)) { // (4)
    
    -                return FormValidation.ok(); // (4)
    
    +            if (StringUtils.isBlank(value)) { 
    
    +                return FormValidation.ok(); 
    
                 }
    
    -            //.includeMatchingAs(ACL.SYSTEM,Jenkins.getInstance(),StandardUsernamePasswordCredentials.class,Collections.<DomainRequirement>emptyList(),CredentialsMatchers.always())
    
    -            if (CredentialsProvider.listCredentials( // (6)
    
    -                    StandardUsernamePasswordCredentials.class, // (1)
    
    +            if (CredentialsProvider.listCredentialsInItem( 
    
    +                    StandardUsernamePasswordCredentials.class, 
    
                         item,
    
    -                    ACL.SYSTEM,
    
    +                    ACL.SYSTEM2,
    
                         Collections.<DomainRequirement>emptyList(),
    
    -                    CredentialsMatchers.always() // (6)
    
    +                    CredentialsMatchers.always() 
    
                 ).isEmpty()) {
    
                     return FormValidation.error("Cannot find currently selected credentials");
    
                 }
    
    
  • src/main/java/org/jenkinsci/plugins/vmanager/dsl/post/ReportBuildAction.java+1 1 modified
    @@ -15,7 +15,7 @@
     
    
     public class ReportBuildAction extends PostActionBase implements Serializable, RunAction2 {
    
         
    
    -    private static final long serialVersionUID = 5000009076155338046L;
    
    +    private static final long serialVersionUID = 5000009076155338047L;
    
         private transient Run<?, ?> build;
    
         private transient TaskListener listener;
    
         private transient ReportManager reportManager;
    
    
  • src/main/java/org/jenkinsci/plugins/vmanager/dsl/post/VMGRPostLaunchStepImpl.java+6 6 modified
    @@ -5,20 +5,20 @@
     import hudson.Launcher;
     import hudson.model.Run;
     import hudson.model.TaskListener;
    -//import org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution;
    +import hudson.util.Secret;
    +
     import org.jenkinsci.plugins.workflow.steps.StepContext;
     import org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution;
    -//import org.jenkinsci.plugins.workflow.steps.StepContextParameter;
    +
     
     public class VMGRPostLaunchStepImpl extends SynchronousNonBlockingStepExecution<Void> {
         
    -   private static final long serialVersionUID = 6000009076155338046L;
    +   private static final long serialVersionUID = 6000009076155338047L;
        private transient final VMGRPostLaunchStep step;
        
        VMGRPostLaunchStepImpl(VMGRPostLaunchStep step, StepContext context) {
             super(context);
             this.step = step;
    -        
         }
        
       
    @@ -35,8 +35,8 @@ protected Void run() throws Exception {
            DSLPublisher publisher;
            if (step.isAdvancedFunctions()){
                
    -           //publisher = new DSLPublisher("", "", "", false, false, false, 0, 0, false, false,false,false,false,null,null,null,6,6,6,null,null,null,null,null,null,false,null,null,false);
    -           publisher = new DSLPublisher(step.getVAPIUrl(), step.getVAPIUser(), step.getVAPIPassword(), step.isAuthRequired(), step.isAdvConfig(), step.isDynamicUserId(), step.getConnTimeout(), step.getReadTimeout(), step.isAdvancedFunctions(),
    +            
    +           publisher = new DSLPublisher(step.getVAPIUrl(), step.getVAPIUser(), Secret.fromString(step.getVAPIPassword()), step.isAuthRequired(), step.isAdvConfig(), step.isDynamicUserId(), step.getConnTimeout(), step.getReadTimeout(), step.isAdvancedFunctions(),
                 step.isRetrieveSummaryReport(), step.isRunReport(), step.isMetricsReport(), step.isVPlanReport(), step.getTestsViewName(), step.getMetricsViewName(), step.getVplanViewName(), step.getTestsDepth(), step.getMetricsDepth(),
                 step.getVPlanDepth(), step.getMetricsInputType(), step.getMetricsAdvanceInput(), step.getVPlanInputType(), step.getVPlanAdvanceInput(), step.getVPlanxFileName(), step.getSummaryType(), step.isCtxInput(),
                 step.getCtxAdvanceInput(), step.getFreeVAPISyntax(), step.isDeleteReportSyntaxInputFile(),step.getVManagerVersion(), step.isSendEmail(), step.getEmailList(),step.getEmailType(), step.getEmailInputFile(),step.isDeleteEmailInputFile(), step.getSummaryMode(), step.isIgnoreSSLError(),null,"text");
    
  • src/main/java/org/jenkinsci/plugins/vmanager/dsl/post/VMGRPostLaunchStep.java+7 8 modified
    @@ -32,14 +32,13 @@
     import hudson.model.TaskListener;
    
     import hudson.util.FormValidation;
    
     import hudson.util.ListBoxModel;
    
    +
    
     import java.io.IOException;
    
     import java.util.Set;
    
     import javax.annotation.Nonnull;
    
     import jakarta.servlet.ServletException;
    
     import net.sf.json.JSONObject;
    
     import org.jenkinsci.plugins.vmanager.Utils;
    
    -//import org.jenkinsci.plugins.workflow.steps.AbstractStepDescriptorImpl;
    
    -//import org.jenkinsci.plugins.workflow.steps.AbstractStepImpl;
    
     import org.jenkinsci.plugins.workflow.steps.Step;
    
     import org.jenkinsci.plugins.workflow.steps.StepContext;
    
     import org.jenkinsci.plugins.workflow.steps.StepDescriptor;
    
    @@ -58,7 +57,6 @@ public class VMGRPostLaunchStep extends Step {
         private boolean authRequired;
    
         private boolean advConfig;
    
         private String vAPIUser;
    
    -    private String vAPIPassword;
    
         private boolean dynamicUserId;
    
         private int connTimeout = 1;
    
         private int readTimeout = 30;
    
    @@ -82,7 +80,7 @@ public class VMGRPostLaunchStep extends Step {
         private String vPlanInputType;
    
         private String vPlanAdvanceInput;
    
         private String vPlanxFileName;
    
    -
    
    +    private String vAPIPassword;
    
         private String summaryType;
    
         private boolean ctxInput;
    
         private String ctxAdvanceInput;
    
    @@ -278,10 +276,6 @@ public String getVAPIUser() {
             return vAPIUser;
    
         }
    
     
    
    -    public String getVAPIPassword() {
    
    -        return vAPIPassword;
    
    -    }
    
    -
    
         public boolean isDynamicUserId() {
    
             return dynamicUserId;
    
         }
    
    @@ -294,6 +288,10 @@ public int getReadTimeout() {
             return readTimeout;
    
         }
    
     
    
    +    public String getVAPIPassword() {
    
    +        return vAPIPassword;
    
    +    }
    
    +
    
         @Override
    
         public StepExecution start(StepContext context) throws Exception {
    
             return new VMGRPostLaunchStepImpl(this, context);
    
    @@ -302,6 +300,7 @@ public StepExecution start(StepContext context) throws Exception {
         @Extension
    
         public static class DescriptorImpl extends StepDescriptor {
    
     
    
    +        
    
             public DescriptorImpl() {
    
                 load();
    
             }
    
    
  • src/main/java/org/jenkinsci/plugins/vmanager/dsl/VMGRLaunchStepImpl.java+1 1 modified
    @@ -17,7 +17,7 @@
     
    
     public class VMGRLaunchStepImpl extends SynchronousNonBlockingStepExecution {
    
     
    
    -    private static final long serialVersionUID = 1000009076155338046L;
    
    +    private static final long serialVersionUID = 1000009076155338047L;
    
         
    
         private transient final VMGRLaunchStep step;
    
     
    
    
  • src/main/java/org/jenkinsci/plugins/vmanager/VMGRAPI.java+16 21 modified
    @@ -9,6 +9,8 @@
     import hudson.tasks.Builder;
    
     import hudson.util.FormValidation;
    
     import hudson.util.ListBoxModel;
    
    +import hudson.util.Secret;
    
    +
    
     import java.io.IOException;
    
     
    
     import jakarta.servlet.ServletException;
    
    @@ -24,7 +26,7 @@ public class VMGRAPI extends Builder {
     	private final String vAPIUrl;
    
     	private final boolean authRequired;
    
     	private final String vAPIUser;
    
    -	private final String vAPIPassword;
    
    +	private final Secret vAPIPassword;
    
     	private final String vAPIInput;
    
     	private final String vJsonInputFile;
    
     	private final boolean deleteInputFile;
    
    @@ -41,7 +43,7 @@ public class VMGRAPI extends Builder {
     	// Fields in config.jelly must match the parameter names in the
    
     	// "DataBoundConstructor"
    
     	@DataBoundConstructor
    
    -	public VMGRAPI(String vAPIUrl, String vAPIUser, String vAPIPassword, String vAPIInput, String vJsonInputFile, boolean deleteInputFile, boolean authRequired, String apiType,
    
    +	public VMGRAPI(String vAPIUrl, String vAPIUser, Secret vAPIPassword, String vAPIInput, String vJsonInputFile, boolean deleteInputFile, boolean authRequired, String apiType,
    
     			boolean dynamicUserId, String apiUrl, String requestMethod, boolean advConfig, int connTimeout, int readTimeout) {
    
     		this.vAPIUrl = vAPIUrl;
    
     		this.vAPIUser = vAPIUser;
    
    @@ -77,10 +79,6 @@ public String getVAPIUser() {
     		return vAPIUser;
    
     	}
    
     
    
    -	public String getVAPIPassword() {
    
    -		return vAPIPassword;
    
    -	}
    
    -
    
     	public String getVAPIInput() {
    
     		return vAPIInput;
    
     	}
    
    @@ -117,24 +115,21 @@ public int getConnTimeout() {
     		return connTimeout;
    
     	}
    
     
    
    +	public Secret getVAPIPassword() {
    
    +        return vAPIPassword;
    
    +    }
    
    +
    
     	public int getReadTimeout() {
    
     		return readTimeout;
    
     	}
    
    -	/*
    
    -	public ListBoxModel doFillRequestMethodItems(){
    
    -
    
    -	    return new ListBoxModel(
    
    -	        new Option("POST", "POST", "POST".equals(requestMethod)),
    
    -	        new Option("GET", "GET", "GET".equals(requestMethod)),
    
    -	        new Option("PUT", "PUT", "PUT".equals(requestMethod)),
    
    -	    	new Option("DELETE", "DELETE", "DELETE".equals(requestMethod)));
    
    -	}
    
    -	*/
    
    +	
    
     	
    
     
    
     	@Override
    
     	public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) {
    
     
    
    +		String vAPIPassword = getVAPIPassword().getPlainText();  
    
    +
    
     		listener.getLogger().println("The HOST for vAPI is: " + vAPIUrl);
    
     		listener.getLogger().println("The vAPIUser for vAPI is: " + vAPIUser);
    
     		listener.getLogger().println("The vAPIPassword for vAPI is: *******");
    
    @@ -222,9 +217,9 @@ public static final class DescriptorImpl extends BuildStepDescriptor<Builder> {
     		/**
    
     		 * To persist global configuration information, simply store it in a
    
     		 * field and call save().
    
    -		 * 
    
    -		
    
    +		 */
    
     
    
    +		
    
     		/**
    
     		 * In order to load the persisted global configuration, you have to call
    
     		 * load() in the constructor.
    
    @@ -305,13 +300,13 @@ public boolean configure(StaplerRequest2 req, JSONObject formData) throws FormEx
     
    
     		
    
     
    
    -		public FormValidation doTestConnection(@QueryParameter("vAPIUser") final String vAPIUser, @QueryParameter("vAPIPassword") final String vAPIPassword,
    
    +		public FormValidation doTestConnection(@QueryParameter("vAPIUser") final String vAPIUser, @QueryParameter("vAPIPassword") final Secret vAPIPassword,
    
     				@QueryParameter("vAPIUrl") final String vAPIUrl, @QueryParameter("authRequired") final boolean authRequired) throws IOException,
    
     				ServletException {
    
     			try {
    
    -
    
    +				String tempPassword = vAPIPassword.getPlainText();
    
     				Utils utils = new Utils();
    
    -				String output = utils.checkVAPIConnection(vAPIUrl, authRequired, vAPIUser, vAPIPassword);
    
    +				String output = utils.checkVAPIConnection(vAPIUrl, authRequired, vAPIUser, tempPassword);
    
     				if (!output.startsWith("Failed")) {
    
     					return FormValidation.ok("Success. " + output);
    
     				} else {
    
    
  • src/main/java/org/jenkinsci/plugins/vmanager/VMGRBuildArchiver.java+6 3 modified
    @@ -44,6 +44,8 @@
     import java.util.logging.Logger;
     import javax.net.ssl.HttpsURLConnection;
     import org.apache.commons.codec.binary.Base64;
    +import hudson.util.Secret;
    +
     
     /**
      *
    @@ -147,10 +149,10 @@ public void markBuildForArchive(List<String> listOfSessions, String apiURL, bool
                 }
                 if (genericCredentialForSessionDelete) {
                     writer.append("archiveUser=" + archiveUser + "\n");
    -                writer.append("archivePassword=" + archivePassword + "\n");
    +                writer.append("archivePassword=" + Secret.fromString(archivePassword).getEncryptedValue() + "\n");
                 } else {
                     writer.append("archiveUser=" + userUsedForLogin + "\n");
    -                writer.append("archivePassword=" + passwordUsedForLogin + "\n");
    +                writer.append("archivePassword=" + Secret.fromString(passwordUsedForLogin).getEncryptedValue() + "\n");
                 }
                 writer.append("sessions=" + sessions + "\n");
                 utils.saveFileOnDisk(fileOutput, writer.toString());
    @@ -184,7 +186,8 @@ public void deleteSessions(Run run, Logger logger) throws Exception {
                 } else {
     
                     String apiUrl = null;
    -                String userCredentials = buildSdi.getProperty("archiveUser").trim() + ":" + buildSdi.getProperty("archivePassword").trim();
    +                String decryptedPassword = Secret.fromString(buildSdi.getProperty("archivePassword").trim()).getPlainText();
    +                String userCredentials = buildSdi.getProperty("archiveUser").trim() + ":" + decryptedPassword;
                     boolean requireAuth = true;
                     if ("false".equals(buildSdi.getProperty("requireAuth").trim())) {
                         requireAuth = false;
    
  • src/main/java/org/jenkinsci/plugins/vmanager/VMGRLaunch.java+116 84 modified
    @@ -18,6 +18,8 @@
     import hudson.tasks.Builder;
    
     import hudson.util.FormValidation;
    
     import hudson.util.ListBoxModel;
    
    +import hudson.util.Secret;
    
    +
    
     import java.io.IOException;
    
     import java.util.Arrays;
    
     import java.util.Collections;
    
    @@ -35,6 +37,7 @@
     import org.kohsuke.stapler.AncestorInPath;
    
     
    
     import org.kohsuke.stapler.DataBoundConstructor;
    
    +
    
     import org.kohsuke.stapler.QueryParameter;
    
     import org.kohsuke.stapler.StaplerRequest2;
    
     
    
    @@ -44,7 +47,6 @@ public class VMGRLaunch extends Builder {
         private final boolean authRequired;
    
         private final boolean advConfig;
    
         private final String vAPIUser;
    
    -    private final String vAPIPassword;
    
         private final String vAPICredentials;
    
         private final String vSIFName;
    
         private final String vSIFInputFile;
    
    @@ -56,7 +58,7 @@ public class VMGRLaunch extends Builder {
         private final String vsifType;
    
         private final String userFarmType;
    
         private final String envSourceInputFile;
    
    -
    
    +    private final Secret vAPIPassword;
    
         private int connTimeout = 1;
    
         private int readTimeout = 30;
    
         private final boolean envVarible;
    
    @@ -85,14 +87,13 @@ public class VMGRLaunch extends Builder {
         private final boolean markBuildAsPassedIfAllRunPassed;
    
         private final boolean failJobUnlessAllRunPassed;
    
         private final boolean userPrivateSSHKey;
    
    -    //private final String extraAttributesForFailuresInputFile;
    
    -    //private final boolean deleteExtraAttributesFile;
    
    + 
    
     
    
         private final boolean vMGRBuildArchive;
    
         private final boolean deleteAlsoSessionDirectory;
    
         private final boolean genericCredentialForSessionDelete;
    
         private final String archiveUser;
    
    -    private final String archivePassword;
    
    +    private final Secret archivePassword;
    
     
    
         private final String famMode;
    
         private final String famModeLocation;
    
    @@ -130,10 +131,10 @@ public class VMGRLaunch extends Builder {
         // Fields in config.jelly must match the parameter names in the
    
         // "DataBoundConstructor"
    
         @DataBoundConstructor
    
    -    public VMGRLaunch(String vAPIUrl, String vAPIUser, String vAPIPassword, String vSIFName, String vSIFInputFile, String credentialInputFile, boolean deleteInputFile, boolean deleteCredentialInputFile, boolean useUserOnFarm, boolean authRequired, String vsifType, String userFarmType,
    
    +    public VMGRLaunch(String vAPIUrl, String vAPIUser, Secret vAPIPassword, String vSIFName, String vSIFInputFile, String credentialInputFile, boolean deleteInputFile, boolean deleteCredentialInputFile, boolean useUserOnFarm, boolean authRequired, String vsifType, String userFarmType,
    
                 boolean dynamicUserId, boolean advConfig, int connTimeout, int readTimeout, boolean envVarible, String envVaribleFile, String inaccessibleResolver, String stoppedResolver, String failedResolver, String doneResolver, String suspendedResolver, boolean waitTillSessionEnds,
    
                 int stepSessionTimeout, boolean generateJUnitXML, boolean extraAttributesForFailures, String staticAttributeList, boolean markBuildAsFailedIfAllRunFailed, boolean failJobIfAllRunFailed, String envSourceInputFile, boolean vMGRBuildArchive, boolean deleteAlsoSessionDirectory,
    
    -            boolean genericCredentialForSessionDelete, String archiveUser, String archivePassword, String famMode, String famModeLocation, boolean noAppendSeed, boolean markBuildAsPassedIfAllRunPassed, boolean failJobUnlessAllRunPassed, boolean userPrivateSSHKey, boolean attrValues,
    
    +            boolean genericCredentialForSessionDelete, String archiveUser, Secret archivePassword, String famMode, String famModeLocation, boolean noAppendSeed, boolean markBuildAsPassedIfAllRunPassed, boolean failJobUnlessAllRunPassed, boolean userPrivateSSHKey, boolean attrValues,
    
                 String attrValuesFile, String executionType, String sessionsInputFile, boolean deleteSessionInputFile, String envVariableType, String envVariableText, String attrVariableType, String attrVariableText, boolean pauseSessionOnBuildInterruption, String envSourceInputFileType,
    
                 String executionScript, String executionShellLocation, String executionVsifFile, String defineVaribleFile, boolean defineVarible, String defineVariableType, String defineVariableText, String vAPICredentials, String credentialType) {
    
             this.vAPIUrl = vAPIUrl;
    
    @@ -182,7 +183,6 @@ public VMGRLaunch(String vAPIUrl, String vAPIUser, String vAPIPassword, String v
             this.genericCredentialForSessionDelete = genericCredentialForSessionDelete;
    
             this.archiveUser = archiveUser;
    
             this.archivePassword = archivePassword;
    
    -
    
             this.famMode = famMode;
    
             this.famModeLocation = famModeLocation;
    
             this.noAppendSeed = noAppendSeed;
    
    @@ -308,10 +308,14 @@ public String getVAPIUser() {
             return vAPIUser;
    
         }
    
     
    
    -    public String getVAPIPassword() {
    
    +    public Secret getVAPIPassword() {
    
             return vAPIPassword;
    
         }
    
     
    
    +    public Secret getArchivePassword() {
    
    +        return archivePassword;
    
    +    }
    
    +
    
         public String getVSIFName() {
    
             return vSIFName;
    
         }
    
    @@ -432,10 +436,6 @@ public String getArchiveUser() {
             return archiveUser;
    
         }
    
     
    
    -    public String getArchivePassword() {
    
    -        return archivePassword;
    
    -    }
    
    -
    
         public String getFamMode() {
    
             return famMode;
    
         }
    
    @@ -464,9 +464,14 @@ public String getVAPICredentials() {
             return vAPICredentials;
    
         }
    
     
    
    +   
    
    +
    
         @Override
    
         public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) {
    
    -
    
    +        
    
    +        String vAPIPassword = getVAPIPassword().getPlainText();        
    
    +        String archivePassword = getArchivePassword().getPlainText();
    
    +       
    
             String workingJobDir = build.getRootDir().getAbsolutePath();
    
             listener.getLogger().println("Root dir is: " + workingJobDir);
    
             
    
    @@ -914,6 +919,7 @@ public void onDeleted(Run run) {
         // point.
    
         public static final class DescriptorImpl extends BuildStepDescriptor<Builder> {
    
     
    
    +       
    
             /**
    
              * To persist global configuration information, simply store it in a
    
              * field and call save().
    
    @@ -1048,7 +1054,7 @@ public ListBoxModel doFillVAPICredentialsItems(
             ) {
    
                 StandardListBoxModel result = new StandardListBoxModel();
    
                 if (item == null) {
    
    -                if (!Jenkins.getInstance().hasPermission(Jenkins.ADMINISTER)) {
    
    +                if (!Jenkins.get().hasPermission(Jenkins.ADMINISTER)) {
    
                         return result.includeCurrentValue(vAPICredentials); // (2)
    
                     }
    
                 } else {
    
    @@ -1059,7 +1065,7 @@ public ListBoxModel doFillVAPICredentialsItems(
                 }
    
                 return result
    
                         .includeEmptyValue()
    
    -                    .includeMatchingAs(ACL.SYSTEM, Jenkins.getInstance(), StandardUsernamePasswordCredentials.class, Collections.<DomainRequirement>emptyList(), CredentialsMatchers.always())
    
    +                    .includeMatchingAs(ACL.SYSTEM2, Jenkins.get(), StandardUsernamePasswordCredentials.class, Collections.<DomainRequirement>emptyList(), CredentialsMatchers.always())
    
                         .includeCurrentValue(vAPICredentials); // (5)
    
     
    
             }
    
    @@ -1073,116 +1079,142 @@ public String getDisplayName() {
     
    
             @Override
    
             public boolean configure(StaplerRequest2 req, JSONObject formData) throws FormException {
    
    -
    
    +            //req.bindJSON(this, formData);
    
                 save();
    
                 return super.configure(req, formData);
    
             }
    
     
    
    -        public FormValidation doTestConnection(@QueryParameter("vAPIUser") final String vAPIUser, @QueryParameter("vAPIPassword") final String vAPIPassword,
    
    +        public FormValidation doTestConnection(@QueryParameter("vAPIUser") final String vAPIUser, @QueryParameter("vAPIPassword") final Secret vAPIPassword,
    
                     @QueryParameter("vAPIUrl") final String vAPIUrl, @QueryParameter("authRequired") final boolean authRequired,
    
                     @QueryParameter("credentialType") final String credentialType, @QueryParameter("vAPICredentials") final String vAPICredentials, @AncestorInPath Item item)
    
                     throws IOException, ServletException {
    
    -            try {
    
    -                String tempUser = vAPIUser;
    
    -                String tempPassword = vAPIPassword;
    
    -                boolean foundMatchUserPassword = false;
    
    -                if ("credential".equals(credentialType)) {
    
    -                    //System.out.println("Trying to find the credential...");
    
    -                    //overwrite the plain text with the credentials
    
    -                    //StandardUsernamePasswordCredentials c = CredentialsProvider.findCredentialById(vAPICredentials, StandardUsernamePasswordCredentials.class, item, Collections.<DomainRequirement>emptyList());
    
    -                    List<StandardUsernamePasswordCredentials> listOfC = CredentialsProvider.lookupCredentials(StandardUsernamePasswordCredentials.class, item, ACL.SYSTEM, Collections.<DomainRequirement>emptyList());
    
    -                    Iterator<StandardUsernamePasswordCredentials> cIterator = listOfC.iterator();
    
    -                    StandardUsernamePasswordCredentials tmpHolder = null;
    
    -                    while (cIterator.hasNext()) {
    
    -                        tmpHolder = cIterator.next();
    
    -                        if (vAPICredentials.equals(tmpHolder.getId())) {
    
    -                            tempUser = tmpHolder.getUsername();
    
    -                            tempPassword = tmpHolder.getPassword().getPlainText();
    
    -                            foundMatchUserPassword = true;
    
    -                            break;
    
    +                try {
    
    +                    String tempUser = vAPIUser;
    
    +                    String tempPassword = vAPIPassword.getPlainText();
    
    +                    boolean foundMatchUserPassword = false;
    
    +                    if ("credential".equals(credentialType)) {  
    
    +                        List<StandardUsernamePasswordCredentials> listOfC = CredentialsProvider.lookupCredentialsInItem(StandardUsernamePasswordCredentials.class, item, ACL.SYSTEM2, Collections.<DomainRequirement>emptyList());
    
    +                        Iterator<StandardUsernamePasswordCredentials> cIterator = listOfC.iterator();
    
    +                        StandardUsernamePasswordCredentials tmpHolder = null;
    
    +                        while (cIterator.hasNext()) {
    
    +                            tmpHolder = cIterator.next();
    
    +                            if (vAPICredentials.equals(tmpHolder.getId())) {
    
    +                                tempUser = tmpHolder.getUsername();
    
    +                                tempPassword = tmpHolder.getPassword().getPlainText();
    
    +                                foundMatchUserPassword = true;
    
    +                                break;
    
    +                            }
    
    +
    
                             }
    
     
    
    +                    } else {
    
    +                        foundMatchUserPassword = true;
    
                         }
    
     
    
    -                } else {
    
    -                    foundMatchUserPassword = true;
    
    +                    if (foundMatchUserPassword) {
    
    +                        Utils utils = new Utils();
    
    +                        String output = utils.checkVAPIConnection(vAPIUrl, authRequired, tempUser, tempPassword);
    
    +                        if (!output.startsWith("Failed")) {
    
    +                            return FormValidation.ok("Success. " + output);
    
    +                        } else {
    
    +                            return FormValidation.error(output);
    
    +                        }
    
    +                    } else {
    
    +                        return FormValidation.error("Could not extract the user/password from the supplied Credential object.  Object was not found within your Jenkins domain.");
    
    +                    }
    
    +                } catch (Exception e) {
    
    +                    return FormValidation.error("Client error : " + e.getMessage());
    
                     }
    
    +        }
    
     
    
    -                if (foundMatchUserPassword) {
    
    +        public FormValidation doTestArchiveUser(@QueryParameter("archiveUser") final String archiveUser, @QueryParameter("archivePassword") final Secret archivePassword,
    
    +                @QueryParameter("vAPIUrl") final String vAPIUrl) throws IOException,
    
    +                ServletException {
    
    +            
    
    +                try {
    
    +                    String tempPassword = archivePassword.getPlainText();
    
                         Utils utils = new Utils();
    
    -                    String output = utils.checkVAPIConnection(vAPIUrl, authRequired, tempUser, tempPassword);
    
    +                    String output = utils.checkVAPIConnection(vAPIUrl, true, archiveUser, tempPassword);
    
                         if (!output.startsWith("Failed")) {
    
                             return FormValidation.ok("Success. " + output);
    
                         } else {
    
                             return FormValidation.error(output);
    
                         }
    
    -                } else {
    
    -                    return FormValidation.error("Could not extract the user/password from the supplied Credential object.  Object was not found within your Jenkins domain.");
    
    +                } catch (Exception e) {
    
    +                    return FormValidation.error("Client error : " + e.getMessage());
    
                     }
    
    -            } catch (Exception e) {
    
    -                return FormValidation.error("Client error : " + e.getMessage());
    
    -            }
    
             }
    
     
    
    -        public FormValidation doTestArchiveUser(@QueryParameter("archiveUser") final String archiveUser, @QueryParameter("archivePassword") final String archivePassword,
    
    -                @QueryParameter("vAPIUrl") final String vAPIUrl) throws IOException,
    
    +        public FormValidation doTestExtraStaticAttr(@QueryParameter("vAPIUser") final String vAPIUser, @QueryParameter("vAPIPassword") final Secret vAPIPassword,
    
    +                @QueryParameter("vAPIUrl") final String vAPIUrl, @QueryParameter("authRequired") final boolean authRequired, @QueryParameter("staticAttributeList") final String staticAttributeList,
    
    +                @QueryParameter("credentialType") final String credentialType, @QueryParameter("vAPICredentials") final String vAPICredentials, @AncestorInPath Item item) throws IOException,
    
                     ServletException {
    
    -            try {
    
    +            
    
    +                try {
    
    +                    String tempUser = vAPIUser;
    
    +                    String tempPassword = vAPIPassword.getPlainText();           
    
    +                    boolean foundMatchUserPassword = false;
    
    +                    if ("credential".equals(credentialType)) {
    
    +                        List<StandardUsernamePasswordCredentials> listOfC = CredentialsProvider.lookupCredentialsInItem(StandardUsernamePasswordCredentials.class, item, ACL.SYSTEM2, Collections.<DomainRequirement>emptyList());
    
    +                        Iterator<StandardUsernamePasswordCredentials> cIterator = listOfC.iterator();
    
    +                        StandardUsernamePasswordCredentials tmpHolder = null;
    
    +                        while (cIterator.hasNext()) {
    
    +                            tmpHolder = cIterator.next();
    
    +                            if (vAPICredentials.equals(tmpHolder.getId())) {
    
    +                                tempUser = tmpHolder.getUsername();
    
    +                                tempPassword = tmpHolder.getPassword().getPlainText();
    
    +                                foundMatchUserPassword = true;
    
    +                                break;
    
    +                            }
    
     
    
    -                Utils utils = new Utils();
    
    -                String output = utils.checkVAPIConnection(vAPIUrl, true, archiveUser, archivePassword);
    
    -                if (!output.startsWith("Failed")) {
    
    -                    return FormValidation.ok("Success. " + output);
    
    -                } else {
    
    -                    return FormValidation.error(output);
    
    -                }
    
    -            } catch (Exception e) {
    
    -                return FormValidation.error("Client error : " + e.getMessage());
    
    -            }
    
    -        }
    
    +                        }
    
     
    
    -        public FormValidation doTestExtraStaticAttr(@QueryParameter("vAPIUser") final String vAPIUser, @QueryParameter("vAPIPassword") final String vAPIPassword,
    
    -                @QueryParameter("vAPIUrl") final String vAPIUrl, @QueryParameter("authRequired") final boolean authRequired, @QueryParameter("staticAttributeList") final String staticAttributeList) throws IOException,
    
    -                ServletException {
    
    -            try {
    
    +                    } else {
    
    +                        foundMatchUserPassword = true;
    
    +                    }
    
     
    
    -                Utils utils = new Utils();
    
    -                String output = utils.checkExtraStaticAttr(vAPIUrl, authRequired, vAPIUser, vAPIPassword, staticAttributeList);
    
    -                if (!output.startsWith("Failed")) {
    
    -                    return FormValidation.ok("Success. " + output);
    
    -                } else {
    
    -                    return FormValidation.error(output);
    
    +                    if (foundMatchUserPassword) {
    
    +                        Utils utils = new Utils();
    
    +                        String output = utils.checkExtraStaticAttr(vAPIUrl, authRequired, tempUser, tempPassword, staticAttributeList);
    
    +                        if (!output.startsWith("Failed")) {
    
    +                            return FormValidation.ok("Success. " + output);
    
    +                        } else {
    
    +                            return FormValidation.error(output);
    
    +                        }
    
    +                    } else {
    
    +                        return FormValidation.error("Could not extract the user/password from the supplied Credential object.  Object was not found within your Jenkins domain.");
    
    +                    }
    
    +                } catch (Exception e) {
    
    +                    return FormValidation.error("Client error : " + e.getMessage());
    
                     }
    
    -            } catch (Exception e) {
    
    -                return FormValidation.error("Client error : " + e.getMessage());
    
    -            }
    
    +   
    
             }
    
     
    
             public FormValidation doCheckVAPICredentials(
    
    -                @AncestorInPath Item item, // (2)
    
    -                @QueryParameter String value // (1)
    
    +                @AncestorInPath Item item, 
    
    +                @QueryParameter String value 
    
     
    
             ) {
    
                 if (item == null) {
    
    -                if (!Jenkins.getInstance().hasPermission(Jenkins.ADMINISTER)) {
    
    -                    return FormValidation.ok(); // (3)
    
    +                if (!Jenkins.get().hasPermission(Jenkins.ADMINISTER)) {
    
    +                    return FormValidation.ok(); 
    
                     }
    
                 } else {
    
                     if (!item.hasPermission(Item.EXTENDED_READ)
    
                             && !item.hasPermission(CredentialsProvider.USE_ITEM)) {
    
    -                    return FormValidation.ok(); // (3)
    
    +                    return FormValidation.ok(); 
    
                     }
    
                 }
    
    -            if (StringUtils.isBlank(value)) { // (4)
    
    -                return FormValidation.ok(); // (4)
    
    +            if (StringUtils.isBlank(value)) { 
    
    +                return FormValidation.ok(); 
    
                 }
    
    -            //.includeMatchingAs(ACL.SYSTEM,Jenkins.getInstance(),StandardUsernamePasswordCredentials.class,Collections.<DomainRequirement>emptyList(),CredentialsMatchers.always())
    
    -            if (CredentialsProvider.listCredentials( // (6)
    
    -                    StandardUsernamePasswordCredentials.class, // (1)
    
    +            
    
    +            if (CredentialsProvider.listCredentialsInItem( 
    
    +                    StandardUsernamePasswordCredentials.class, 
    
                         item,
    
    -                    ACL.SYSTEM,
    
    +                    ACL.SYSTEM2,
    
                         Collections.<DomainRequirement>emptyList(),
    
    -                    CredentialsMatchers.always() // (6)
    
    +                    CredentialsMatchers.always() 
    
                 ).isEmpty()) {
    
                     return FormValidation.error("Cannot find currently selected credentials");
    
                 }
    
    
  • src/main/resources/org/jenkinsci/plugins/vmanager/VMGRLaunch/config.jelly+1 1 modified
    @@ -183,7 +183,7 @@
                      <f:optionalBlock name="extraAttributesForFailures"  title="Add extra attributes for failure stack" description="If selected, the job will add extra attributes for failure stack." checked="${instance.extraAttributesForFailures}" inline="true">
    
      		 
    
                <f:entry title="Attribute List (attribute codes must be used)" field="staticAttributeList" description="Static extra attributes for failure stack, separated by comma"><f:textbox /></f:entry>
    
    -           <f:validateButton title="${%Test Attributes Validity}" progress="${%Testing Attribute Codes Validity...}" method="testExtraStaticAttr" with="vAPIUser,vAPIPassword,vAPIUrl,authRequired,staticAttributeList" />
    
    +           <f:validateButton title="${%Test Attributes Validity}" progress="${%Testing Attribute Codes Validity...}" method="testExtraStaticAttr" with="vAPIUser,vAPIPassword,vAPIUrl,authRequired,staticAttributeList,credentialType,vAPICredentials" />
    
       		 
    
      		 </f:optionalBlock>
    
     		</f:optionalBlock>
    
    

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