HTML injection vulnerability in Fortify Plugin
Description
Jenkins Fortify Plugin 22.1.38 and earlier has an HTML injection vulnerability due to unescaped error messages in form validation.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Jenkins Fortify Plugin 22.1.38 and earlier has an HTML injection vulnerability due to unescaped error messages in form validation.
Vulnerability
Description
The Jenkins Fortify Plugin versions 22.1.38 and earlier fail to properly escape error messages returned by a form validation method. This oversight allows an attacker to inject arbitrary HTML into the Jenkins user interface when the validation fails [1][2][3]. The root cause is that the plugin does not sanitize the error message before rendering it in the Jenkins UI, leading to an HTML injection vulnerability.
Exploitation
An attacker can exploit this vulnerability by crafting a malicious input that triggers a validation error. The unescaped error message is then displayed in the Jenkins web interface, allowing the attacker to inject HTML content. The attack does not require authentication if the form validation endpoint is accessible without proper permissions; however, the commit addressing this issue also adds a @POST annotation and permission checks, suggesting that the endpoint may have been accessible via GET requests or without sufficient authorization [1][2].
Impact
Successful exploitation enables an attacker to inject arbitrary HTML into the Jenkins UI. This can be used for phishing attacks, defacement, or to trick users into performing actions that compromise their credentials or the system. The vulnerability is classified as medium severity in the Jenkins security advisory [2].
Mitigation
The vulnerability is fixed in Fortify Plugin version 22.1.39. Users are strongly advised to update to this version or later. The fix ensures that error messages are properly escaped and that the form validation method requires POST requests and appropriate permissions [1][2]. No workarounds are available; updating the plugin is the recommended course of action.
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.
| Package | Affected versions | Patched versions |
|---|---|---|
org.jenkins-ci.plugins:fortifyMaven | < 22.2.39 | 22.2.39 |
Affected products
2- Range: 0
Patches
1357d7bfbcb0fSECURITY-3115, SECURITY-3139, SECURITY-3140, SECURITY-3141
7 files changed · +222 −95
src/main/java/com/fortify/plugin/jenkins/FortifyPlugin.java+133 −45 modified@@ -41,6 +41,7 @@ import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.verb.POST; import com.cloudbees.plugins.credentials.Credentials; import com.cloudbees.plugins.credentials.CredentialsMatchers; @@ -1253,6 +1254,7 @@ public FormValidation doCheckBreakdownPageSize(@QueryParameter String value) { return FormValidation.ok(); } + @POST public FormValidation doCheckUrl(@QueryParameter String value) { try { checkUrlValue(value == null ? null : value.trim()); @@ -1262,13 +1264,15 @@ public FormValidation doCheckUrl(@QueryParameter String value) { return FormValidation.ok(); } + @POST public FormValidation doCheckSscTokenCredentialsId(@QueryParameter String value, @QueryParameter String url) { if (StringUtils.isBlank(value) && (StringUtils.isNotBlank(url) && doCheckUrl(url) == FormValidation.ok())) { return FormValidation.warning("Authentication token cannot be empty"); } return FormValidation.ok(); } + @POST public FormValidation doCheckCtrlTokenCredentialsId(@QueryParameter String value, @QueryParameter String ctrlUrl) { if (StringUtils.isBlank(value) && StringUtils.isNotBlank(ctrlUrl)) { return FormValidation.warning("Controller token cannot be empty"); @@ -1288,7 +1292,9 @@ public FormValidation doCheckFpr(@QueryParameter String value) { } } + @POST public FormValidation doCheckProjectTemplate(@QueryParameter String value) { + checkAdministerPermission(); try { checkProjectTemplateName(value.trim()); } catch (FortifyException e) { @@ -1337,6 +1343,7 @@ public FormValidation doCheckPollingInterval(@QueryParameter String value) { } } + @POST public FormValidation doCheckCtrlUrl(@QueryParameter String value, @QueryParameter String url) { if (StringUtils.isBlank(value)) { if (StringUtils.isNotBlank(url) && (doCheckUrl(url) == FormValidation.ok())) { @@ -1353,6 +1360,7 @@ public FormValidation doCheckCtrlUrl(@QueryParameter String value, @QueryParamet return FormValidation.ok(); } + @POST public ListBoxModel doFillSscTokenCredentialsIdItems(@AncestorInPath Item item, @QueryParameter String sscTokenCredentialsId, @QueryParameter String url) { StandardListBoxModel result = new StandardListBoxModel(); if (item == null) { @@ -1368,8 +1376,14 @@ public ListBoxModel doFillSscTokenCredentialsIdItems(@AncestorInPath Item item, .includeMatchingAs(ACL.SYSTEM, item, FortifyApiToken.class, URIRequirementBuilder.fromUri(url).build(), CredentialsMatchers.instanceOf(FortifyApiToken.class)); } + @POST public FormValidation doTestConnection(@QueryParameter String url, @QueryParameter String sscTokenCredentialsId, @QueryParameter Boolean isProxy, @QueryParameter Integer connectTimeout, @QueryParameter Integer readTimeout, @QueryParameter Integer writeTimeout) { + checkAdministerPermission(); + return testSscConnection(url, sscTokenCredentialsId, isProxy, connectTimeout, readTimeout, writeTimeout); + } + + private FormValidation testSscConnection(final String url, final String sscTokenCredentialsId, final Boolean isProxy, final Integer connectTimeout, final Integer readTimeout, final Integer writeTimeout) { String sscUrl = url == null ? "" : url.trim(); try { checkUrlValue(sscUrl); @@ -1418,9 +1432,9 @@ public NoReturn runWith(FortifyClient client) throws Exception { } catch (Throwable t) { String message = t.getMessage(); if (message != null && message.contains("Access Denied")) { - return FormValidation.errorWithMarkup("Invalid token. (" + message + ")"); + return FormValidation.error("Invalid token. (" + removeHtmlFormatting(message) + ")"); } - return FormValidation.errorWithMarkup("Cannot connect to SSC server. " + message); + return FormValidation.error("Cannot connect to SSC server. " + removeHtmlFormatting(message)); } finally { this.url = orig_url; setIsProxy(orig_isProxy); @@ -1431,6 +1445,14 @@ public NoReturn runWith(FortifyClient client) throws Exception { } } + private String removeHtmlFormatting(String html) { + if (html != null) { + // we're using the simplest approach here in order not to introduce a new library dependency in this release + return html.replaceAll("<[^>]*>", ""); + } + return ""; + } + private FortifyApiToken getTokenFrom(String tokenId, String url) throws FortifyException { FortifyApiToken c = tokenId == null ? null : CredentialsMatchers.firstOrNull( CredentialsProvider.lookupCredentials(FortifyApiToken.class, Jenkins.get(), ACL.SYSTEM, @@ -1439,6 +1461,7 @@ private FortifyApiToken getTokenFrom(String tokenId, String url) throws FortifyE return c; } + @POST public ListBoxModel doFillCtrlTokenCredentialsIdItems(@AncestorInPath Item item, @QueryParameter String ctrlTokenCredentialsId, @QueryParameter String ctrlUrl) { StandardListBoxModel result = new StandardListBoxModel(); if (item == null) { @@ -1456,7 +1479,9 @@ public ListBoxModel doFillCtrlTokenCredentialsIdItems(@AncestorInPath Item item, CredentialsMatchers.instanceOf(FortifyApiToken.class)); } + @POST public FormValidation doTestCtrlConnection(@QueryParameter String ctrlUrl, @QueryParameter String ctrlTokenCredentialsId, @QueryParameter Boolean isProxy) throws IOException { + checkAdministerPermission(); String controllerUrl = ctrlUrl == null ? "" : ctrlUrl.trim(); try { checkCtrlUrlValue(controllerUrl); @@ -1549,6 +1574,10 @@ private void checkCtrlUrlValue(String ctrlUrl) throws FortifyException { if (ctrlUrl.endsWith("/")) { ctrlUrl = ctrlUrl.substring(0, ctrlUrl.length()-1); } + int hash = ctrlUrl.indexOf("%23"); + if (hash > 0) { + ctrlUrl = ctrlUrl.substring(0, hash); + } if (!StringUtils.endsWith(ctrlUrl,"/scancentral-ctrl") && !StringUtils.endsWith(ctrlUrl,"/cloud-ctrl")) { throw new FortifyException(new Message(Message.ERROR, "Invalid context")); } @@ -1561,7 +1590,13 @@ private void checkCtrlUrlValue(String ctrlUrl) throws FortifyException { } } - public void doRefreshProjects(StaplerRequest req, StaplerResponse rsp, @QueryParameter String value) throws Exception { + @POST + public void doRefreshProjects(StaplerRequest req, StaplerResponse rsp, @QueryParameter String value, @AncestorInPath Item item) throws Exception { + if (item != null) { + item.checkPermission(Item.CONFIGURE); + } else { + Jenkins.get().checkPermission(Jenkins.ADMINISTER); + } try { String typedText = sanitizeUnicodeControls(req.getParameter("typedText")); // always retrieve data from SSC @@ -1587,7 +1622,13 @@ public void doRefreshProjects(StaplerRequest req, StaplerResponse rsp, @QueryPar } } - public void doRefreshVersions(StaplerRequest req, StaplerResponse rsp, @QueryParameter String value) throws Exception { + @POST + public void doRefreshVersions(StaplerRequest req, StaplerResponse rsp, @QueryParameter String value, @AncestorInPath Item item) throws Exception { + if (item != null) { + item.checkPermission(Item.CONFIGURE); + } else { + Jenkins.get().checkPermission(Jenkins.ADMINISTER); + } try { String selectedApp = sanitizeUnicodeControls(req.getParameter("selectedPrj")); String typedText = sanitizeUnicodeControls(req.getParameter("typedText")); @@ -1638,7 +1679,9 @@ private String escapeJsonValue(String stringValue) { return stringValue.replace("\"", "\\\""); } + @POST public void doRefreshProjectTemplates(StaplerRequest req, StaplerResponse rsp, @QueryParameter String value) throws Exception { + checkAdministerPermission(); // backup original values String orig_url = this.url; ProxyConfig orig_proxyConfig = this.proxyConfig; @@ -1661,7 +1704,7 @@ public void doRefreshProjectTemplates(StaplerRequest req, StaplerResponse rsp, @ this.sscTokenCredentialsId = tokenId; try { - FormValidation testConnectionResult = doTestConnection(this.url, this.getSscTokenCredentialsId(), useProxyParam, connectTimeout, readTimeout, writeTimeout); + FormValidation testConnectionResult = testSscConnection(this.url, this.getSscTokenCredentialsId(), useProxyParam, connectTimeout, readTimeout, writeTimeout); if (!testConnectionResult.kind.equals(FormValidation.Kind.OK)) { LOGGER.log(Level.WARNING, "Can't retrieve Fortify Issue Template list because of SSC server connection problem: " + testConnectionResult.getLocalizedMessage()); return; // don't get templates if server is unavailable @@ -1695,15 +1738,21 @@ public void doRefreshProjectTemplates(StaplerRequest req, StaplerResponse rsp, @ } } + private static void checkAdministerPermission() { + Jenkins.get().checkPermission(Jenkins.ADMINISTER); + } + + @POST public void doRefreshSensorPools(StaplerRequest req, StaplerResponse rsp, @QueryParameter String value) throws Exception { + checkAdministerPermission(); // backup original values String orig_url = this.url; String url = req.getParameter("url"); this.url = url != null ? url.trim() : ""; try { - FormValidation testConnectionResult = doTestConnection(this.url, this.getSscTokenCredentialsId(), this.getIsProxy(), connectTimeout, readTimeout, writeTimeout); //XXX verify ctrl or ssc token id is needed + FormValidation testConnectionResult = testSscConnection(this.url, this.getSscTokenCredentialsId(), this.getIsProxy(), connectTimeout, readTimeout, writeTimeout); //XXX verify ctrl or ssc token id is needed if (!testConnectionResult.kind.equals(FormValidation.Kind.OK)) { throw new Exception(testConnectionResult.getLocalizedMessage()); // don't get sensor pools if server is unavailable } @@ -1733,7 +1782,13 @@ public void doRefreshSensorPools(StaplerRequest req, StaplerResponse rsp, @Query } } - public void doCreateNewProject(final StaplerRequest req, StaplerResponse rsp, @QueryParameter String value) throws Exception { + @POST + public void doCreateNewProject(final StaplerRequest req, StaplerResponse rsp, @QueryParameter String value, @AncestorInPath Item item) throws Exception { + if (item != null) { + item.checkPermission(Item.CONFIGURE); + } else { + Jenkins.get().checkPermission(Jenkins.ADMINISTER); + } try { runWithFortifyClient(getToken(), new FortifyClient.Command<FortifyClient.NoReturn>() { @Override @@ -1749,7 +1804,7 @@ public NoReturn runWith(FortifyClient client) throws Exception { e.printStackTrace(); } - doRefreshProjects(req, rsp, value); + doRefreshProjects(req, rsp, value, item); } private boolean isSettingUpdated = false; @@ -1798,25 +1853,41 @@ public boolean isSettingUpdated() { } } - public ComboBoxModel doFillAppNameItems() { - Map<String, Long> allPrj = getAllProjects(null); + @POST + public ComboBoxModel doFillAppNameItems(@AncestorInPath Item item) { + Map<String, Long> allPrj; + if (item != null) { + item.checkPermission(Item.CONFIGURE); + allPrj = getAllProjects(null); + } else { + allPrj = Collections.emptyMap(); + } return new ComboBoxModel(allPrj.keySet()); } - public ComboBoxModel getAppNameItems() { - return doFillAppNameItems(); + @POST + public ComboBoxModel getAppNameItems(@AncestorInPath Item item) { + return doFillAppNameItems(item); } - public ComboBoxModel doFillAppVersionItems(@QueryParameter String appName) { - Map<String, Long> allPrjVersions = getVersionsFor(appName); - if (null == allPrjVersions) { - return new ComboBoxModel(Collections.<String>emptyList()); + @POST + public ComboBoxModel doFillAppVersionItems(@QueryParameter String appName, @AncestorInPath Item item) { + Map<String, Long> allPrjVersions; + if (item != null) { + item.checkPermission(Item.CONFIGURE); + allPrjVersions = getVersionsFor(appName); + if (null == allPrjVersions) { + return new ComboBoxModel(Collections.<String>emptyList()); + } + } else { + allPrjVersions = Collections.emptyMap(); } return new ComboBoxModel(allPrjVersions.keySet()); } - public ComboBoxModel getAppVersionItems(@QueryParameter String appName) { - return doFillAppVersionItems(appName); + @POST + public ComboBoxModel getAppVersionItems(@QueryParameter String appName, @AncestorInPath Item item) { + return doFillAppVersionItems(appName, item); } private Map<String, Long> getAllProjects(String query) { @@ -1878,11 +1949,15 @@ public Map<String, Long> runWith(FortifyClient client) throws Exception { } } - public AutoCompletionCandidates doAutoCompleteAppName(@QueryParameter String value) { + @POST + public AutoCompletionCandidates doAutoCompleteAppName(@QueryParameter String value, @AncestorInPath Item item) { AutoCompletionCandidates c = new AutoCompletionCandidates(); - for (String nextApp : getAllProjects(value).keySet()) { - if (nextApp.toLowerCase(Locale.ENGLISH).startsWith(value.toLowerCase(Locale.ENGLISH))) { - c.add(nextApp); + if (item != null) { + item.checkPermission(Item.CONFIGURE); + for (String nextApp : getAllProjects(value).keySet()) { + if (nextApp.toLowerCase(Locale.ENGLISH).startsWith(value.toLowerCase(Locale.ENGLISH))) { + c.add(nextApp); + } } } return c; @@ -1895,20 +1970,28 @@ public AutoCompletionCandidates doAutoCompleteAppName(@QueryParameter String val * @return A list of Issue template and ID * @throws ApiException */ - public ComboBoxModel doFillProjectTemplateItems() { - if (projTemplateList.isEmpty()) { - projTemplateList = getProjTemplateListNoCache(); + @POST + public ComboBoxModel doFillProjectTemplateItems(@AncestorInPath Item item) { + List<String> names; + if (item != null) { + item.checkPermission(Item.CONFIGURE); + if (projTemplateList.isEmpty()) { + projTemplateList = getProjTemplateListNoCache(); + } + names = new ArrayList<String>(projTemplateList.size()); + for (ProjectTemplateBean b : projTemplateList) { + names.add(b.getName()); + } + } else { + names = Collections.emptyList(); } - List<String> names = new ArrayList<String>(projTemplateList.size()); - for (ProjectTemplateBean b : projTemplateList) { - names.add(b.getName()); - } return new ComboBoxModel(names); } - public ComboBoxModel getProjectTemplateItems() { - return doFillProjectTemplateItems(); + @POST + public ComboBoxModel getProjectTemplateItems(@AncestorInPath Item item) { + return doFillProjectTemplateItems(item); } public List<ProjectTemplateBean> getProjTemplateListList() { @@ -1950,13 +2033,17 @@ public int compare(ProjectTemplateBean o1, ProjectTemplateBean o2) { return Collections.emptyList(); } - public ListBoxModel doFillFilterSetItems(@QueryParameter String appName, @QueryParameter String appVersion) { + @POST + public ListBoxModel doFillFilterSetItems(@QueryParameter String appName, @QueryParameter String appVersion, @AncestorInPath Item item) { ListBoxModel standardListBoxModel = new ListBoxModel(); - standardListBoxModel.add(""); - Map<String, String> allFilterSets = refreshFilterSetsFor(appName, appVersion); - if (allFilterSets != null) { - for (Map.Entry<String, String> nextFilterSet : allFilterSets.entrySet()) { - standardListBoxModel.add(nextFilterSet.getKey(), nextFilterSet.getValue()); + if (item != null) { + item.checkPermission(Item.CONFIGURE); + standardListBoxModel.add(""); + Map<String, String> allFilterSets = refreshFilterSetsFor(appName, appVersion); + if (allFilterSets != null) { + for (Map.Entry<String, String> nextFilterSet : allFilterSets.entrySet()) { + standardListBoxModel.add(nextFilterSet.getKey(), nextFilterSet.getValue()); + } } } return standardListBoxModel; @@ -1995,16 +2082,17 @@ public Map<String, String> runWith(FortifyClient client) throws Exception { return Collections.emptyMap(); } - public ListBoxModel doFillSensorPoolUUIDItems() { - sensorPoolList = getSensorPoolListNoCache(); - + @POST + public ListBoxModel doFillSensorPoolUUIDItems(@AncestorInPath Item item) { List<ListBoxModel.Option> optionList = new ArrayList<>(); - - for (SensorPoolBean sensorPoolBean : sensorPoolList) { - ListBoxModel.Option option = new ListBoxModel.Option(sensorPoolBean.getName(), sensorPoolBean.getUuid()); - optionList.add(option); + if (item != null) { + item.checkPermission(Item.CONFIGURE); + sensorPoolList = getSensorPoolListNoCache(); + for (SensorPoolBean sensorPoolBean : sensorPoolList) { + ListBoxModel.Option option = new ListBoxModel.Option(sensorPoolBean.getName(), sensorPoolBean.getUuid()); + optionList.add(option); + } } - return new ListBoxModel(optionList); }
src/main/java/com/fortify/plugin/jenkins/steps/CloudScanMbs.java+18 −10 modified@@ -28,11 +28,14 @@ import org.jenkinsci.plugins.workflow.steps.StepDescriptor; import org.jenkinsci.plugins.workflow.steps.StepExecution; import org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution; +import hudson.model.Item; +import org.kohsuke.stapler.AncestorInPath; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.verb.POST; import com.fortify.plugin.jenkins.FortifyPlugin; import com.google.common.collect.ImmutableSet; @@ -247,26 +250,31 @@ public FormValidation doCheckBuildID(@QueryParameter String value) { return Validators.checkFieldNotEmpty(value); } - public void doRefreshProjects(StaplerRequest req, StaplerResponse rsp, @QueryParameter String value) + @POST + public void doRefreshProjects(StaplerRequest req, StaplerResponse rsp, @QueryParameter String value, @AncestorInPath Item item) throws Exception { - FortifyPlugin.DESCRIPTOR.doRefreshProjects(req, rsp, value); + FortifyPlugin.DESCRIPTOR.doRefreshProjects(req, rsp, value, item); } - public void doRefreshVersions(StaplerRequest req, StaplerResponse rsp, @QueryParameter String value) + @POST + public void doRefreshVersions(StaplerRequest req, StaplerResponse rsp, @QueryParameter String value, @AncestorInPath Item item) throws Exception { - FortifyPlugin.DESCRIPTOR.doRefreshVersions(req, rsp, value); + FortifyPlugin.DESCRIPTOR.doRefreshVersions(req, rsp, value, item); } - public ComboBoxModel doFillAppNameItems() { - return FortifyPlugin.DESCRIPTOR.doFillAppNameItems(); + @POST + public ComboBoxModel doFillAppNameItems(@AncestorInPath Item item) { + return FortifyPlugin.DESCRIPTOR.doFillAppNameItems(item); } - public ComboBoxModel doFillAppVersionItems(@QueryParameter String appName) { - return FortifyPlugin.DESCRIPTOR.doFillAppVersionItems(appName); + @POST + public ComboBoxModel doFillAppVersionItems(@QueryParameter String appName, @AncestorInPath Item item) { + return FortifyPlugin.DESCRIPTOR.doFillAppVersionItems(appName, item); } - public ListBoxModel doFillSensorPoolUUIDItems() { - return FortifyPlugin.DESCRIPTOR.doFillSensorPoolUUIDItems(); + @POST + public ListBoxModel doFillSensorPoolUUIDItems(@AncestorInPath Item item) { + return FortifyPlugin.DESCRIPTOR.doFillSensorPoolUUIDItems(item); } }
src/main/java/com/fortify/plugin/jenkins/steps/CloudScanStart.java+18 −10 modified@@ -22,17 +22,20 @@ import java.util.List; import java.util.Set; +import hudson.model.Item; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.jenkinsci.plugins.workflow.steps.StepContext; import org.jenkinsci.plugins.workflow.steps.StepDescriptor; import org.jenkinsci.plugins.workflow.steps.StepExecution; import org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution; +import org.kohsuke.stapler.AncestorInPath; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.verb.POST; import com.fortify.plugin.jenkins.FortifyPlugin; import com.fortify.plugin.jenkins.steps.remote.GradleProjectType; @@ -372,26 +375,31 @@ public Set<? extends Class<?>> getRequiredContext() { return ImmutableSet.of(Run.class, FilePath.class, EnvVars.class, Launcher.class, TaskListener.class); } - public void doRefreshProjects(StaplerRequest req, StaplerResponse rsp, @QueryParameter String value) + @POST + public void doRefreshProjects(StaplerRequest req, StaplerResponse rsp, @QueryParameter String value, @AncestorInPath Item item) throws Exception { - FortifyPlugin.DESCRIPTOR.doRefreshProjects(req, rsp, value); + FortifyPlugin.DESCRIPTOR.doRefreshProjects(req, rsp, value, item); } - public void doRefreshVersions(StaplerRequest req, StaplerResponse rsp, @QueryParameter String value) + @POST + public void doRefreshVersions(StaplerRequest req, StaplerResponse rsp, @QueryParameter String value, @AncestorInPath Item item) throws Exception { - FortifyPlugin.DESCRIPTOR.doRefreshVersions(req, rsp, value); + FortifyPlugin.DESCRIPTOR.doRefreshVersions(req, rsp, value, item); } - public ComboBoxModel doFillAppNameItems() { - return FortifyPlugin.DESCRIPTOR.doFillAppNameItems(); + @POST + public ComboBoxModel doFillAppNameItems(@AncestorInPath Item item) { + return FortifyPlugin.DESCRIPTOR.doFillAppNameItems(item); } - public ComboBoxModel doFillAppVersionItems(@QueryParameter String appName) { - return FortifyPlugin.DESCRIPTOR.doFillAppVersionItems(appName); + @POST + public ComboBoxModel doFillAppVersionItems(@QueryParameter String appName, @AncestorInPath Item item) { + return FortifyPlugin.DESCRIPTOR.doFillAppVersionItems(appName, item); } - public ListBoxModel doFillSensorPoolUUIDItems() { - return FortifyPlugin.DESCRIPTOR.doFillSensorPoolUUIDItems(); + @POST + public ListBoxModel doFillSensorPoolUUIDItems(@AncestorInPath Item item) { + return FortifyPlugin.DESCRIPTOR.doFillSensorPoolUUIDItems(item); } }
src/main/java/com/fortify/plugin/jenkins/steps/FortifyUpload.java+18 −10 modified@@ -34,11 +34,13 @@ import org.jenkinsci.plugins.workflow.steps.StepDescriptor; import org.jenkinsci.plugins.workflow.steps.StepExecution; import org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution; +import org.kohsuke.stapler.AncestorInPath; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.verb.POST; import com.fortify.plugin.jenkins.FPRSummary; import com.fortify.plugin.jenkins.FortifyPlugin; @@ -63,6 +65,7 @@ import hudson.Util; import hudson.model.AbstractBuild; import hudson.model.BuildListener; +import hudson.model.Item; import hudson.model.Result; import hudson.model.Run; import hudson.model.StreamBuildListener; @@ -789,24 +792,29 @@ public Set<? extends Class<?>> getRequiredContext() { return ImmutableSet.of(Run.class, FilePath.class, EnvVars.class, Launcher.class, TaskListener.class); } - public ComboBoxModel getApplicationNameItems() { - return FortifyPlugin.DESCRIPTOR.getAppNameItems(); + @POST + public ComboBoxModel getApplicationNameItems(@AncestorInPath Item item) { + return FortifyPlugin.DESCRIPTOR.getAppNameItems(item); } - public ComboBoxModel getApplicationVersionItems(@QueryParameter String applicationName) { - return FortifyPlugin.DESCRIPTOR.getAppVersionItems(applicationName); + @POST + public ComboBoxModel getApplicationVersionItems(@QueryParameter String applicationName, @AncestorInPath Item item) { + return FortifyPlugin.DESCRIPTOR.getAppVersionItems(applicationName, item); } - public void doRefreshApplications(StaplerRequest req, StaplerResponse rsp, @QueryParameter String value) throws Exception { - FortifyPlugin.DESCRIPTOR.doRefreshProjects(req, rsp, value); + @POST + public void doRefreshApplications(StaplerRequest req, StaplerResponse rsp, @QueryParameter String value, @AncestorInPath Item item) throws Exception { + FortifyPlugin.DESCRIPTOR.doRefreshProjects(req, rsp, value, item); } - public void doRefreshVersions(StaplerRequest req, StaplerResponse rsp, @QueryParameter String value) throws Exception { - FortifyPlugin.DESCRIPTOR.doRefreshVersions(req, rsp, value); + @POST + public void doRefreshVersions(StaplerRequest req, StaplerResponse rsp, @QueryParameter String value, @AncestorInPath Item item) throws Exception { + FortifyPlugin.DESCRIPTOR.doRefreshVersions(req, rsp, value, item); } - public ListBoxModel doFillFilterSetItems(@QueryParameter String appName, @QueryParameter String appVersion) { - return FortifyPlugin.DESCRIPTOR.doFillFilterSetItems(appName, appVersion); + @POST + public ListBoxModel doFillFilterSetItems(@QueryParameter String appName, @QueryParameter String appVersion, @AncestorInPath Item item) { + return FortifyPlugin.DESCRIPTOR.doFillFilterSetItems(appName, appVersion, item); } public FormValidation doCheckAppName(@QueryParameter String value) {
src/main/java/com/fortify/plugin/jenkins/TableAction.java+7 −2 modified@@ -31,6 +31,7 @@ import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; import org.kohsuke.stapler.bind.JavaScriptMethod; +import org.kohsuke.stapler.verb.POST; import com.fortify.plugin.jenkins.bean.IssueBean; import com.fortify.plugin.jenkins.bean.IssueFolderBean; @@ -371,6 +372,7 @@ public synchronized List<IssueFolderBean> getFolders() { return folders; } + @POST public void doSetPageSize(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { String size = req.getParameter("size"); Integer hadValue = (Integer) req.getSession().getAttribute("pageSize"); @@ -399,9 +401,9 @@ public void doSelectedGrouping(StaplerRequest req, StaplerResponse rsp) throws I } - // we removed that functionality because it stopped working with the REST client - // API, need to re-think a little + @POST public void doShowAllNotNew(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { + // we removed that functionality because it stopped working with the REST client API, need to re-think a little String all = req.getParameter("all"); if (StringUtils.isBlank(all)) { return; @@ -422,6 +424,7 @@ public void doShowAllNotNew(StaplerRequest req, StaplerResponse rsp) throws IOEx doAjaxIssues(req, rsp); } + @POST public void doUpdateIssueList(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { String viewName = req.getParameter("folder"); if (StringUtils.isBlank(viewName)) { @@ -446,6 +449,7 @@ public void doUpdateIssueList(StaplerRequest req, StaplerResponse rsp) throws IO doAjaxIssues(req, rsp); } + @POST public void doAjaxIssues(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { Object currView = req.getSession().getAttribute("currentView"); if ("yes".equalsIgnoreCase(req.getParameter("firstTime")) || currView == null) { @@ -468,6 +472,7 @@ public void doAjaxStats(StaplerRequest req, StaplerResponse rsp) throws IOExcept req.getView(this, "issueCountTable.jelly").forward(req, rsp); } + @POST public synchronized void doCheckUpdates(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { long lastChanged = getLastChanged();
src/main/resources/com/fortify/plugin/jenkins/FortifyPlugin/global.jelly+3 −3 modified@@ -27,7 +27,7 @@ <f:section title="Fortify Assessment"> <f:section title="Software Security Center configuration"> <f:entry title="SSC URL" field="url" help="/plugin/fortify/help-sscUrl.html"> - <f:textbox name="url" id="url"/> + <f:textbox name="url" id="url" checkMethod="post"/> </f:entry> <f:entry field="sscTokenCredentialsId" title="Authentication token" help="/plugin/fortify/help-sscAuthToken.html"> @@ -41,7 +41,7 @@ <f:entry title="Issue template" help="/plugin/fortify/help-sscProjTemplate.html"> <script type="text/javascript" src="${rootURL}/plugin/fortify/refresh-projects.js"/> <div style="float:left;width:80%;"> - <f:editableComboBox id="projectTemplate" name="projectTemplate" field="projectTemplate" clazz="setting-input" items="${descriptor.projectTemplateItems}" /> + <f:editableComboBox id="projectTemplate" name="projectTemplate" field="projectTemplate" clazz="setting-input" items="${descriptor.projectTemplateItems}" checkMethod="post"/> </div> <div style="float:left"> <input value="▼" type="button" id="refreshButton" onclick="refreshTemplateList('${rootURL}/descriptor/${descriptor.clazz.name}/refreshProjectTemplates','url,sscTokenCredentialsId,isProxy')" /> @@ -72,7 +72,7 @@ <f:section title="Controller configuration"> <f:entry title="Controller URL" help="/plugin/fortify/help-controllerUrl.html"> - <f:textbox name="ctrlUrl" field="ctrlUrl" id="ctrlUrl"/> + <f:textbox name="ctrlUrl" field="ctrlUrl" id="ctrlUrl" checkMethod="post"/> </f:entry> <f:entry field="ctrlTokenCredentialsId" title="Controller token" help="/plugin/fortify/help-controllerToken.html">
src/main/webapp/refresh-issues.js+25 −15 modified@@ -15,7 +15,7 @@ *******************************************************************************/ var isUpdateEnable = true; - function updateByUrl(boxId,urlLink,spinnerUrl) { + function updateByUrl(boxId,urlLink,params,spinnerUrl) { // first display the "loading..." icon if (isUpdateEnable) { isUpdateEnable = false; @@ -24,6 +24,7 @@ // then actually fetch the HTML new Ajax.Request(urlLink, { method: "post", + parameters: params, onComplete: function(rsp,_) { var issueTable = document.getElementById('issueTable'); if (issueTable != null) { @@ -36,34 +37,40 @@ } function updateList(boxId,folder,nextPage,spinnerUrl) { - updateByUrl(boxId,contextUrl+"/updateIssueList?folder=" + folder + "&page=" + nextPage,spinnerUrl); + var params = {'folder' : folder, 'page' : nextPage}; + updateByUrl(boxId,contextUrl+"/updateIssueList",params,spinnerUrl); } function updateListWithSort(boxId,folder,nextPage,sortOrd,spinnerUrl) { - updateByUrl(boxId,contextUrl+"/updateIssueList?folder=" + folder + "&page=" + nextPage + "&sort=" + sortOrd,spinnerUrl); + var params = {'folder' : folder, 'page' : nextPage, 'sort' : sortOrd}; + updateByUrl(boxId,contextUrl+"/updateIssueList",params,spinnerUrl); } function updatePageSize(boxId,aSize,spinnerUrl) { - updateByUrl(boxId,contextUrl+"/setPageSize?size=" + aSize,spinnerUrl); + var params = {'size' : aSize}; + updateByUrl(boxId,contextUrl+"/setPageSize",params,spinnerUrl); } function showNew(boxId,spinnerUrl) { - updateByUrl(boxId,contextUrl+"/showAllNotNew?all=no",spinnerUrl); + var params = 'all=no'; + updateByUrl(boxId,contextUrl+"/showAllNotNew",params,spinnerUrl); } function showAll(boxId,spinnerUrl) { - updateByUrl(boxId,contextUrl+"/showAllNotNew?all=yes",spinnerUrl); + var params = 'all=yes'; + updateByUrl(boxId,contextUrl+"/showAllNotNew",params,spinnerUrl); } - function showGrouping(boxId,selectedGrouping,spinnerUrl) - { - updateByUrl(boxId,contextUrl+"/selectedGrouping?grouping="+selectedGrouping, spinnerUrl); + function showGrouping(boxId,selectedGrouping,spinnerUrl) { + var params = {'grouping' : selectedGrouping}; + updateByUrl(boxId,contextUrl+"/selectedGrouping",params, spinnerUrl); } function scheduleUpdateCheck() { - var parameters = {}; - new Ajax.Request(contextUrl+"/checkUpdates?stamp="+stamp,{ - method: "get", + var params = 'stamp='+stamp; + new Ajax.Request(contextUrl+"/checkUpdates",{ + method: "post", + parameters: params, onComplete: function(rsp,_) { var update = rsp.getResponseHeader('go'); if(update == "go") { @@ -80,7 +87,7 @@ function reloadStatistics() { var parameters = {}; new Ajax.Request(contextUrl+"/ajaxStats",{ - method: "get", + method: "post", onComplete: function(rsp,_) { var scanStatistics = document.getElementById('scanStatistics'); if (scanStatistics != null) { @@ -93,6 +100,7 @@ function reloadIssues() { var parameters = {}; new Ajax.Request(contextUrl+"/ajaxIssues",{ + method: "post", parameters: parameters, onComplete: function(rsp) { var issueTable = document.getElementById('issueTable'); @@ -106,6 +114,7 @@ function reload(url,box) { var parameters = {}; new Ajax.Request(url,{ + method: "post", parameters: parameters, onComplete: function(rsp) { var issueTable = document.getElementById(box); @@ -122,8 +131,9 @@ var box = document.getElementById('firstTimeSpinF'); box.innerHTML = '<img src="'+spinnerUrl+'" alt=""/>'; // then actually fetch the HTML - var request = new Ajax.Request(contextUrl+"/ajaxIssues?firstTime=yes",{ - method: "get", + var request = new Ajax.Request(contextUrl+"/ajaxIssues",{ + method: "post", + parameters : "firstTime=yes", onComplete: function(rsp,_) { var issueTable = document.getElementById('issueTable'); issueTable.innerHTML = rsp.responseText;
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4- github.com/advisories/GHSA-223m-pgcq-f3xgghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2023-4303ghsaADVISORY
- www.jenkins.io/security/advisory/2023-08-16/ghsavendor-advisoryWEB
- github.com/jenkinsci/fortify-plugin/commit/357d7bfbcb0ff796ea7d078bee13159f1d000f5dghsaWEB
News mentions
1- Jenkins Security Advisory 2023-08-16Jenkins Security Advisories · Aug 16, 2023