3breadt dd-plist xml external entity reference
Description
A vulnerability was found in 3breadt dd-plist 1.17 and classified as problematic. Affected by this issue is some unknown functionality. The manipulation leads to xml external entity reference. An attack has to be approached locally. Upgrading to version 1.18 is able to address this issue. The patch is identified as 8c954e8d9f6f6863729e50105a8abf3f87fff74c. It is recommended to upgrade the affected component. VDB-221486 is the identifier assigned to this vulnerability.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
dd-plist 1.17 is vulnerable to XML External Entity (XXE) attacks via crafted property lists, allowing local attackers to read files or conduct SSRF; upgrade to 1.18.
Vulnerability
Overview
The dd-plist library, version 1.17, contains an XML External Entity (XXE) vulnerability in its XMLPropertyListParser class. The library fails to disable external entity processing and DTD loading when parsing XML property lists, allowing an attacker to inject malicious XML content that references external entities. This issue is classified as problematic and requires local access to exploit [1].
Exploitation
Prerequisites
An attacker must be able to supply a crafted XML property list file to the parser. Since the attack vector is local, the attacker would need to place the malicious file on the system or trick a user into opening it via another application that uses dd-plist. No authentication is required beyond the ability to provide the file for parsing [1].
Impact
Successful exploitation could lead to information disclosure (e.g., reading local files through external entity references) or server-side request forgery (SSRF) if the parser can make outbound network connections. The exact impact depends on the context in which dd-plist is used, but XXE vulnerabilities can typically result in exposure of sensitive data [2].
Mitigation
The vulnerability is fixed in dd-plist version 1.18. The patch (commit 8c954e8d9f6f6863729e50105a8abf3f87fff74c) disables external entity processing and DTD loading, and sets XIncludeAware and expandEntityReferences to false [2]. Users should upgrade to the latest version. The fix was introduced via pull request #26, which also addresses loading of the DTD from the JAR file [4].
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 |
|---|---|---|
com.googlecode.plist:dd-plistMaven | < 1.18 | 1.18 |
Affected products
3Patches
18c954e8d9f6f1) Take steps to guard against external XXE attacks (except, note that <!DOCTYPE> cannot be disabled in XML plists).
3 files changed · +75 −48
build.xml+2 −1 modified@@ -34,7 +34,8 @@ <target name="jar" depends="compile"> <jar destfile="${dist}/${jar}"> - <fileset dir="${build}/classes"/> + <fileset dir="${build}/classes"/> + <fileset dir="${source}" includes="**/*.dtd"/> </jar> </target>
src/main/java/com/dd/plist/PropertyList-1.0.dtd+19 −0 added@@ -0,0 +1,19 @@ +<!ENTITY % plistObject "(array | data | date | dict | real | integer | string | true | false )" > +<!ELEMENT plist %plistObject;> +<!ATTLIST plist version CDATA "1.0" > + +<!-- Collections --> +<!ELEMENT array (%plistObject;)*> +<!ELEMENT dict (key, %plistObject;)*> +<!ELEMENT key (#PCDATA)> + +<!--- Primitive types --> +<!ELEMENT string (#PCDATA)> +<!ELEMENT data (#PCDATA)> <!-- Contents interpreted as Base-64 encoded --> +<!ELEMENT date (#PCDATA)> <!-- Contents should conform to a subset of ISO 8601 (in particular, YYYY '-' MM '-' DD 'T' HH ':' MM ':' SS 'Z'. Smaller units may be omitted with a loss of precision) --> + +<!-- Numerical primitives --> +<!ELEMENT true EMPTY> <!-- Boolean constant true --> +<!ELEMENT false EMPTY> <!-- Boolean constant false --> +<!ELEMENT real (#PCDATA)> <!-- Contents should represent a floating point number matching ("+" | "-")? d+ ("."d*)? ("E" ("+" | "-") d+)? where d is a digit 0-9. --> +<!ELEMENT integer (#PCDATA)> <!-- Contents should represent a (possibly signed) integer number in base 10 -->
src/main/java/com/dd/plist/XMLPropertyListParser.java+54 −47 modified@@ -32,6 +32,7 @@ import javax.xml.parsers.ParserConfigurationException; import java.io.ByteArrayInputStream; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.text.ParseException; @@ -44,24 +45,25 @@ * @author Daniel Dreibrodt */ public class XMLPropertyListParser { - - private static DocumentBuilderFactory docBuilderFactory = null; - - /** - * Instantiation is prohibited by outside classes. - */ - protected XMLPropertyListParser() { - /** empty **/ - } - - /** - * Initialize the document builder factory so that it can be reused and does not need to - * be reinitialized for each parse action. - */ - private static synchronized void initDocBuilderFactory() { - docBuilderFactory = DocumentBuilderFactory.newInstance(); - docBuilderFactory.setIgnoringComments(true); - docBuilderFactory.setCoalescing(true); + private static final DocumentBuilderFactory FACTORY = DocumentBuilderFactory.newInstance(); + static { + try { + FACTORY.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + Float v1_7 = new Float("1.7"); + Float javaVersion = new Float(System.getProperty("java.specification.version")); + if (javaVersion.compareTo(v1_7) >= 0) { + FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false); + FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + } + FACTORY.setXIncludeAware(false); + FACTORY.setExpandEntityReferences(false); + FACTORY.setNamespaceAware(false); + FACTORY.setIgnoringComments(true); + FACTORY.setCoalescing(true); + FACTORY.setValidating(false); + } catch (ParserConfigurationException e) { + throw new RuntimeException(e); + } } /** @@ -72,22 +74,10 @@ private static synchronized void initDocBuilderFactory() { * @throws javax.xml.parsers.ParserConfigurationException If a document builder for parsing a XML property list * could not be created. This should not occur. */ - private static synchronized DocumentBuilder getDocBuilder() throws ParserConfigurationException { - if (docBuilderFactory == null) - initDocBuilderFactory(); - DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); - docBuilder.setEntityResolver(new EntityResolver() { - public InputSource resolveEntity(String publicId, String systemId) { - if ("-//Apple Computer//DTD PLIST 1.0//EN".equals(publicId) || // older publicId - "-//Apple//DTD PLIST 1.0//EN".equals(publicId)) { // newer publicId - // return a dummy, zero length DTD so we don't have to fetch - // it from the network. - return new InputSource(new ByteArrayInputStream(new byte[0])); - } - return null; - } - }); - return docBuilder; + public static synchronized DocumentBuilder getDocBuilder() throws ParserConfigurationException { + DocumentBuilder builder = FACTORY.newDocumentBuilder(); + builder.setEntityResolver(new PlistDTDResolver()); + return builder; } /** @@ -103,12 +93,10 @@ public InputSource resolveEntity(String publicId, String systemId) { * @throws com.dd.plist.PropertyListFormatException If the given property list has an invalid format. * @throws java.text.ParseException If a date string could not be parsed. */ - public static NSObject parse(File f) throws ParserConfigurationException, IOException, SAXException, PropertyListFormatException, ParseException { - DocumentBuilder docBuilder = getDocBuilder(); - - Document doc = docBuilder.parse(f); + public static NSObject parse(File f) + throws ParserConfigurationException, IOException, SAXException, PropertyListFormatException, ParseException { - return parse(doc); + return parse(getDocBuilder().parse(new FileInputStream(f))); } /** @@ -123,9 +111,10 @@ public static NSObject parse(File f) throws ParserConfigurationException, IOExce * @throws com.dd.plist.PropertyListFormatException If the given property list has an invalid format. * @throws java.text.ParseException If a date string could not be parsed. */ - public static NSObject parse(final byte[] bytes) throws ParserConfigurationException, ParseException, SAXException, PropertyListFormatException, IOException { - ByteArrayInputStream bis = new ByteArrayInputStream(bytes); - return parse(bis); + public static NSObject parse(final byte[] bytes) + throws ParserConfigurationException, ParseException, SAXException, PropertyListFormatException, IOException { + + return parse(new ByteArrayInputStream(bytes)); } /** @@ -141,12 +130,10 @@ public static NSObject parse(final byte[] bytes) throws ParserConfigurationExcep * @throws com.dd.plist.PropertyListFormatException If the given property list has an invalid format. * @throws java.text.ParseException If a date string could not be parsed. */ - public static NSObject parse(InputStream is) throws ParserConfigurationException, IOException, SAXException, PropertyListFormatException, ParseException { - DocumentBuilder docBuilder = getDocBuilder(); - - Document doc = docBuilder.parse(is); + public static NSObject parse(InputStream is) + throws ParserConfigurationException, IOException, SAXException, PropertyListFormatException, ParseException { - return parse(doc); + return parse(getDocBuilder().parse(is)); } /** @@ -290,4 +277,24 @@ private static String getNodeTextContents(Node n) { } } } + + /** + * Resolves only the Apple PLIST DTD. + */ + static class PlistDTDResolver implements EntityResolver { + private static final String PLIST_SYSTEMID_1 = "-//Apple Computer//DTD PLIST 1.0//EN"; + private static final String PLIST_SYSTEMID_2 = "-//Apple//DTD PLIST 1.0//EN"; + + PlistDTDResolver() { + } + + // Implement EntityResolver + + public InputSource resolveEntity(String publicId, String systemId) { + if (PLIST_SYSTEMID_1.equals(publicId) || PLIST_SYSTEMID_2.equals(publicId)) { + return new InputSource(XMLPropertyListParser.class.getResourceAsStream("PropertyList-1.0.dtd")); + } + return null; + } + } }
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
7- github.com/3breadt/dd-plist/commit/8c954e8d9f6f6863729e50105a8abf3f87fff74cghsapatchWEB
- github.com/3breadt/dd-plist/releases/tag/dd-plist-1.18ghsapatchWEB
- github.com/advisories/GHSA-4jx2-hvqw-93j9ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2016-15026ghsaADVISORY
- github.com/3breadt/dd-plist/pull/26ghsaissue-trackingWEB
- vuldb.comghsasignaturepermissions-requiredWEB
- vuldb.comghsavdb-entrytechnical-descriptionWEB
News mentions
0No linked articles in our index yet.