VYPR
Moderate severityNVD Advisory· Published Mar 29, 2022· Updated Aug 3, 2024

CVE-2022-28146

CVE-2022-28146

Description

Jenkins Continuous Integration with Toad Edge Plugin 2.3 and earlier allows attackers with Item/Configure permission to read arbitrary files on the Jenkins controller by specifying an input folder parameter in build steps.

AI Insight

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

Jenkins Continuous Integration with Toad Edge Plugin 2.3 and earlier allows attackers with Item/Configure permission to read arbitrary files on the Jenkins controller by specifying an input folder parameter in build steps.

Vulnerability

Jenkins Continuous Integration with Toad Edge Plugin version 2.3 and earlier does not restrict the input folder parameter in its build steps [1][4]. Attackers with Item/Configure permission can specify any folder path on the Jenkins controller, leading to arbitrary file read [1][4].

Exploitation

An attacker with Item/Configure permission can configure a build step to use an arbitrary folder path as the input parameter [1][4]. No additional authentication or user interaction is required beyond having the permission [1][4].

Impact

Successful exploitation allows the attacker to read arbitrary files from the Jenkins controller file system [1][4]. This can expose sensitive information such as credentials, secrets, or configuration files [1][4].

Mitigation

The vulnerability is fixed in Continuous Integration with Toad Edge Plugin version 2.4, released on March 29, 2022 [2][3]. Users should upgrade to version 2.4 or later [2][3]. No workarounds are available for older versions [1][2].

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.

PackageAffected versionsPatched versions
org.jenkins-ci.plugins:ci-with-toad-edgeMaven
< 2.42.4

Affected products

2

Patches

1
49d4b855773e

{SECURITY-2633}

