VYPR
High severityNVD Advisory· Published Dec 7, 2022· Updated Apr 23, 2025

CVE-2022-46682

CVE-2022-46682

Description

Jenkins Plot Plugin 2.1.11 and earlier does not configure its XML parser to prevent XML external entity (XXE) attacks.

AI Insight

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

Jenkins Plot Plugin 2.1.11 and earlier is vulnerable to XXE attacks via crafted XML input files, allowing secret extraction or SSRF.

The Jenkins Plot Plugin (versions 2.1.11 and earlier) fails to disable external entity resolution in its XML parser when processing XML input files for the 'Plot build data' build step [1][4]. This omission allows XML External Entity (XXE) attacks, a well-known class of XML parsing vulnerabilities.

An attacker who can control the XML input files used by the plugin (e.g., by committing a malicious file to a source repository or uploading it to the Jenkins workspace) can craft a file that includes external entities [1]. No special authentication is required beyond the ability to trigger a build that uses the Plot build step with the attacker-controlled file.

Successful exploitation can lead to extraction of secrets from the Jenkins controller (e.g., credentials, environment variables) via file inclusion, or to server-side request forgery (SSRF) by making the Jenkins server issue requests to internal or external systems [1][4]. The impact is high, as it can compromise the confidentiality of sensitive data and enable further attacks.

The vulnerability is fixed in Plot Plugin version 2.1.12, which disables external entity resolution for its XML parser [1][3]. Users are advised to update to this version immediately. No workarounds are mentioned in the advisory.

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:plotMaven
< 2.1.122.1.12

Affected products

3

Patches

1
4f7afbe064aa

SECURITY-2940

