Skip to content

Commit

Permalink
Disable XML External Entities (#2607)
Browse files Browse the repository at this point in the history
Co-authored-by: Chris Hennick <hennickc@amazon.com>
  • Loading branch information
Pr0methean and Pr0methean committed Feb 12, 2024
1 parent 8706343 commit c20a913
Showing 1 changed file with 35 additions and 38 deletions.
73 changes: 35 additions & 38 deletions src/main/java/com/github/tomakehurst/wiremock/common/xml/Xml.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016-2022 Thomas Akehurst
* Copyright (C) 2016-2024 Thomas Akehurst
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -26,6 +26,7 @@
import java.io.StringWriter;
import java.security.AccessController;
import java.security.PrivilegedAction;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
Expand Down Expand Up @@ -112,6 +113,8 @@ private static TransformerFactory createTransformerFactory() {
transformerFactory = TransformerFactory.newInstance();
}
transformerFactory.setAttribute("indent-number", 2);
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
return transformerFactory;
}

Expand Down Expand Up @@ -143,7 +146,7 @@ public static String toStringValue(Node node) {
private static String render(Node node) {
try {
StringWriter sw = new StringWriter();
Transformer transformer = TransformerFactory.newInstance().newTransformer();
Transformer transformer = createTransformerFactory().newTransformer();
transformer.setOutputProperty(OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(INDENT, "yes");
transformer.transform(new DOMSource(node), new StreamResult(sw));
Expand Down Expand Up @@ -177,43 +180,37 @@ public static DocumentBuilderFactory newDocumentBuilderFactory() {
private static class SkipResolvingEntitiesDocumentBuilderFactory extends DocumentBuilderFactory {

private static final ThreadLocal<DocumentBuilderFactory> DBF_CACHE =
new ThreadLocal<DocumentBuilderFactory>() {
@Override
protected DocumentBuilderFactory initialValue() {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://xml.org/sax/features/validation", false);
dbf.setFeature(
"http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
dbf.setFeature(
"http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
return dbf;
} catch (ParserConfigurationException e) {
return throwUnchecked(e, DocumentBuilderFactory.class);
}
}
};
ThreadLocal.withInitial(
() -> {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://xml.org/sax/features/validation", false);
dbf.setFeature(
"http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
dbf.setFeature(
"http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
dbf.setXIncludeAware(false);
dbf.setExpandEntityReferences(false);
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
return dbf;
} catch (ParserConfigurationException e) {
return throwUnchecked(e, DocumentBuilderFactory.class);
}
});
private static final ThreadLocal<DocumentBuilder> DB_CACHE =
new ThreadLocal<DocumentBuilder>() {
@Override
protected DocumentBuilder initialValue() {
try {
DocumentBuilder documentBuilder = DBF_CACHE.get().newDocumentBuilder();
documentBuilder.setErrorHandler(new SilentErrorHandler());
return documentBuilder;
} catch (ParserConfigurationException e) {
return throwUnchecked(e, DocumentBuilder.class);
}
}

@Override
public DocumentBuilder get() {
DocumentBuilder documentBuilder = super.get();
documentBuilder.setEntityResolver(new ResolveToEmptyString());
documentBuilder.setErrorHandler(null);
return documentBuilder;
}
};
ThreadLocal.withInitial(
() -> {
try {
DocumentBuilder documentBuilder = DBF_CACHE.get().newDocumentBuilder();
documentBuilder.setEntityResolver(new ResolveToEmptyString());
documentBuilder.setErrorHandler(new SilentErrorHandler());
return documentBuilder;
} catch (ParserConfigurationException e) {
return throwUnchecked(e, DocumentBuilder.class);
}
});

@Override
public DocumentBuilder newDocumentBuilder() throws ParserConfigurationException {
Expand Down

0 comments on commit c20a913

Please sign in to comment.