24 files changed · +115 96
  • src/main/java/ci/with/toad/edge/CompareBuilder.java+13 0 modified
    @@ -130,6 +130,19 @@ public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListen
     		System.setOut(listener.getLogger());
     		System.setErr(listener.getLogger());
     
    +		FormValidation checkValidation = FormValidationUtil.restrictLocation(srcInputFileOrFolder, build);
    +		if(checkValidation != FormValidation.ok()) {
    +			throw new Error(checkValidation.getMessage());
    +		}
    +		FormValidation checkValidationTarget = FormValidationUtil.restrictLocation(tgtInputFileOrFolder, build);
    +		if(checkValidationTarget != FormValidation.ok()) {
    +			throw new Error(checkValidationTarget.getMessage());
    +		}
    +		FormValidation checkValidationConfig=FormValidationUtil.restrictLocation(configFile, build);
    +		if(checkValidationConfig != FormValidation.ok()){
    +			throw new Error(checkValidationConfig.getMessage());
    +		}
    +
     		copyBuildFiles(build, listener);
     		ensureTmpOutputFolder(build, listener);
     
    
  • src/main/java/ci/with/toad/edge/CompareWithBaselineBuilder.java+13 0 modified
    @@ -128,6 +128,19 @@ public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListen
     		System.setOut(listener.getLogger());
     		System.setErr(listener.getLogger());
     
    +		FormValidation checkValidation = FormValidationUtil.restrictLocation(srcInputFileOrFolder, build);
    +		if(checkValidation != FormValidation.ok()) {
    +			throw new Error(checkValidation.getMessage());
    +		}
    +		FormValidation checkValidationTarget = FormValidationUtil.restrictLocation(tgtInputFileOrFolder, build);
    +		if(checkValidationTarget != FormValidation.ok()) {
    +			throw new Error(checkValidationTarget.getMessage());
    +		}
    +		FormValidation checkValidationConfig=FormValidationUtil.restrictLocation(configFile, build);
    +		if(checkValidationConfig != FormValidation.ok()){
    +			throw new Error(checkValidationConfig.getMessage());
    +		}
    +
     		copyBuildFiles(build, listener);
     		ensureTmpOutputFolder(build, listener);
     
    
  • src/main/java/ci/with/toad/edge/CreateBaselineBuilder.java+6 1 modified
    @@ -88,7 +88,12 @@ private FilePath getTmpOutput(AbstractBuild<?, ?> build) throws IOException, Int
     	public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException {
     		System.setOut(listener.getLogger());
     		System.setErr(listener.getLogger());
    -		
    +
    +		FormValidation checkValidation = FormValidationUtil.restrictLocation(inputFileOrFolder, build);
    +		if(checkValidation != FormValidation.ok()) {
    +			throw new Error(checkValidation.getMessage());
    +		}
    +
     		copyBuildFiles(build, listener);
     
     		Map<String, String> arguments = new HashMap<>();
    
  • src/main/java/ci/with/toad/edge/CreateSnapshotBuilder.java+6 1 modified
    @@ -89,7 +89,12 @@ private FilePath getTmpOutput(AbstractBuild<?, ?> build) throws IOException, Int
     	public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException {
     		System.setOut(listener.getLogger());
     		System.setErr(listener.getLogger());
    -		
    +
    +		FormValidation checkValidation = FormValidationUtil.restrictLocation(inputFileOrFolder, build);
    +		if( checkValidation != FormValidation.ok()) {
    +			throw new Error(checkValidation.getMessage());
    +		}
    +
     		copyBuildFiles(build, listener);
     
     		Map<String, String> arguments = new HashMap<>();
    
  • src/main/java/ci/with/toad/edge/DeployScriptBuilder.java+9 0 modified
    @@ -87,6 +87,15 @@ public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListen
     		System.setOut(listener.getLogger());
     		System.setErr(listener.getLogger());
     
    +		FormValidation checkValidation = FormValidationUtil.restrictLocation(in, build);
    +		if( checkValidation != FormValidation.ok()) {
    +			throw new Error(checkValidation.getMessage());
    +		}
    +		FormValidation checkValidationOut = FormValidationUtil.restrictLocation(out, build);
    +		if(checkValidationOut != FormValidation.ok()) {
    +			throw new Error(checkValidation.getMessage());
    +		}
    +
     		copyBuildFiles(build, listener);
     
     		Map<String, String> arguments = new HashMap<>();
    
  • src/main/java/ci/with/toad/edge/FormValidationUtil.java+33 0 modified
    @@ -16,11 +16,19 @@
      */
     package ci.with.toad.edge;
     
    +import hudson.FilePath;
    +import hudson.model.AbstractBuild;
     import org.jvnet.localizer.Localizable;
     import org.jvnet.localizer.ResourceBundleHolder;
     
     import hudson.util.FormValidation;
     
    +import javax.annotation.Nonnull;
    +import java.io.File;
    +import java.io.IOException;
    +import java.net.URI;
    +import java.net.URL;
    +
     public class FormValidationUtil {
     	
     	/**
    @@ -35,4 +43,29 @@ public static FormValidation doCheckEmptyValue(String value, String fieldName) {
     		}
     		return FormValidation.ok();
     	}
    +
    +	/**
    +	 * Checks if folder path is in current workspace path
    +	 *
    +	 * @param folderPath
    +	 * @return
    +	 */
    +	@Nonnull
    +	public static FormValidation restrictLocation(String folderPath, AbstractBuild<?, ?> build) throws IOException, InterruptedException {
    +        final FilePath workspaceDir = build.getWorkspace();
    +		final FilePath inputDir = FileUtils.getFilePath(build,folderPath);
    +		if(workspaceDir == null) {
    +			return FormValidation.ok();
    +		}
    +		final String inputDirLocation = inputDir.toURI().getPath();
    +		final String workspaceDirLocation = workspaceDir.toURI().getPath();
    +
    +		if(workspaceDir.isRemote() != inputDir.isRemote()) {
    +           return FormValidation.error(String.format("Input folder: %s  needs to be in the job's agent node", inputDirLocation));
    +		}
    +		if(inputDirLocation.contains(workspaceDirLocation)) {
    +			return FormValidation.ok();
    +		}
    +		return FormValidation.error(String.format("Specified folder or file (%s) should be inside project workspace directory",inputDirLocation));
    +	}
     }
    
  • src/main/java/ci/with/toad/edge/GenerateChangeScriptBuilder.java+6 1 modified
    @@ -82,7 +82,12 @@ private FilePath getTmpOut(AbstractBuild<?, ?> build) {
     	public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException {
     		System.setOut(listener.getLogger());
     		System.setErr(listener.getLogger());
    -		
    +
    +		FormValidation checkValidation = FormValidationUtil.restrictLocation(in, build);
    +		if(checkValidation != FormValidation.ok()) {
    +			throw new Error(checkValidation.getMessage());
    +		}
    +
     		copyBuildFiles(build, listener);
     
     		Map<String, String> arguments = new HashMap<>();
    
  • src/main/java/ci/with/toad/edge/GenerateCreateScriptBuilder.java+6 1 modified
    @@ -89,7 +89,12 @@ private FilePath getTmpOutput(AbstractBuild<?, ?> build) {
     	public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException {
     		System.setOut(listener.getLogger());
     		System.setErr(listener.getLogger());
    -		
    +
    +		FormValidation checkValidation = FormValidationUtil.restrictLocation(inputFileOrFolder, build);
    +		if(checkValidation != FormValidation.ok()){
    +			throw new Error(checkValidation.getMessage());
    +		}
    +
     		copyBuildFiles(build, listener);
     
     		Map<String, String> arguments = new HashMap<>();
    
  • src/main/java/ci/with/toad/edge/GenerateJenkinsReportBuilder.java+5 0 modified
    @@ -84,6 +84,11 @@ public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListen
     		System.setOut(listener.getLogger());
     		System.setErr(listener.getLogger());
     
    +		FormValidation checkValidation = FormValidationUtil.restrictLocation(inputFolder, build);
    +		if(checkValidation != FormValidation.ok()) {
    +			throw new Error(checkValidation.getMessage());
    +		}
    +
     		copyBuildFiles(build, listener);
     		FilePath tmpOutput = getTmpOut(build);
     		tmpOutput.mkdirs();
    
  • src/main/java/ci/with/toad/edge/GenerateStandaloneReportBuilder.java+4 0 modified
    @@ -85,6 +85,10 @@ public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListen
     		System.setOut(listener.getLogger());
     		System.setErr(listener.getLogger());
     
    +		FormValidation checkValidation = FormValidationUtil.restrictLocation(inputFolder, build);
    +		if(checkValidation != FormValidation.ok()) {
    +			throw new Error(checkValidation.getMessage());
    +		}
     		copyBuildFiles(build, listener);
     		FilePath tmpOutput = getTmpOut(build);
     		tmpOutput.mkdirs();
    
  • src/main/resources/ci/with/toad/edge/CompareBuilder/help-configFile.html+1 4 modified
    @@ -8,10 +8,7 @@
     	  File location must be specified as:
     	  <ul>
     		  <li>
    -		  Absolute path to location on your Jenkins master node
    -		  </li>
    -		  <li>
    -		  Relative path to your project's workspace. Either starting with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir. 
    +			  Relative or absolute path to your project's workspace. Relative path should start with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir.
     		  </li>
     	  </ul>
       </p>
    
  • src/main/resources/ci/with/toad/edge/CompareBuilder/help-srcInputFileOrFolder.html+1 7 modified
    @@ -13,13 +13,7 @@
     	  Folder/file location must be specified as:
     	  <ul>
     		  <li>
    -		  Absolute path to location on your Jenkins master node
    -		  </li>
    -		  <li>
    -		  Relative path to your project's workspace. Either starting with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir. 
    -		  </li>
    -		  <li>
    -		  Relative path to your job's run root directory. It must start with ${JOB_ROOT_DIR} prefix. i.e. ${JOB_ROOT_DIR}dir.
    +			  Relative or absolute path to your project's workspace. Relative path should start with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir.
     		  </li>
     	  </ul>
       </p>
    
  • src/main/resources/ci/with/toad/edge/CompareBuilder/help-tgtInputFileOrFolder.html+1 7 modified
    @@ -13,13 +13,7 @@
     	  Folder/file location must be specified as:
     	  <ul>
     		  <li>
    -		  Absolute path to location on your Jenkins master node
    -		  </li>
    -		  <li>
    -		  Relative path to your project's workspace. Either starting with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir. 
    -		  </li>
    -		  <li>
    -		  Relative path to your job's run root directory. It must start with ${JOB_ROOT_DIR} prefix. i.e. ${JOB_ROOT_DIR}dir.
    +			  Relative or absolute path to your project's workspace. Relative path should start with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir.
     		  </li>
     	  </ul>
       </p>
    
  • src/main/resources/ci/with/toad/edge/CompareWithBaselineBuilder/help-configFile.html+1 4 modified
    @@ -8,10 +8,7 @@
     	  File location must be specified as:
     	  <ul>
     		  <li>
    -		  Absolute path to location on your Jenkins master node
    -		  </li>
    -		  <li>
    -		  Relative path to your project's workspace. Either starting with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir. 
    +			  Relative or absolute path to your project's workspace. Relative path should start with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir.
     		  </li>
     	  </ul>
       </p>
    
  • src/main/resources/ci/with/toad/edge/CompareWithBaselineBuilder/help-srcInputFileOrFolder.html+1 7 modified
    @@ -13,13 +13,7 @@
     	  Folder/file location must be specified as:
     	  <ul>
     		  <li>
    -		  Absolute path to location on your Jenkins master node
    -		  </li>
    -		  <li>
    -		  Relative path to your project's workspace. Either starting with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir. 
    -		  </li>
    -		  <li>
    -		  Relative path to your job's run root directory. It must start with ${JOB_ROOT_DIR} prefix. i.e. ${JOB_ROOT_DIR}dir.
    +			  Relative or absolute path to your project's workspace. Relative path should start with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir.
     		  </li>
     	  </ul>
       </p>
    
  • src/main/resources/ci/with/toad/edge/CompareWithBaselineBuilder/help-tgtInputFileOrFolder.html+1 7 modified
    @@ -13,13 +13,7 @@
     	  Folder/file location must be specified as:
     	  <ul>
     		  <li>
    -		  Absolute path to location on your Jenkins master node
    -		  </li>
    -		  <li>
    -		  Relative path to your project's workspace. Either starting with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir. 
    -		  </li>
    -		  <li>
    -		  Relative path to your job's run root directory. It must start with ${JOB_ROOT_DIR} prefix. i.e. ${JOB_ROOT_DIR}dir.
    +			  Relative or absolute path to your project's workspace. Relative path should start with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir.
     		  </li>
     	  </ul>
       </p>
    
  • src/main/resources/ci/with/toad/edge/CreateBaselineBuilder/help-inputFileOrFolder.html+1 7 modified
    @@ -12,13 +12,7 @@
     	  Folder/file location must be specified as:
     	  <ul>
     		  <li>
    -		  Absolute path to location on your Jenkins master node
    -		  </li>
    -		  <li>
    -		  Relative path to your project's workspace. Either starting with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir. 
    -		  </li>
    -		  <li>
    -		  Relative path to your job's run root directory. It must start with ${JOB_ROOT_DIR} prefix. i.e. ${JOB_ROOT_DIR}dir.
    +			  Relative or absolute path to your project's workspace. Relative path should start with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir.
     		  </li>
     	  </ul>
       </p>
    
  • src/main/resources/ci/with/toad/edge/CreateSnapshotBuilder/help-inputFileOrFolder.html+1 7 modified
    @@ -12,13 +12,7 @@
     	  Folder/file location must be specified as:
     	  <ul>
     		  <li>
    -		  Absolute path to location on your Jenkins master node
    -		  </li>
    -		  <li>
    -		  Relative path to your project's workspace. Either starting with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir. 
    -		  </li>
    -		  <li>
    -		  Relative path to your job's run root directory. It must start with ${JOB_ROOT_DIR} prefix. i.e. ${JOB_ROOT_DIR}dir.
    +			  Relative or absolute path to your project's workspace. Relative path should start with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir.
     		  </li>
     	  </ul>
       </p>
    
  • src/main/resources/ci/with/toad/edge/DeployScriptBuilder/help-in.html+1 7 modified
    @@ -8,13 +8,7 @@
     	  File location must be specified as:
     	  <ul>
     		  <li>
    -		  Absolute path to location on your Jenkins master node
    -		  </li>
    -		  <li>
    -		  Relative path to your project's workspace. Either starting with ${WORKSPACE} prefix. i.e. ${WORKSPACE}file or without prefix i.e. dir. 
    -		  </li>
    -		  <li>
    -		  Relative path to your job's run root directory. It must start with ${JOB_ROOT_DIR} prefix. i.e. ${JOB_ROOT_DIR}file.
    +			  Relative or absolute path to your project's workspace. Relative path should start with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir.
     		  </li>
     	  </ul>
       </p>
    
  • src/main/resources/ci/with/toad/edge/DeployScriptBuilder/help-out.html+1 7 modified
    @@ -8,13 +8,7 @@
     	  File location must be specified as:
     	  <ul>
     		  <li>
    -		  Absolute path to location on your Jenkins master node
    -		  </li>
    -		  <li>
    -		  Relative path to your project's workspace. Either starting with ${WORKSPACE} prefix. i.e. ${WORKSPACE}file or without prefix i.e. dir. 
    -		  </li>
    -		  <li>
    -		  Relative path to your job's run root directory. It must start with ${JOB_ROOT_DIR} prefix. i.e. ${JOB_ROOT_DIR}file.
    +			  Relative or absolute path to your project's workspace. Relative path should start with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir.
     		  </li>
     	  </ul>
       </p>
    
  • src/main/resources/ci/with/toad/edge/GenerateChangeScriptBuilder/help-in.html+1 7 modified
    @@ -9,13 +9,7 @@
     	  	Folder location must be specified as:
     	  	<ul>
     		  	<li>
    -		  	Absolute path to location on your Jenkins master node
    -		  	</li>
    -		  	<li>
    -		  	Relative path to your project's workspace. Either starting with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir. 
    -		  	</li>
    -		  	<li>
    -		  	Relative path to your job's run root directory. It must start with ${JOB_ROOT_DIR} prefix. i.e. ${JOB_ROOT_DIR}dir.
    +				Relative or absolute path to your project's workspace. Relative path should start with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir.
     		  	</li>
     	  	</ul>
       	</p>
    
  • src/main/resources/ci/with/toad/edge/GenerateCreateScriptBuilder/help-inputFileOrFolder.html+1 7 modified
    @@ -13,13 +13,7 @@
     	  Folder/file location must be specified as:
     	  <ul>
     		  <li>
    -		  Absolute path to location on your Jenkins master node
    -		  </li>
    -		  <li>
    -		  Relative path to your project's workspace. Either starting with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir. 
    -		  </li>
    -		  <li>
    -		  Relative path to your job's run root directory. It must start with ${JOB_ROOT_DIR} prefix. i.e. ${JOB_ROOT_DIR}dir.
    +			  Relative or absolute path to your project's workspace. Relative path should start with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir.
     		  </li>
     	  </ul>
       </p>
    
  • src/main/resources/ci/with/toad/edge/GenerateJenkinsReportBuilder/help-inputFolder.html+1 7 modified
    @@ -8,13 +8,7 @@
     	  Folder location must be specified as:
     	  <ul>
     		  <li>
    -		  Absolute path to location on your Jenkins master node
    -		  </li>
    -		  <li>
    -		  Relative path to your project's workspace. Either starting with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir. 
    -		  </li>
    -		  <li>
    -		  Relative path to your job's run root directory. It must start with ${JOB_ROOT_DIR} prefix. i.e. ${JOB_ROOT_DIR}dir.
    +			  Relative or absolute path to your project's workspace. Relative path should start with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir.
     		  </li>
     	  </ul>
       </p>
    
  • src/main/resources/ci/with/toad/edge/GenerateStandaloneReportBuilder/help-inputFolder.html+1 7 modified
    @@ -8,13 +8,7 @@
     	  Folder location must be specified as:
     	  <ul>
     		  <li>
    -		  Absolute path to location on your Jenkins master node
    -		  </li>
    -		  <li>
    -		  Relative path to your project's workspace. Either starting with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir. 
    -		  </li>
    -		  <li>
    -		  Relative path to your job's run root directory. It must start with ${JOB_ROOT_DIR} prefix. i.e. ${JOB_ROOT_DIR}dir.
    +              Relative or absolute path to your project's workspace. Relative path should start with ${WORKSPACE} prefix. i.e. ${WORKSPACE}dir or without prefix i.e. dir.
     		  </li>
     	  </ul>
       </p>
    

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

1