https://github.com/jenkinsci/plot-pluginJean-Marc MeessenDec 2, 2022via ghsa
4 files changed · +62 7
  • .gitignore+2 1 modified
    @@ -4,4 +4,5 @@ work
     .project
     .settings
     *.iml
    -.idea
    \ No newline at end of file
    +.idea
    +.vscode
    \ No newline at end of file
    
  • src/main/java/hudson/plugins/plot/XMLSeries.java+17 5 modified
    @@ -9,6 +9,8 @@
     import hudson.Extension;
     import hudson.FilePath;
     import hudson.model.Descriptor;
    +
    +import java.io.IOException;
     import java.io.InputStream;
     import java.io.PrintStream;
     import java.util.ArrayDeque;
    @@ -21,11 +23,14 @@
     import java.util.Scanner;
     import java.util.logging.Level;
     import java.util.logging.Logger;
    +
     import javax.xml.namespace.QName;
     import javax.xml.xpath.XPath;
     import javax.xml.xpath.XPathConstants;
     import javax.xml.xpath.XPathExpressionException;
     import javax.xml.xpath.XPathFactory;
    +
    +import jenkins.util.xml.XMLUtils;
     import net.sf.json.JSONObject;
     import org.apache.commons.io.IOUtils;
     import org.apache.commons.lang.ArrayUtils;
    @@ -35,6 +40,7 @@
     import org.w3c.dom.Node;
     import org.w3c.dom.NodeList;
     import org.xml.sax.InputSource;
    +import org.xml.sax.SAXException;
     
     /**
      * Represents a plot data series configuration from an XML file.
    @@ -203,10 +209,7 @@ public List<PlotPoint> loadSeries(FilePath workspaceRootDir, int buildNumber,
                     if (LOGGER.isLoggable(DEFAULT_LOG_LEVEL)) {
                         LOGGER.log(DEFAULT_LOG_LEVEL, "Loading plot series data from: " + getFile());
                     }
    -
                     in = seriesFiles[0].read();
    -                // load existing plot file
    -                inputSource = new InputSource(in);
                 } catch (Exception e) {
                     LOGGER.log(Level.SEVERE,
                             "Exception reading plot series data from " + seriesFiles[0], e);
    @@ -221,8 +224,10 @@ public List<PlotPoint> loadSeries(FilePath workspaceRootDir, int buildNumber,
                     LOGGER.log(DEFAULT_LOG_LEVEL, "Loaded XML Plot file: " + getFile());
                 }
     
    +
                 XPath xpath = XPathFactory.newInstance().newXPath();
    -            Object xmlObject = xpath.evaluate(xpathString, inputSource, nodeType);
    +            Object xmlObject = xpath.evaluate(xpathString, XMLUtils.parse(in), nodeType);
    +
     
                 /*
                  * If we have a nodeset, we need multiples, otherwise we just need
    @@ -266,6 +271,13 @@ public List<PlotPoint> loadSeries(FilePath workspaceRootDir, int buildNumber,
                 return ret;
             } catch (XPathExpressionException e) {
                 LOGGER.log(Level.SEVERE, "XPathExpressionException for XPath '" + getXpath() + "'", e);
    +        }  catch (SAXException e) {
    +            if (logger != null) {
    +                logger.println(e.getMessage());
    +            }
    +            LOGGER.log(Level.SEVERE, "Exception parsing XML", e);
    +        } catch (IOException e) {
    +            LOGGER.log(Level.SEVERE, "Unexpected IO Error", e);
             } finally {
                 IOUtils.closeQuietly(in);
             }
    @@ -280,7 +292,7 @@ private void addNodeToList(List<PlotPoint> ret, Node n, int buildNumber) {
                 addValueToList(ret, nodeMap.getNamedItem("name").getTextContent().trim(),
                         n, buildNumber);
             } else {
    -            addValueToList(ret, n.getLocalName().trim(), n, buildNumber);
    +            addValueToList(ret, n.getNodeName().trim(), n, buildNumber);
             }
         }
     
    
  • src/test/java/hudson/plugins/plot/XMLSeriesTest.java+35 1 modified
    @@ -2,12 +2,20 @@
     
     import org.junit.Test;
     
    +import java.io.ByteArrayOutputStream;
    +import java.io.PrintStream;
    +import java.io.UnsupportedEncodingException;
    +import java.nio.charset.StandardCharsets;
     import java.util.HashMap;
     import java.util.List;
     import java.util.Map;
     
    -import static org.junit.Assert.assertEquals;
    +import static org.hamcrest.CoreMatchers.containsString;
    +import static org.hamcrest.MatcherAssert.assertThat;
    +import static org.junit.Assert.assertNull;
     import static org.junit.Assert.assertNotNull;
    +import static org.junit.Assert.assertEquals;
    +
     
     /**
      * Test an XML series.
    @@ -18,6 +26,7 @@ public class XMLSeriesTest extends SeriesTestCase {
         private static final String TEST_XML_FILE = "test.xml";
         private static final String TEST2_XML_FILE = "test2.xml";
         private static final String TEST3_XML_FILE = "test3.xml";
    +    private static final String TEST4_XML_FILE = "test4.xml";
     
         @Test
         public void testXMLSeries_WhenNodesSharingAParentHaveOneStringAndOneNumericContent_ThenCoalesceNodesToPointLabelledWithStringContent() {
    @@ -204,4 +213,29 @@ public void testXMLSeriesUrl() {
             assertEquals("http://localhost/42/one/0", points.get(0).getUrl());
             assertEquals("http://localhost/42/two/0", points.get(1).getUrl());
         }
    +
    +    @Test
    +    public void testXMLSeries_failToReadExternalDTD() throws UnsupportedEncodingException {
    +        // Create a new XML series with test file
    +        String xpathString = "/results/testcase/*";
    +        XMLSeries series = new XMLSeries(TEST4_XML_FILE, xpathString, "NODESET", null);
    +        testSeries(series, TEST4_XML_FILE, "", "xml");
    +
    +        //we want to examin the logoutput
    +        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
    +        final String utf8 = StandardCharsets.UTF_8.name();
    +        PrintStream customOutput = new PrintStream(baos, true, utf8);
    +
    +        // load the series to see if we have the expected behavior.
    +        List<PlotPoint> points = series.loadSeries(workspaceRootDir, 0, customOutput);
    +
    +
    +        assertNull(points);
    +
    +        String expectedOutput = "DOCTYPE is disallowed when the feature \"http://apache.org/xml/features/disallow-doctype-decl\" set to true";
    +        String customOutputAsString = baos.toString();
    +        assertNotNull(customOutputAsString);
    +        //depending on the "JRE" (?) the custom output is terminated or not by a \n
    +        assertThat(customOutputAsString, containsString(expectedOutput));
    +    }
     }
    
  • src/test/resources/test4.xml+8 0 added
    @@ -0,0 +1,8 @@
    +<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
    +<!DOCTYPE html SYSTEM "https://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    +<html>
    +  <testcase name="first/one">
    +    <one>0.521</one>
    +    <two>0.5015</two>
    +  </testcase>
    +</html>
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

1