CVE-2022-43419
Description
Jenkins Katalon Plugin 1.0.32 and earlier stores API keys unencrypted in job config.xml files, exposing them to users with Extended Read permission or file system access.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Jenkins Katalon Plugin 1.0.32 and earlier stores API keys unencrypted in job config.xml files, exposing them to users with Extended Read permission or file system access.
Vulnerability
Details
Jenkins Katalon Plugin versions 1.0.32 and earlier stores API keys in plaintext within job config.xml files on the Jenkins controller [1][4]. This occurs because the plugin does not use Jenkins' built-in credential storage mechanism, instead writing the API key directly into the job configuration XML [3]. As a result, the sensitive credential is persisted unencrypted on disk.
Exploitation
Prerequisites
An attacker must have either the Extended Read permission on a job or direct access to the Jenkins controller's file system to read the config.xml file [1][2]. No additional authentication is required beyond these permissions. The vulnerability is present in all jobs that use the Katalon Plugin to configure API keys.
Impact
Successful exploitation allows an attacker to retrieve the stored API key, which could be used to authenticate to the Katalon service and potentially access or modify test artifacts, configurations, or other resources associated with the Jenkins instance [4]. The severity is considered medium (CVSS 5.5) according to the Jenkins security advisory [1].
Mitigation
The issue is fixed in Katalon Plugin versions 1.0.33 and 1.0.34, which migrate to using Jenkins' encrypted credential store [2][3]. Users should upgrade immediately. There is no workaround other than restricting Extended Read permissions and file system access to trusted users.
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 |
|---|---|---|
org.jenkins-ci.plugins:katalonMaven | < 1.0.33 | 1.0.33 |
Affected products
2- Range: unspecified
Patches
164f819387f3fMerge pull request #28 from katalon-studio/TES-948
2 files changed · +38 −39
src/main/java/com/katalon/jenkins/plugin/ExecuteKatalonTestOpsPlan.java+10 −39 modified@@ -1,15 +1,14 @@ package com.katalon.jenkins.plugin; import com.cloudbees.plugins.credentials.CredentialsMatchers; -import com.cloudbees.plugins.credentials.CredentialsProvider; import com.cloudbees.plugins.credentials.common.StandardListBoxModel; -import com.cloudbees.plugins.credentials.domains.DomainRequirement; import com.cloudbees.plugins.credentials.domains.URIRequirementBuilder; import com.katalon.jenkins.plugin.entity.Plan; import com.katalon.jenkins.plugin.entity.Project; import com.katalon.jenkins.plugin.helper.KatalonTestOpsHelper; import com.katalon.jenkins.plugin.helper.KatalonTestOpsSearchHelper; import com.katalon.jenkins.plugin.helper.JenkinsLogger; +import com.katalon.jenkins.plugin.helper.SecurityHelper; import com.katalon.utils.Logger; import hudson.Extension; import hudson.FilePath; @@ -23,6 +22,7 @@ import hudson.tasks.Builder; import hudson.util.FormValidation; import hudson.util.ListBoxModel; +import hudson.util.Secret; import jenkins.model.Jenkins; import jenkins.tasks.SimpleBuildStep; import net.sf.json.JSONObject; @@ -33,16 +33,12 @@ import javax.annotation.Nonnull; import java.io.IOException; -import java.util.Collections; -import java.util.List; import java.util.UUID; public class ExecuteKatalonTestOpsPlan extends Builder implements SimpleBuildStep { private String credentialsId; - private String apiKey; - private String plan; private String serverUrl; @@ -52,7 +48,6 @@ public class ExecuteKatalonTestOpsPlan extends Builder implements SimpleBuildSte @DataBoundConstructor public ExecuteKatalonTestOpsPlan( String credentialsId, - String apiKey, String serverUrl, String projectId, String planId) { @@ -68,7 +63,6 @@ public ExecuteKatalonTestOpsPlan( this.serverUrl = serverUrl; } this.credentialsId = credentialsId; - this.apiKey = apiKey; this.plan = planId; this.projectId = projectId; } @@ -81,14 +75,6 @@ public void setCredentialsId(String credentialsId) { this.credentialsId = credentialsId; } - public String getApiKey() { - return apiKey; - } - - public void setApiKey(String credentialsId) { - this.apiKey = credentialsId; - } - public String getServerUrl() { return serverUrl; } @@ -127,7 +113,8 @@ public void perform(@Nonnull Run<?, ?> run, @Nonnull FilePath filePath, @Nonnull private boolean doPerform(TaskListener taskListener) { Logger logger = new JenkinsLogger(taskListener); KatalonTestOpsHelper katalonAnalyticsHandler = new KatalonTestOpsHelper(logger); - return katalonAnalyticsHandler.run(serverUrl, apiKey, plan, projectId); + Secret apiKey = SecurityHelper.getApiKey(credentialsId); + return katalonAnalyticsHandler.run(serverUrl, apiKey.getPlainText(), plan, projectId); } @Override @@ -161,20 +148,6 @@ public boolean configure(StaplerRequest req, JSONObject formData) throws FormExc return super.configure(req, formData); } - private String getApiKey(String credentialsId) { - if (credentialsId == null) { - return null; - } - List<StringCredentials> creds = CredentialsProvider.lookupCredentials(StringCredentials.class, Jenkins.getInstance(), ACL.SYSTEM, Collections.<DomainRequirement>emptyList()); - StringCredentials credentials = null; - for (StringCredentials c : creds) { - if (credentialsId.matches(c.getId())) { - credentials = c; - } - } - return credentials == null ? null : credentials.getSecret().getPlainText(); - } - public FormValidation doTestConnection(@QueryParameter("serverUrl") final String url, @QueryParameter("credentialsId") final String credentialsId) { if (url.isEmpty()) { @@ -185,14 +158,14 @@ public FormValidation doTestConnection(@QueryParameter("serverUrl") final String return FormValidation.error("Please select credentials."); } - String apiKey = getApiKey(credentialsId); + Secret apiKey = SecurityHelper.getApiKey(credentialsId); if (apiKey == null) { return FormValidation.error("Cannot get API key."); } try { KatalonTestOpsHelper katalonTestOpsHelper = new KatalonTestOpsHelper(); - String token = katalonTestOpsHelper.requestToken(url, apiKey); + String token = katalonTestOpsHelper.requestToken(url, apiKey.getPlainText()); if (token != null) { return FormValidation.ok("Success!"); } else { @@ -214,11 +187,11 @@ public ListBoxModel doFillProjectIdItems(@QueryParameter("serverUrl") final Stri } ListBoxModel options = new ListBoxModel(); - String apiKey = getApiKey(credentialsId); + Secret apiKey = SecurityHelper.getApiKey(credentialsId); if (apiKey != null) { KatalonTestOpsHelper katalonTestOpsHelper = new KatalonTestOpsHelper(); try { - String token = katalonTestOpsHelper.requestToken(url, apiKey); + String token = katalonTestOpsHelper.requestToken(url, apiKey.getPlainText()); if (token != null) { KatalonTestOpsSearchHelper katalonTestOpsSearchHelper = new KatalonTestOpsSearchHelper(); Project[] projects = katalonTestOpsSearchHelper.getProjects(token, url); @@ -251,15 +224,15 @@ public ListBoxModel doFillPlanItems(@QueryParameter("serverUrl") final String ur return new ListBoxModel(); } - String apiKey = getApiKey(credentialsId); + Secret apiKey = SecurityHelper.getApiKey(credentialsId); if (apiKey == null) { return new ListBoxModel(); } ListBoxModel options = new ListBoxModel(); KatalonTestOpsHelper katalonTestOpsHelper = new KatalonTestOpsHelper(); try { - String token = katalonTestOpsHelper.requestToken(url, apiKey); + String token = katalonTestOpsHelper.requestToken(url, apiKey.getPlainText()); if (token != null) { KatalonTestOpsSearchHelper katalonTestOpsSearchHelper = new KatalonTestOpsSearchHelper(); Plan[] plans = katalonTestOpsSearchHelper.getPlan(token, url, projectId); @@ -325,10 +298,8 @@ public ListBoxModel doFillCredentialsIdItems(@AncestorInPath Item item, @Override public Builder newInstance(StaplerRequest req, JSONObject formData) throws FormException { String credentialsId = formData.getString("credentialsId"); - String apiKey = getApiKey(credentialsId); return new ExecuteKatalonTestOpsPlan( credentialsId, - apiKey, formData.getString("serverUrl"), formData.getString("projectId"), formData.getString("plan"));
src/main/java/com/katalon/jenkins/plugin/helper/SecurityHelper.java+28 −0 added@@ -0,0 +1,28 @@ +package com.katalon.jenkins.plugin.helper; + +import com.cloudbees.plugins.credentials.CredentialsProvider; +import com.cloudbees.plugins.credentials.domains.DomainRequirement; +import hudson.security.ACL; +import hudson.util.Secret; +import jenkins.model.Jenkins; +import org.jenkinsci.plugins.plaincredentials.StringCredentials; + +import java.util.Collections; +import java.util.List; + +public class SecurityHelper { + + public static Secret getApiKey(String credentialsId) { + if (credentialsId == null) { + return null; + } + List<StringCredentials> creds = CredentialsProvider.lookupCredentials(StringCredentials.class, Jenkins.getInstance(), ACL.SYSTEM, Collections.<DomainRequirement>emptyList()); + StringCredentials credentials = null; + for (StringCredentials c : creds) { + if (credentialsId.matches(c.getId())) { + credentials = c; + } + } + return credentials == null ? null : credentials.getSecret(); + } +}
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/advisories/GHSA-35rx-7pc8-6963ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-43419ghsaADVISORY
- www.openwall.com/lists/oss-security/2022/10/19/3ghsamailing-listWEB
- github.com/jenkinsci/katalon-plugin/commit/64f819387f3f14d54f3a1542578a5c7aa9feb85cghsaWEB
- github.com/jenkinsci/katalon-plugin/pull/28ghsaWEB
- www.jenkins.io/security/advisory/2022-10-19/ghsaWEB
News mentions
0No linked articles in our index yet.