VYPR
Moderate severityNVD Advisory· Published Sep 20, 2023· Updated Sep 24, 2024

CVE-2023-43501

CVE-2023-43501

Description

A missing permission check in Jenkins Build Failure Analyzer Plugin 2.4.1 and earlier allows attackers with Overall/Read permission to connect to an attacker-specified hostname and port using attacker-specified username and password.

AI Insight

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

Jenkins Build Failure Analyzer Plugin 2.4.1 and earlier lacks a permission check, allowing Overall/Read users to SSRF to attacker-specified hosts with attacker-specified credentials.

Root

Cause

The Jenkins Build Failure Analyzer Plugin, versions 2.4.1 and earlier, fails to perform a required permission check when processing certain build failure analysis operations. This missing permission check means that the plugin does not verify whether the current user has the necessary authorization (e.g., Overall/Administer) before allowing a connection to an external host [1][2].

Exploitation

An attacker with only the Overall/Read permission — a relatively low-privileged role — can craft a request that causes the plugin to initiate an outbound network connection. The attacker can specify both the target hostname and port, as well as a username and password pair. No additional authentication or special privileges are needed beyond Overall/Read [1][2].

Impact

This vulnerability constitutes a server-side request forgery (SSRF) with attacker-controlled credentials. An attacker can use the Jenkins server as a proxy to probe internal network services, attempt brute-force or credential-stuffing attacks against those services, or potentially exploit trust relationships between the Jenkins server and other systems. Since the request includes arbitrary credentials, the attacker may try to authenticate to internal resources, potentially spreading the attack inside the network [2][3].

Mitigation

The vulnerability is fixed in Build Failure Analyzer Plugin version 2.4.2 [2][3][4]. Users should upgrade to this version immediately. No workarounds are described, and Jenkins has not included this CVE in the Known Exploited Vulnerabilities (KEV) catalog as of the advisory date.

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
com.sonyericsson.jenkins.plugins.bfa:build-failure-analyzerMaven
< 2.4.22.4.2

Affected products

2

Patches

1
a261229a67c5

[SECURITY-3226][SECURITY-3239][SECURITY-3244]

