Skip to content

Commit e49f0c9

Browse files
committed
Add XMLFilterParseStringTest.
1 parent d8f2da3 commit e49f0c9

1 file changed

Lines changed: 67 additions & 0 deletions

File tree

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* https://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.commons.xml;
19+
20+
import static org.junit.jupiter.api.Assertions.assertFalse;
21+
22+
import java.io.StringReader;
23+
import java.nio.charset.StandardCharsets;
24+
import java.nio.file.Files;
25+
import java.nio.file.Path;
26+
27+
import javax.xml.transform.Templates;
28+
import javax.xml.transform.sax.SAXTransformerFactory;
29+
import javax.xml.transform.stream.StreamSource;
30+
31+
import org.junit.jupiter.api.Tag;
32+
import org.junit.jupiter.api.Test;
33+
import org.junit.jupiter.api.io.TempDir;
34+
import org.xml.sax.XMLFilter;
35+
36+
@Tag("trax")
37+
class XMLFilterParseStringTest {
38+
39+
private static final String IDENTITY_XSLT =
40+
// @formatter:off
41+
"<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">" +
42+
"<xsl:template match=\"/\"><xsl:copy-of select=\".\"/></xsl:template>" +
43+
"</xsl:stylesheet>";
44+
// @formatter:on
45+
46+
private static String entityPayload() {
47+
// @formatter:off
48+
return "<?xml version=\"1.0\"?>\n" +
49+
"<!DOCTYPE root [<!ENTITY xxe SYSTEM \"" + AttackTestSupport.resourceUrl("referenced.txt") + "\">]>\n" +
50+
"<root>&xxe;</root>";
51+
// @formatter:on
52+
}
53+
54+
@Test
55+
void hardenedFilterParseStringDoesNotLeakExternalEntity(@TempDir final Path tmpDir) throws Exception {
56+
final SAXTransformerFactory factory = (SAXTransformerFactory) XmlFactories.newTransformerFactory();
57+
final Templates templates = factory.newTemplates(new StreamSource(new StringReader(IDENTITY_XSLT)));
58+
final XMLFilter filter = factory.newXMLFilter(templates);
59+
final Path tmp = Files.createTempFile(tmpDir, "xmlfilter", ".xml");
60+
Files.write(tmp, entityPayload().getBytes(StandardCharsets.UTF_8));
61+
final StringBuilder out = new StringBuilder();
62+
filter.setContentHandler(AttackTestSupport.capturingHandler(out));
63+
// public API – XMLFilter.parse(String) – the path that ends in XMLFilterImpl.parse(String)
64+
filter.parse(tmp.toUri().toString());
65+
assertFalse(out.toString().contains(AttackTestSupport.LEAKED_MARKER), "external entity leaked through XMLFilter.parse(String)");
66+
}
67+
}

0 commit comments

Comments
 (0)