VYPR
Moderate severityNVD Advisory· Published Nov 4, 2020· Updated Aug 4, 2024

CVE-2020-2305

CVE-2020-2305

Description

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

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.jenkins-ci.plugins:mercurialMaven
>= 2.11, < 2.122.12
org.jenkins-ci.plugins:mercurialMaven
>= 2.10, < 2.10.12.10.1
org.jenkins-ci.plugins:mercurialMaven
>= 2.9, < 2.9.12.9.1
org.jenkins-ci.plugins:mercurialMaven
< 2.8.12.8.1

Affected products

1

Patches

1
84af58b08f80

[SECURITY-2115]

https://github.com/jenkinsci/mercurial-pluginJesse GlickOct 29, 2020via ghsa
3 files changed · +85 70
  • pom.xml+2 2 modified
    @@ -17,7 +17,7 @@
         <properties>
             <revision>2.12</revision>
             <changelist>-SNAPSHOT</changelist>
    -        <jenkins.version>2.176.4</jenkins.version>
    +        <jenkins.version>2.190.3</jenkins.version>
             <java.level>8</java.level>
             <no-test-jar>false</no-test-jar>
             <reuseForks>false</reuseForks> <!-- long story -->
    @@ -78,7 +78,7 @@
             <dependencies>
                 <dependency>
                     <groupId>io.jenkins.tools.bom</groupId>
    -                <artifactId>bom-2.176.x</artifactId>
    +                <artifactId>bom-2.190.x</artifactId>
                     <version>13</version>
                     <scope>import</scope>
                     <type>pom</type>
    
  • src/main/java/hudson/plugins/mercurial/MercurialChangeLogParser.java+65 24 modified
    @@ -4,15 +4,17 @@
     import hudson.model.Run;
     import hudson.scm.ChangeLogParser;
     import hudson.scm.RepositoryBrowser;
    -import hudson.util.Digester2;
     import java.io.File;
     import java.io.IOException;
     import java.util.ArrayList;
     import java.util.Comparator;
     import java.util.Iterator;
     import java.util.Set;
    +import jenkins.util.xml.XMLUtils;
     
    -import org.apache.commons.digester.Digester;
    +import org.w3c.dom.Element;
    +import org.w3c.dom.Node;
    +import org.w3c.dom.NodeList;
     import org.xml.sax.SAXException;
     
     /**
    @@ -30,35 +32,74 @@ public MercurialChangeLogParser(Set<String> modules) {
     
         @Override public MercurialChangeSetList parse(Run build, RepositoryBrowser<?> browser, File changelogFile)
                 throws IOException, SAXException {
    -        Digester digester = new Digester2();
    -        ArrayList<MercurialChangeSet> r = new ArrayList<MercurialChangeSet>();
    -        digester.push(r);
    -
    -        digester.addObjectCreate("*/changeset", MercurialChangeSet.class);
    -        digester.addSetProperties("*/changeset");
    -        digester.addSetProperties("*/changeset", "author", "user");
    -        digester.addBeanPropertySetter("*/changeset/msg");
    -        // Before JENKINS-55319:
    -        digester.addBeanPropertySetter("*/changeset/added");
    -        digester.addBeanPropertySetter("*/changeset/deleted");
    -        digester.addBeanPropertySetter("*/changeset/files");
    -        // After JENKINS-55319:
    -        digester.addCallMethod("*/changeset/file", "addFile", 1);
    -        digester.addCallParam("*/changeset/file", 0);
    -        digester.addCallMethod("*/changeset/addedFile", "addAddedFile", 1);
    -        digester.addCallParam("*/changeset/addedFile", 0);
    -        digester.addCallMethod("*/changeset/deletedFile", "addDeletedFile", 1);
    -        digester.addCallParam("*/changeset/deletedFile", 0);
    -        digester.addBeanPropertySetter("*/changeset/parents");
    -        digester.addSetNext("*/changeset", "add");
    +        ArrayList<MercurialChangeSet> r = new ArrayList<>();
     
    +        Element changesetsE;
             try {
    -            digester.parse(changelogFile);
    +            changesetsE = XMLUtils.parse(changelogFile, "UTF-8").getDocumentElement();
             } catch (IOException e) {
                 throw new IOException("Failed to parse " + changelogFile, e);
             } catch (SAXException e) {
                 throw new IOException("Failed to parse " + changelogFile + ": '" + Util.loadFile(changelogFile) + "'", e);
             }
    +        NodeList changesetsNL = changesetsE.getChildNodes();
    +        for (int i = 0; i < changesetsNL.getLength(); i++) {
    +            if (changesetsNL.item(i).getNodeType() != Node.ELEMENT_NODE) {
    +                continue;
    +            }
    +            Element changesetE = (Element) changesetsNL.item(i);
    +            MercurialChangeSet cs = new MercurialChangeSet();
    +            // See CHANGELOG_TEMPLATE:
    +            cs.setNode(changesetE.getAttribute("node"));
    +            if (changesetE.hasAttribute("user")) {
    +                cs.setAuthor(changesetE.getAttribute("user"));
    +            } else {
    +                cs.setAuthor(changesetE.getAttribute("author"));
    +            }
    +            if (changesetE.hasAttribute("rev")) { // unit tests omit it
    +                cs.setRev(Long.parseLong(changesetE.getAttribute("rev")));
    +            }
    +            cs.setDate(changesetE.getAttribute("date"));
    +            NodeList changesetNL = changesetE.getChildNodes();
    +            for (int j = 0; j < changesetNL.getLength(); j++) {
    +                if (changesetNL.item(j).getNodeType() != Node.ELEMENT_NODE) {
    +                    continue;
    +                }
    +                Element otherE = (Element) changesetNL.item(j);
    +                String text = otherE.getTextContent();
    +                switch (otherE.getTagName()) {
    +                case "msg":
    +                    cs.setMsg(text);
    +                    break;
    +                // Before JENKINS-55319:
    +                case "added":
    +                    cs.setAdded(text);
    +                    break;
    +                case "deleted":
    +                    cs.setDeleted(text);
    +                    break;
    +                case "files":
    +                    cs.setFiles(text);
    +                    break;
    +                // After JENKINS-55319:
    +                case "file":
    +                    cs.addFile(text);
    +                    break;
    +                case "addedFile":
    +                    cs.addAddedFile(text);
    +                    break;
    +                case "deletedFile":
    +                    cs.addDeletedFile(text);
    +                    break;
    +                case "parents":
    +                    cs.setParents(text);
    +                    break;
    +                default:
    +                    throw new IOException(otherE.getTagName());
    +                }
    +            }
    +            r.add(cs);
    +        }
     
             if (modules != null) {
                 Iterator<MercurialChangeSet> it = r.iterator();
    
  • src/main/java/hudson/plugins/mercurial/MercurialChangeSet.java+18 44 modified
    @@ -11,7 +11,7 @@
     import java.util.Collections;
     import java.util.List;
     import org.kohsuke.accmod.Restricted;
    -import org.kohsuke.accmod.restrictions.DoNotUse;
    +import org.kohsuke.accmod.restrictions.NoExternalUse;
     
     import org.kohsuke.stapler.export.Exported;
     
    @@ -203,91 +203,66 @@ public List<EditType> getEditTypes() {
             }
         }
     
    -//
    -// used by Digester 
    -//
    -    @Restricted(DoNotUse.class)
    -    public void setMsg(String msg) {
    +    // For use from MercurialChangeLogParser:
    +
    +    void setMsg(String msg) {
             this.msg = msg;
         }
     
    -    @Restricted(DoNotUse.class)
    +    @Restricted(NoExternalUse.class) // for tests
         public void setNode(String node) {
             this.node = node;
         }
     
    -    @Restricted(DoNotUse.class)
    -    public void setUser(String author) {
    -        this.author = author;
    -    }
    -
    -    @Restricted(DoNotUse.class)
    -    public String getUser() {
    -        return author;
    -    }
    -
    -    @Restricted(DoNotUse.class)
    -    public void setAuthor(String author) {
    +    void setAuthor(String author) {
             this.author = author;
         }
     
    -    @Restricted(DoNotUse.class)
    -    public void setRev(long rev) {
    +    void setRev(long rev) {
             this.rev = rev;
         }
     
    -    @Restricted(DoNotUse.class)
    -    public void setDate(String date) {
    +    void setDate(String date) {
             this.date = date;
         }
     
    -    @Restricted(DoNotUse.class)
    -    public void addAddedFile(String file) {
    +    void addAddedFile(String file) {
             added.add(file);
         }
     
    -    @Restricted(DoNotUse.class)
    -    public void addDeletedFile(String file) {
    +    void addDeletedFile(String file) {
             deleted.add(file);
         }
     
    -    @Restricted(DoNotUse.class)
    -    public void addFile(String file) {
    +    void addFile(String file) {
             modified.add(file);
         }
     
    -    /** @deprecated predates JENKINS-55319, here only for compatibility */
    -    @Deprecated
    -    @Restricted(DoNotUse.class)
    -    public void setAdded(String list) {
    +    /** predates JENKINS-55319, here only for compatibility */
    +    void setAdded(String list) {
             if (merge) {
                 return;
             }
             added = toList(list);
         }
     
    -    /** @deprecated predates JENKINS-55319, here only for compatibility */
    -    @Deprecated
    -    @Restricted(DoNotUse.class)
    -    public void setDeleted(String list) {
    +    /** predates JENKINS-55319, here only for compatibility */
    +    void setDeleted(String list) {
             if (merge) {
                 return;
             }
             deleted = toList(list);
         }
     
    -    /** @deprecated predates JENKINS-55319, here only for compatibility */
    -    @Deprecated
    -    @Restricted(DoNotUse.class)
    -    public void setFiles(String list) {
    +    /** predates JENKINS-55319, here only for compatibility */
    +    void setFiles(String list) {
             if (merge) {
                 return;
             }
             modified = toList(list);
         }
     
    -    @Restricted(DoNotUse.class)
    -    public void setParents(String parents) {
    +    void setParents(String parents) {
             // Possible values for parents when not using --debug:
             // ""                                     - commit made in succession
             // "6019:b70a530bdb93 "                   - commit with older parent
    @@ -299,7 +274,6 @@ public void setParents(String parents) {
             merge = parents.indexOf(':') != parents.lastIndexOf(':') && !parents.contains("-1");
         }
     
    -    @Deprecated
         private List<String> toList(String list) {
             list = list.trim();
             if(list.length()==0) return Collections.emptyList();
    

Vulnerability mechanics

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

References

5

News mentions

0

No linked articles in our index yet.