Skip to content

Commit c20a913

Browse files
authored
Disable XML External Entities (#2607)
Co-authored-by: Chris Hennick <[email protected]>
1 parent 8706343 commit c20a913

1 file changed

Lines changed: 35 additions & 38 deletions

File tree

  • src/main/java/com/github/tomakehurst/wiremock/common/xml

src/main/java/com/github/tomakehurst/wiremock/common/xml/Xml.java

Lines changed: 35 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2016-2022 Thomas Akehurst
2+
* Copyright (C) 2016-2024 Thomas Akehurst
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@
2626
import java.io.StringWriter;
2727
import java.security.AccessController;
2828
import java.security.PrivilegedAction;
29+
import javax.xml.XMLConstants;
2930
import javax.xml.parsers.DocumentBuilder;
3031
import javax.xml.parsers.DocumentBuilderFactory;
3132
import javax.xml.parsers.ParserConfigurationException;
@@ -112,6 +113,8 @@ private static TransformerFactory createTransformerFactory() {
112113
transformerFactory = TransformerFactory.newInstance();
113114
}
114115
transformerFactory.setAttribute("indent-number", 2);
116+
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
117+
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
115118
return transformerFactory;
116119
}
117120

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

179182
private static final ThreadLocal<DocumentBuilderFactory> DBF_CACHE =
180-
new ThreadLocal<DocumentBuilderFactory>() {
181-
@Override
182-
protected DocumentBuilderFactory initialValue() {
183-
try {
184-
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
185-
dbf.setFeature("http://xml.org/sax/features/validation", false);
186-
dbf.setFeature(
187-
"http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
188-
dbf.setFeature(
189-
"http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
190-
return dbf;
191-
} catch (ParserConfigurationException e) {
192-
return throwUnchecked(e, DocumentBuilderFactory.class);
193-
}
194-
}
195-
};
183+
ThreadLocal.withInitial(
184+
() -> {
185+
try {
186+
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
187+
dbf.setFeature("http://xml.org/sax/features/validation", false);
188+
dbf.setFeature(
189+
"http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
190+
dbf.setFeature(
191+
"http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
192+
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
193+
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
194+
dbf.setXIncludeAware(false);
195+
dbf.setExpandEntityReferences(false);
196+
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
197+
return dbf;
198+
} catch (ParserConfigurationException e) {
199+
return throwUnchecked(e, DocumentBuilderFactory.class);
200+
}
201+
});
196202
private static final ThreadLocal<DocumentBuilder> DB_CACHE =
197-
new ThreadLocal<DocumentBuilder>() {
198-
@Override
199-
protected DocumentBuilder initialValue() {
200-
try {
201-
DocumentBuilder documentBuilder = DBF_CACHE.get().newDocumentBuilder();
202-
documentBuilder.setErrorHandler(new SilentErrorHandler());
203-
return documentBuilder;
204-
} catch (ParserConfigurationException e) {
205-
return throwUnchecked(e, DocumentBuilder.class);
206-
}
207-
}
208-
209-
@Override
210-
public DocumentBuilder get() {
211-
DocumentBuilder documentBuilder = super.get();
212-
documentBuilder.setEntityResolver(new ResolveToEmptyString());
213-
documentBuilder.setErrorHandler(null);
214-
return documentBuilder;
215-
}
216-
};
203+
ThreadLocal.withInitial(
204+
() -> {
205+
try {
206+
DocumentBuilder documentBuilder = DBF_CACHE.get().newDocumentBuilder();
207+
documentBuilder.setEntityResolver(new ResolveToEmptyString());
208+
documentBuilder.setErrorHandler(new SilentErrorHandler());
209+
return documentBuilder;
210+
} catch (ParserConfigurationException e) {
211+
return throwUnchecked(e, DocumentBuilder.class);
212+
}
213+
});
217214

218215
@Override
219216
public DocumentBuilder newDocumentBuilder() throws ParserConfigurationException {

0 commit comments

Comments
 (0)