CVE-2019-10449
Description
Jenkins Fortify on Demand Plugin stores credentials unencrypted in job config.xml, exposing them to users with Extended Read or file system access.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Jenkins Fortify on Demand Plugin stores credentials unencrypted in job config.xml, exposing them to users with Extended Read or file system access.
Vulnerability
Jenkins Fortify on Demand Plugin stores credentials unencrypted in job config.xml files on the Jenkins master [1]. This includes the personal access token, client secret, and other authentication secrets [2]. The plugin does not use Jenkins' built-in Secret encryption mechanism, leaving credentials in plain text.
Exploitation
Users with Extended Read permission on a job or access to the Jenkins master file system can view the job config.xml file and retrieve the stored credentials [1]. No special privileges beyond those are required. The credentials are visible as plain text strings in the XML configuration.
Impact
An attacker who gains access to these credentials can authenticate to Fortify on Demand services as the victim, potentially accessing sensitive application security data, managing scans, or performing actions with the victim's privileges [1][2].
Mitigation
The fix implemented in commits [3] and [4] changes credential fields to use the hudson.util.Secret class, which encrypts the stored values. The plugin version containing the fix should be applied. Users are advised to upgrade to the latest version of the Fortify on Demand Plugin and also ensure Jenkins master file system access is restricted [1].
AI Insight generated on May 22, 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:fortify-on-demand-uploaderMaven | < 5.0.0 | 5.0.0 |
Affected products
2- Range: 4.0.0 and earlier
Patches
283b23662dc0cMerge pull request #85 from daniel-beck/SECURITY-1433
3 files changed · +10 −10
src/main/java/org/jenkinsci/plugins/fodupload/controllers/StaticScanController.java+0 −2 modified@@ -12,8 +12,6 @@ import org.jenkinsci.plugins.fodupload.models.JobModel; import org.jenkinsci.plugins.fodupload.models.response.GenericErrorResponse; import org.jenkinsci.plugins.fodupload.models.response.PostStartScanResponse; -import org.jenkinsci.plugins.fodupload.models.response.ReleaseAssessmentTypeDTO; -import sun.applet.Main; import java.io.File; import java.io.FileInputStream;
src/main/java/org/jenkinsci/plugins/fodupload/PollingBuildStep.java+5 −4 modified@@ -16,6 +16,7 @@ import hudson.tasks.Recorder; import hudson.util.FormValidation; import hudson.util.ListBoxModel; +import hudson.util.Secret; import jenkins.model.GlobalConfiguration; import jenkins.tasks.SimpleBuildStep; import org.jenkinsci.plugins.fodupload.polling.PollReleaseStatusResult; @@ -48,13 +49,13 @@ public PollingBuildStep(String bsiToken, String clientId, String clientSecret, String username, - String personalAccessToken, + Secret personalAccessToken, String tenantId) { sharedBuildStep = new SharedPollingBuildStep(bsiToken, overrideGlobalConfig, pollingInterval, policyFailureBuildResultPreference, clientId, clientSecret, - username, personalAccessToken, tenantId); + username, personalAccessToken.getEncryptedValue(), tenantId); } @Override @@ -93,8 +94,8 @@ public String getUsername() { } @SuppressWarnings("unused") - public String getPersonalAccessToken() { - return sharedBuildStep.getAuthModel().getPersonalAccessToken(); + public Secret getPersonalAccessToken() { + return Secret.fromString(sharedBuildStep.getAuthModel().getPersonalAccessToken()); } @SuppressWarnings("unused")
src/main/java/org/jenkinsci/plugins/fodupload/StaticAssessmentBuildStep.java+5 −4 modified@@ -15,6 +15,7 @@ import hudson.tasks.Recorder; import hudson.util.FormValidation; import hudson.util.ListBoxModel; +import hudson.util.Secret; import jenkins.tasks.SimpleBuildStep; import org.jenkinsci.plugins.fodupload.models.JobModel; import org.kohsuke.stapler.DataBoundConstructor; @@ -44,7 +45,7 @@ public class StaticAssessmentBuildStep extends Recorder implements SimpleBuildSt public StaticAssessmentBuildStep(String bsiToken, boolean overrideGlobalConfig, String username, - String personalAccessToken, + Secret personalAccessToken, String tenantId, boolean purchaseEntitlements, String entitlementPreference, @@ -55,7 +56,7 @@ public StaticAssessmentBuildStep(String bsiToken, sharedBuildStep = new SharedUploadBuildStep(bsiToken, overrideGlobalConfig, username, - personalAccessToken, + personalAccessToken.getEncryptedValue(), tenantId, purchaseEntitlements, entitlementPreference, @@ -107,8 +108,8 @@ public String getUsername() { } @SuppressWarnings("unused") - public String getPersonalAccessToken() { - return sharedBuildStep.getAuthModel().getPersonalAccessToken(); + public Secret getPersonalAccessToken() { + return Secret.fromString(sharedBuildStep.getAuthModel().getPersonalAccessToken()); } @SuppressWarnings("unused")
277642040362Address SECURITY-1433 leftovers
3 files changed · +10 −10
src/main/java/org/jenkinsci/plugins/fodupload/controllers/StaticScanController.java+0 −2 modified@@ -12,8 +12,6 @@ import org.jenkinsci.plugins.fodupload.models.JobModel; import org.jenkinsci.plugins.fodupload.models.response.GenericErrorResponse; import org.jenkinsci.plugins.fodupload.models.response.PostStartScanResponse; -import org.jenkinsci.plugins.fodupload.models.response.ReleaseAssessmentTypeDTO; -import sun.applet.Main; import java.io.File; import java.io.FileInputStream;
src/main/java/org/jenkinsci/plugins/fodupload/PollingBuildStep.java+5 −4 modified@@ -16,6 +16,7 @@ import hudson.tasks.Recorder; import hudson.util.FormValidation; import hudson.util.ListBoxModel; +import hudson.util.Secret; import jenkins.model.GlobalConfiguration; import jenkins.tasks.SimpleBuildStep; import org.jenkinsci.plugins.fodupload.polling.PollReleaseStatusResult; @@ -48,13 +49,13 @@ public PollingBuildStep(String bsiToken, String clientId, String clientSecret, String username, - String personalAccessToken, + Secret personalAccessToken, String tenantId) { sharedBuildStep = new SharedPollingBuildStep(bsiToken, overrideGlobalConfig, pollingInterval, policyFailureBuildResultPreference, clientId, clientSecret, - username, personalAccessToken, tenantId); + username, personalAccessToken.getEncryptedValue(), tenantId); } @Override @@ -93,8 +94,8 @@ public String getUsername() { } @SuppressWarnings("unused") - public String getPersonalAccessToken() { - return sharedBuildStep.getAuthModel().getPersonalAccessToken(); + public Secret getPersonalAccessToken() { + return Secret.fromString(sharedBuildStep.getAuthModel().getPersonalAccessToken()); } @SuppressWarnings("unused")
src/main/java/org/jenkinsci/plugins/fodupload/StaticAssessmentBuildStep.java+5 −4 modified@@ -15,6 +15,7 @@ import hudson.tasks.Recorder; import hudson.util.FormValidation; import hudson.util.ListBoxModel; +import hudson.util.Secret; import jenkins.tasks.SimpleBuildStep; import org.jenkinsci.plugins.fodupload.models.JobModel; import org.kohsuke.stapler.DataBoundConstructor; @@ -44,7 +45,7 @@ public class StaticAssessmentBuildStep extends Recorder implements SimpleBuildSt public StaticAssessmentBuildStep(String bsiToken, boolean overrideGlobalConfig, String username, - String personalAccessToken, + Secret personalAccessToken, String tenantId, boolean purchaseEntitlements, String entitlementPreference, @@ -55,7 +56,7 @@ public StaticAssessmentBuildStep(String bsiToken, sharedBuildStep = new SharedUploadBuildStep(bsiToken, overrideGlobalConfig, username, - personalAccessToken, + personalAccessToken.getEncryptedValue(), tenantId, purchaseEntitlements, entitlementPreference, @@ -107,8 +108,8 @@ public String getUsername() { } @SuppressWarnings("unused") - public String getPersonalAccessToken() { - return sharedBuildStep.getAuthModel().getPersonalAccessToken(); + public Secret getPersonalAccessToken() { + return Secret.fromString(sharedBuildStep.getAuthModel().getPersonalAccessToken()); } @SuppressWarnings("unused")
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-hhhh-69qp-5p2vghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2019-10449ghsaADVISORY
- github.com/jenkinsci/fortify-on-demand-uploader-plugin/commit/277642040362bcc64df163bfc1ab48f7763c2853ghsaWEB
- github.com/jenkinsci/fortify-on-demand-uploader-plugin/commit/83b23662dc0ce9486b904e282bd8047496730819ghsaWEB
- jenkins.io/security/advisory/2019-10-16/ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.