Summary
com.koushikdutta.async.parser.DocumentParser and the response side of com.koushikdutta.async.http.body.DocumentBody parse HTTP response bodies as XML using a DocumentBuilderFactory with no XML External Entity (XXE) hardening. Because this parser is the default `AsyncParser` returned for `text/xml` responses, any client app fetching XML from an untrusted (or compromised) server is exposed to XXE — file disclosure, SSRF, billion-laughs DoS.
Location
`AndroidAsync/src/com/koushikdutta/async/parser/DocumentParser.java:23`
```java
public class DocumentParser implements AsyncParser {
@OverRide
public Future parse(DataEmitter emitter) {
return new ByteBufferListParser().parse(emitter)
.thenConvert(from -> DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteBufferListInputStream(from)));
}
...
@OverRide public String getMime() { return "text/xml"; }
}
```
No hardening is applied to the `DocumentBuilderFactory`:
- No `setFeature("http://apache.org/xml/features/disallow-doctype-decl\", true)`
- No `setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true)`
- No disabling of external general/parameter entities or external DTD loading
- `setExpandEntityReferences` left at default (true)
Impact
An Android (or JVM) application using AndroidAsync to fetch XML over HTTP:
```java
AsyncHttpClient.getDefaultInstance().executeDocument(new AsyncHttpGet(url), callback);
```
…can be served a malicious payload by any HTTP origin it talks to:
```xml
]>
&xxe;
```
On Android, the result of resolving such an entity is typically reflected back into the app via the parsed `Document` and may end up logged, displayed, or proxied. On the JVM the same primitive enables SSRF and file disclosure against the app's local filesystem.
Suggested fix
Apply the OWASP XXE Prevention Cheat Sheet hardening at factory construction. Each `setFeature` should be try/catched and tolerated if the underlying JAXP provider doesn't support it (so the library remains pluggable):
```java
private static DocumentBuilderFactory hardenedFactory() {
DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
try { f.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); } catch (ParserConfigurationException ignored) {}
try { f.setFeature("http://apache.org/xml/features/disallow-doctype-decl\", true); } catch (ParserConfigurationException ignored) {}
try { f.setFeature("http://xml.org/sax/features/external-general-entities\", false); } catch (ParserConfigurationException ignored) {}
try { f.setFeature("http://xml.org/sax/features/external-parameter-entities\", false); } catch (ParserConfigurationException ignored) {}
try { f.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd\", false); } catch (ParserConfigurationException ignored) {}
f.setXIncludeAware(false);
f.setExpandEntityReferences(false);
return f;
}
```
If applications need to accept DOCTYPEs deliberately, expose a builder option rather than defaulting to permissive parsing.
How found
SAST sweep over the top-100 starred Java repos on GitHub.
References
- CWE-611: Improper Restriction of XML External Entity Reference
- OWASP XXE Prevention Cheat Sheet — Java DocumentBuilderFactory section
Summary
com.koushikdutta.async.parser.DocumentParserand the response side ofcom.koushikdutta.async.http.body.DocumentBodyparse HTTP response bodies as XML using aDocumentBuilderFactorywith no XML External Entity (XXE) hardening. Because this parser is the default `AsyncParser` returned for `text/xml` responses, any client app fetching XML from an untrusted (or compromised) server is exposed to XXE — file disclosure, SSRF, billion-laughs DoS.Location
`AndroidAsync/src/com/koushikdutta/async/parser/DocumentParser.java:23`
```java
public class DocumentParser implements AsyncParser {
@OverRide
public Future parse(DataEmitter emitter) {
return new ByteBufferListParser().parse(emitter)
.thenConvert(from -> DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteBufferListInputStream(from)));
}
...
@OverRide public String getMime() { return "text/xml"; }
}
```
No hardening is applied to the `DocumentBuilderFactory`:
Impact
An Android (or JVM) application using AndroidAsync to fetch XML over HTTP:
```java
AsyncHttpClient.getDefaultInstance().executeDocument(new AsyncHttpGet(url), callback);
```
…can be served a malicious payload by any HTTP origin it talks to:
```xml
]>
&xxe;
```
On Android, the result of resolving such an entity is typically reflected back into the app via the parsed `Document` and may end up logged, displayed, or proxied. On the JVM the same primitive enables SSRF and file disclosure against the app's local filesystem.
Suggested fix
Apply the OWASP XXE Prevention Cheat Sheet hardening at factory construction. Each `setFeature` should be try/catched and tolerated if the underlying JAXP provider doesn't support it (so the library remains pluggable):
```java
private static DocumentBuilderFactory hardenedFactory() {
DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
try { f.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); } catch (ParserConfigurationException ignored) {}
try { f.setFeature("http://apache.org/xml/features/disallow-doctype-decl\", true); } catch (ParserConfigurationException ignored) {}
try { f.setFeature("http://xml.org/sax/features/external-general-entities\", false); } catch (ParserConfigurationException ignored) {}
try { f.setFeature("http://xml.org/sax/features/external-parameter-entities\", false); } catch (ParserConfigurationException ignored) {}
try { f.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd\", false); } catch (ParserConfigurationException ignored) {}
f.setXIncludeAware(false);
f.setExpandEntityReferences(false);
return f;
}
```
If applications need to accept DOCTYPEs deliberately, expose a builder option rather than defaulting to permissive parsing.
How found
SAST sweep over the top-100 starred Java repos on GitHub.
References