5 files changed · +114 1
  • src/main/java/com/sonyericsson/jenkins/plugins/bfa/AnnotationHelper.java+4 1 modified
    @@ -23,6 +23,7 @@
      */
     package com.sonyericsson.jenkins.plugins.bfa;
     
    +import hudson.Functions;
     import java.io.Serializable;
     
     /**
    @@ -43,7 +44,9 @@ public class AnnotationHelper implements Serializable {
          */
         public String getBefore() {
             if (!title.isEmpty()) {
    -            return before + "<span style=\"color:white;background:red\" title=\"" + title + "\">";
    +            return before
    +                    + "<span style=\"color:white;background:red\" title=\""
    +                    + Functions.htmlAttributeEscape(title) + "\">";
             } else {
                 return before;
             }
    
  • src/main/java/com/sonyericsson/jenkins/plugins/bfa/CauseManagement.java+2 0 modified
    @@ -44,6 +44,7 @@
     import org.kohsuke.stapler.Stapler;
     import org.kohsuke.stapler.StaplerRequest;
     import org.kohsuke.stapler.StaplerResponse;
    +import org.kohsuke.stapler.verb.POST;
     import java.io.IOException;
     
     /**
    @@ -220,6 +221,7 @@ public FailureCause getDynamic(String id, StaplerRequest request, StaplerRespons
          * @param response the stapler response.
          * @throws IOException if so during redirect.
          */
    +    @POST
         public void doRemoveConfirm(@QueryParameter String id, StaplerRequest request, StaplerResponse response)
                 throws IOException {
             Jenkins.getInstance().checkPermission(PluginImpl.REMOVE_PERMISSION);
    
  • src/main/java/com/sonyericsson/jenkins/plugins/bfa/db/MongoDBKnowledgeBase.java+3 0 modified
    @@ -82,6 +82,7 @@
     import org.kohsuke.stapler.DataBoundConstructor;
     import org.kohsuke.stapler.DataBoundSetter;
     import org.kohsuke.stapler.QueryParameter;
    +import org.kohsuke.stapler.verb.POST;
     import org.mongojack.JacksonMongoCollection;
     import org.mongojack.internal.MongoJackModule;
     
    @@ -868,6 +869,7 @@ public FormValidation doCheckDbName(@QueryParameter("value") String value) {
              * @return {@link FormValidation#ok() } if can be done,
              *         {@link FormValidation#error(java.lang.String) } otherwise.
              */
    +        @POST
             public FormValidation doTestConnection(
                     @QueryParameter("host") final String host,
                     @QueryParameter("port") final int port,
    @@ -876,6 +878,7 @@ public FormValidation doTestConnection(
                     @QueryParameter("password") final String password,
                     @QueryParameter("tls") final boolean tls,
                     @QueryParameter("retrywrites") final boolean retryWrites) {
    +            Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER);
                 MongoDBKnowledgeBase base = new MongoDBKnowledgeBase(host, port, dbName, userName,
                         Secret.fromString(password), false, false);
                 base.setTls(tls);
    
  • src/test/java/com/sonyericsson/jenkins/plugins/bfa/CauseManagementPermissionTest.java+63 0 modified
    @@ -1,17 +1,23 @@
     package com.sonyericsson.jenkins.plugins.bfa;
     
    +import jenkins.model.Jenkins;
     import org.htmlunit.FailingHttpStatusCodeException;
    +import org.htmlunit.HttpMethod;
    +import org.htmlunit.WebRequest;
     import org.htmlunit.html.HtmlPage;
     import hudson.model.Hudson;
     import hudson.security.GlobalMatrixAuthorizationStrategy;
     import hudson.security.SecurityRealm;
     import org.junit.Before;
     import org.junit.Rule;
     import org.junit.Test;
    +import org.jvnet.hudson.test.Issue;
     import org.jvnet.hudson.test.JenkinsRule;
     
     import javax.servlet.http.HttpServletResponse;
     
    +import java.net.URL;
    +
     import static org.junit.Assert.assertEquals;
     import static org.junit.Assert.assertNotNull;
     import static org.junit.Assert.assertNull;
    @@ -24,6 +30,10 @@
      */
     public class CauseManagementPermissionTest {
     
    +    private static final int EXPECTED_HTTP_NOT_FOUND_RESPONSE_CODE = 404;
    +    private static final int EXPECTED_HTTP_FORBIDDEN_RESPONSE_CODE = 403;
    +    private static final int EXPECTED_HTTP_SUCCESS_RESPONSE_CODE = 200;
    +
         /**
          * The Jenkins Rule.
          */
    @@ -44,8 +54,11 @@ public void jenkinsConfiguration() {
             authorizationStrategy.add(Hudson.READ, "anonymous");
             authorizationStrategy.add(PluginImpl.VIEW_PERMISSION, "view");
             authorizationStrategy.add(PluginImpl.UPDATE_PERMISSION, "update");
    +        authorizationStrategy.add(PluginImpl.REMOVE_PERMISSION, "remove");
             authorizationStrategy.add(PluginImpl.VIEW_PERMISSION, "all");
             authorizationStrategy.add(PluginImpl.UPDATE_PERMISSION, "all");
    +        authorizationStrategy.add(PluginImpl.REMOVE_PERMISSION, "all");
    +        authorizationStrategy.add(Jenkins.ADMINISTER, "admin");
             j.getInstance().setAuthorizationStrategy(authorizationStrategy);
         }
     
    @@ -128,4 +141,54 @@ public void allowedToUpdateCausesWhenGrantedBothUpdateAndView() throws Exception
             // Checks the "Create New" button is available
             assertNotNull(page.getFirstByXPath("//a[.='Create new']"));
         }
    +
    +    /**
    +     * Tests that removeConfirm only can be used with POST, and responds with 404 otherwise.
    +     *
    +     * @throws java.lang.Exception If Jenkins cannot be accessed
    +     */
    +    @Issue("SECURITY-3239")
    +    @Test
    +    public void testDoRemoveConfirmRequiresPost() throws Exception {
    +        JenkinsRule.WebClient webClient = j.createWebClient().withThrowExceptionOnFailingStatusCode(false);
    +        webClient.login("all");
    +        assertEquals(
    +                EXPECTED_HTTP_NOT_FOUND_RESPONSE_CODE,
    +                webClient.goTo("failure-cause-management/removeConfirm").getWebResponse().getStatusCode());
    +        WebRequest webRequest = new WebRequest(
    +                new URL(j.jenkins.getRootUrl().toString() + "/failure-cause-management/removeConfirm"),
    +                HttpMethod.POST);
    +        webRequest = webClient.addCrumb(webRequest);
    +        assertEquals(
    +                EXPECTED_HTTP_SUCCESS_RESPONSE_CODE,
    +                webClient.getPage(webRequest).getWebResponse().getStatusCode());
    +    }
    +
    +    /**
    +     * Test that testing mongo connection can only be accessed through a POST request from an admin.
    +     *
    +     * @throws Exception if Jenkins cannot be accessed
    +     */
    +    @Issue("SECURITY-3226")
    +    @Test
    +    public void testTestMongoDBConnection() throws Exception {
    +        JenkinsRule.WebClient webClient = j.createWebClient().withThrowExceptionOnFailingStatusCode(false);
    +        String testUrl = "descriptorByName/com.sonyericsson.jenkins.plugins.bfa.db.MongoDBKnowledgeBase/"
    +                + "testConnection?port=9876&host=localhost&&dbName=Whatever\n";
    +        assertEquals(
    +                EXPECTED_HTTP_NOT_FOUND_RESPONSE_CODE,
    +                webClient.goTo(testUrl).getWebResponse().getStatusCode());
    +        webClient.login("all");
    +        WebRequest webRequest = new WebRequest(
    +                new URL(j.jenkins.getRootUrl().toString() + testUrl),
    +                HttpMethod.POST);
    +        webRequest = webClient.addCrumb(webRequest);
    +        assertEquals(
    +                EXPECTED_HTTP_FORBIDDEN_RESPONSE_CODE,
    +                webClient.getPage(webRequest).getWebResponse().getStatusCode());
    +        webClient.login("admin");
    +        assertEquals(
    +                EXPECTED_HTTP_SUCCESS_RESPONSE_CODE,
    +                webClient.getPage(webRequest).getWebResponse().getStatusCode());
    +    }
     }
    
  • src/test/java/com/sonyericsson/jenkins/plugins/bfa/IndicationAnnotatorTest.java+42 0 added
    @@ -0,0 +1,42 @@
    +package com.sonyericsson.jenkins.plugins.bfa;
    +
    +import static org.junit.Assert.assertTrue;
    +
    +import com.sonyericsson.jenkins.plugins.bfa.model.FailureCause;
    +import com.sonyericsson.jenkins.plugins.bfa.model.FoundFailureCause;
    +import com.sonyericsson.jenkins.plugins.bfa.model.indication.FoundIndication;
    +import hudson.MarkupText;
    +import org.junit.Test;
    +import org.jvnet.hudson.test.Issue;
    +import java.util.ArrayList;
    +import java.util.List;
    +
    +/**
    + * Tests for the IndicationAnnotator.
    + *
    + * @author Tomas Westling &lt;tomas.westling@axis.com&gt;
    + */
    +public class IndicationAnnotatorTest {
    +
    +    private static final String EXPECTED_ANNOTATED_TEXT = "tilt&quot; onmouseover=alert(1) foo=&quot;bar";
    +
    +    /**
    +     * Tests that html is escaped correctly when annotating text.
    +     */
    +    @Issue("SECURITY-3244")
    +    @Test
    +    public void testAnnotate() {
    +        MarkupText text = new MarkupText("matchingString");
    +        FoundIndication fi = new FoundIndication(
    +                "pattern", "matchingFile", "matchingString");
    +        List<FoundIndication> fis = new ArrayList<>();
    +        fis.add(fi);
    +        FoundFailureCause ffc = new FoundFailureCause(
    +                new FailureCause("tilt\" onmouseover=alert(1) foo=\"bar", "description"), fis);
    +        List<FoundFailureCause> foundFailureCauses = new ArrayList<>();
    +        foundFailureCauses.add(ffc);
    +        IndicationAnnotator ia = new IndicationAnnotator(foundFailureCauses);
    +        ia.annotate(null, text);
    +        assertTrue(text.toString(false).indexOf(EXPECTED_ANNOTATED_TEXT) != -1);
    +    }
    +}
    

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