Skip to content

Commit dd47bc0

Browse files
committed
fix(core): correct schema validation for hints and grok documents when used with schema locations
Signed-off-by: Chad Wilson <29788154+chadlwilson@users.noreply.github.com>
1 parent bb16245 commit dd47bc0

25 files changed

+529
-193
lines changed

core/src/main/java/org/owasp/dependencycheck/Engine.java

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -140,14 +140,6 @@ public class Engine implements FileFilter, AutoCloseable {
140140
* A reference to the database.
141141
*/
142142
private CveDB database = null;
143-
/**
144-
* Used to store the value of
145-
* System.getProperty("javax.xml.accessExternalSchema") - ODC may change the
146-
* value of this system property at runtime. We store the value to reset the
147-
* property to its original value.
148-
*/
149-
private final String accessExternalSchema;
150-
151143
/**
152144
* Creates a new {@link Mode#STANDALONE} Engine.
153145
*
@@ -188,8 +180,6 @@ public Engine(@NotNull final ClassLoader serviceClassLoader, @NotNull final Mode
188180
this.settings = settings;
189181
this.serviceClassLoader = serviceClassLoader;
190182
this.mode = mode;
191-
this.accessExternalSchema = System.getProperty("javax.xml.accessExternalSchema");
192-
193183
initializeEngine();
194184
}
195185

@@ -215,11 +205,6 @@ public void close() {
215205
database = null;
216206
}
217207
}
218-
if (accessExternalSchema != null) {
219-
System.setProperty("javax.xml.accessExternalSchema", accessExternalSchema);
220-
} else {
221-
System.clearProperty("javax.xml.accessExternalSchema");
222-
}
223208
JCS.shutdown();
224209
}
225210

core/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -506,9 +506,8 @@ private void ensureParentDirectoryExists(File file) throws ReportException {
506506
* Reformats the given XML file.
507507
*
508508
* @param path the path to the XML file to be reformatted
509-
* @throws ReportException thrown if the given JSON file is malformed
510509
*/
511-
private void pretifyXml(String path) throws ReportException {
510+
private void pretifyXml(String path) {
512511
final String outputPath = path + ".pretty";
513512
final File in = new File(path);
514513
final File out = new File(outputPath);
@@ -520,10 +519,7 @@ private void pretifyXml(String path) throws ReportException {
520519
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
521520
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
522521

523-
final SAXSource saxs = new SAXSource(new InputSource(path));
524-
final XMLReader saxReader = XmlUtils.buildSecureSaxParser().getXMLReader();
525-
526-
saxs.setXMLReader(saxReader);
522+
final SAXSource saxs = new SAXSource(XmlUtils.buildSecureXmlReader(), new InputSource(path));
527523
transformer.transform(saxs, new StreamResult(new OutputStreamWriter(os, StandardCharsets.UTF_8)));
528524
} catch (ParserConfigurationException | TransformerConfigurationException ex) {
529525
LOGGER.debug("Configuration exception when pretty printing", ex);

core/src/main/java/org/owasp/dependencycheck/xml/assembly/GrokParser.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,8 @@
2727
import java.nio.charset.StandardCharsets;
2828
import javax.annotation.concurrent.ThreadSafe;
2929
import javax.xml.parsers.ParserConfigurationException;
30-
import javax.xml.parsers.SAXParser;
3130

32-
import org.owasp.dependencycheck.utils.FileUtils;
31+
import org.owasp.dependencycheck.utils.AutoCloseableInputSource;
3332
import org.owasp.dependencycheck.utils.XmlUtils;
3433

3534
import org.slf4j.Logger;
@@ -38,6 +37,8 @@
3837
import org.xml.sax.SAXException;
3938
import org.xml.sax.XMLReader;
4039

40+
import static org.owasp.dependencycheck.utils.AutoCloseableInputSource.fromResource;
41+
4142
/**
4243
* A simple validating parser for XML Grok Assembly XML files.
4344
*
@@ -80,10 +81,9 @@ public AssemblyData parse(File file) throws GrokParseException {
8081
* @throws GrokParseException thrown if the XML cannot be parsed
8182
*/
8283
public AssemblyData parse(InputStream inputStream) throws GrokParseException {
83-
try (InputStream schema = FileUtils.getResourceAsStream(GROK_SCHEMA)) {
84+
try (AutoCloseableInputSource schema = fromResource(GROK_SCHEMA)) {
8485
final GrokHandler handler = new GrokHandler();
85-
final SAXParser saxParser = XmlUtils.buildSecureSaxParser(schema);
86-
final XMLReader xmlReader = saxParser.getXMLReader();
86+
final XMLReader xmlReader = XmlUtils.buildSecureValidatingXmlReader(schema);
8787
xmlReader.setErrorHandler(new GrokErrorHandler());
8888
xmlReader.setContentHandler(handler);
8989
try (Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {

core/src/main/java/org/owasp/dependencycheck/xml/hints/HintParser.java

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@
2828
import java.util.List;
2929
import javax.annotation.concurrent.NotThreadSafe;
3030
import javax.xml.parsers.ParserConfigurationException;
31-
import javax.xml.parsers.SAXParser;
31+
3232
import org.apache.commons.io.ByteOrderMark;
3333
import org.apache.commons.io.input.BOMInputStream;
3434

35-
import org.owasp.dependencycheck.utils.FileUtils;
35+
import org.owasp.dependencycheck.utils.AutoCloseableInputSource;
3636
import org.owasp.dependencycheck.utils.XmlUtils;
3737

3838
import org.slf4j.Logger;
@@ -41,6 +41,8 @@
4141
import org.xml.sax.SAXException;
4242
import org.xml.sax.XMLReader;
4343

44+
import static org.owasp.dependencycheck.utils.AutoCloseableInputSource.fromResource;
45+
4446
/**
4547
* A simple validating parser for XML Hint Rules.
4648
*
@@ -53,21 +55,6 @@ public class HintParser {
5355
* The logger.
5456
*/
5557
private static final Logger LOGGER = LoggerFactory.getLogger(HintParser.class);
56-
/**
57-
* JAXP Schema Language. Source:
58-
* http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html
59-
*/
60-
public static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
61-
/**
62-
* W3C XML Schema. Source:
63-
* http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html
64-
*/
65-
public static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
66-
/**
67-
* JAXP Schema Source. Source:
68-
* http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html
69-
*/
70-
public static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource";
7158

7259
/**
7360
* The schema for the hint XML files.
@@ -142,20 +129,18 @@ public void parseHints(File file) throws HintParseException {
142129
* @throws SAXException thrown if the XML cannot be parsed
143130
*/
144131
public void parseHints(InputStream inputStream) throws HintParseException, SAXException {
145-
try (
146-
InputStream schemaStream14 = FileUtils.getResourceAsStream(HINT_SCHEMA_1_4);
147-
InputStream schemaStream13 = FileUtils.getResourceAsStream(HINT_SCHEMA_1_3);
148-
InputStream schemaStream12 = FileUtils.getResourceAsStream(HINT_SCHEMA_1_2);
149-
InputStream schemaStream11 = FileUtils.getResourceAsStream(HINT_SCHEMA_1_1)) {
132+
try (AutoCloseableInputSource schemaStream14 = fromResource(HINT_SCHEMA_1_4);
133+
AutoCloseableInputSource schemaStream13 = fromResource(HINT_SCHEMA_1_3);
134+
AutoCloseableInputSource schemaStream12 = fromResource(HINT_SCHEMA_1_2);
135+
AutoCloseableInputSource schemaStream11 = fromResource(HINT_SCHEMA_1_1)) {
150136

151137
final BOMInputStream bomStream = BOMInputStream.builder().setInputStream(inputStream).get();
152138
final ByteOrderMark bom = bomStream.getBOM();
153139
final String defaultEncoding = StandardCharsets.UTF_8.name();
154140
final String charsetName = bom == null ? defaultEncoding : bom.getCharsetName();
155141

156142
final HintHandler handler = new HintHandler();
157-
final SAXParser saxParser = XmlUtils.buildSecureSaxParser(schemaStream14, schemaStream13, schemaStream12, schemaStream11);
158-
final XMLReader xmlReader = saxParser.getXMLReader();
143+
final XMLReader xmlReader = XmlUtils.buildSecureValidatingXmlReader(schemaStream14, schemaStream13, schemaStream12, schemaStream11);
159144
xmlReader.setErrorHandler(new HintErrorHandler());
160145
xmlReader.setContentHandler(handler);
161146
try (Reader reader = new InputStreamReader(bomStream, charsetName)) {

core/src/main/java/org/owasp/dependencycheck/xml/pom/PomParser.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,7 @@ public Model parseWithoutDocTypeCleanup(File file) throws PomParseException {
107107
public Model parse(InputStream inputStream) throws PomParseException {
108108
try {
109109
final PomHandler handler = new PomHandler();
110-
final SAXParser saxParser = XmlUtils.buildSecureSaxParser();
111-
final XMLReader xmlReader = saxParser.getXMLReader();
110+
final XMLReader xmlReader = XmlUtils.buildSecureXmlReader();
112111
xmlReader.setContentHandler(handler);
113112

114113
final BOMInputStream bomStream = BOMInputStream.builder()
@@ -138,8 +137,7 @@ public Model parse(InputStream inputStream) throws PomParseException {
138137
public Model parseWithoutDocTypeCleanup(InputStream inputStream) throws PomParseException {
139138
try {
140139
final PomHandler handler = new PomHandler();
141-
final SAXParser saxParser = XmlUtils.buildSecureSaxParser();
142-
final XMLReader xmlReader = saxParser.getXMLReader();
140+
final XMLReader xmlReader = XmlUtils.buildSecureXmlReader();
143141
xmlReader.setContentHandler(handler);
144142

145143
final BOMInputStream bomStream = BOMInputStream.builder().setInputStream(new XmlInputStream(inputStream)).get();

core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionParser.java

Lines changed: 10 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,21 @@
2828
import java.util.List;
2929
import javax.annotation.concurrent.ThreadSafe;
3030
import javax.xml.parsers.ParserConfigurationException;
31-
import javax.xml.parsers.SAXParser;
31+
3232
import org.apache.commons.io.ByteOrderMark;
3333
import org.apache.commons.io.input.BOMInputStream;
3434

35-
import org.owasp.dependencycheck.utils.FileUtils;
35+
import org.owasp.dependencycheck.utils.AutoCloseableInputSource;
3636
import org.owasp.dependencycheck.utils.XmlUtils;
3737

3838
import org.slf4j.Logger;
3939
import org.slf4j.LoggerFactory;
40-
import org.xml.sax.EntityResolver;
4140
import org.xml.sax.InputSource;
4241
import org.xml.sax.SAXException;
4342
import org.xml.sax.XMLReader;
4443

44+
import static org.owasp.dependencycheck.utils.AutoCloseableInputSource.fromResource;
45+
4546
/**
4647
* A simple validating parser for XML Suppression Rules.
4748
*
@@ -105,24 +106,21 @@ public List<SuppressionRule> parseSuppressionRules(File file) throws Suppression
105106
*/
106107
public List<SuppressionRule> parseSuppressionRules(InputStream inputStream)
107108
throws SuppressionParseException, SAXException {
108-
try (
109-
InputStream schemaStream14 = FileUtils.getResourceAsStream(SUPPRESSION_SCHEMA_1_4);
110-
InputStream schemaStream13 = FileUtils.getResourceAsStream(SUPPRESSION_SCHEMA_1_3);
111-
InputStream schemaStream12 = FileUtils.getResourceAsStream(SUPPRESSION_SCHEMA_1_2);
112-
InputStream schemaStream11 = FileUtils.getResourceAsStream(SUPPRESSION_SCHEMA_1_1);
113-
InputStream schemaStream10 = FileUtils.getResourceAsStream(SUPPRESSION_SCHEMA_1_0)) {
109+
try (AutoCloseableInputSource schemaStream14 = fromResource(SUPPRESSION_SCHEMA_1_4);
110+
AutoCloseableInputSource schemaStream13 = fromResource(SUPPRESSION_SCHEMA_1_3);
111+
AutoCloseableInputSource schemaStream12 = fromResource(SUPPRESSION_SCHEMA_1_2);
112+
AutoCloseableInputSource schemaStream11 = fromResource(SUPPRESSION_SCHEMA_1_1);
113+
AutoCloseableInputSource schemaStream10 = fromResource(SUPPRESSION_SCHEMA_1_0)) {
114114

115115
final BOMInputStream bomStream = BOMInputStream.builder().setInputStream(inputStream).get();
116116
final ByteOrderMark bom = bomStream.getBOM();
117117
final String defaultEncoding = StandardCharsets.UTF_8.name();
118118
final String charsetName = bom == null ? defaultEncoding : bom.getCharsetName();
119119

120120
final SuppressionHandler handler = new SuppressionHandler();
121-
final SAXParser saxParser = XmlUtils.buildSecureSaxParser(schemaStream14, schemaStream13, schemaStream12, schemaStream11, schemaStream10);
122-
final XMLReader xmlReader = saxParser.getXMLReader();
121+
final XMLReader xmlReader = XmlUtils.buildSecureValidatingXmlReader(schemaStream14, schemaStream13, schemaStream12, schemaStream11, schemaStream10);
123122
xmlReader.setErrorHandler(new SuppressionErrorHandler());
124123
xmlReader.setContentHandler(handler);
125-
xmlReader.setEntityResolver(new ClassloaderResolver());
126124
try (Reader reader = new InputStreamReader(bomStream, charsetName)) {
127125
final InputSource in = new InputSource(reader);
128126
xmlReader.parse(in);
@@ -141,24 +139,4 @@ public List<SuppressionRule> parseSuppressionRules(InputStream inputStream)
141139
}
142140
}
143141

144-
/**
145-
* Load HTTPS schema resources locally from the JAR files resources.
146-
*/
147-
private static class ClassloaderResolver implements EntityResolver {
148-
149-
@Override
150-
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
151-
152-
if (systemId != null && systemId.startsWith("https://jeremylong.github.io/DependencyCheck/")) {
153-
final String resource = "schema/" + systemId.substring(45);
154-
final InputStream in = SuppressionParser.class.getClassLoader().getResourceAsStream(resource);
155-
if (in != null) {
156-
final InputSource source = new InputSource(in);
157-
source.setSystemId(systemId);
158-
return source;
159-
}
160-
}
161-
return null;
162-
}
163-
}
164142
}

core/src/test/java/org/owasp/dependencycheck/xml/assembly/GrokHandlerTest.java

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@
1919

2020
import org.junit.jupiter.api.Test;
2121
import org.owasp.dependencycheck.BaseTest;
22+
import org.owasp.dependencycheck.utils.AutoCloseableInputSource;
2223
import org.owasp.dependencycheck.utils.XmlUtils;
2324
import org.xml.sax.InputSource;
2425
import org.xml.sax.XMLReader;
2526

26-
import javax.xml.parsers.SAXParser;
2727
import java.io.File;
2828
import java.io.FileInputStream;
2929
import java.io.InputStream;
@@ -32,6 +32,7 @@
3232
import java.nio.charset.StandardCharsets;
3333

3434
import static org.junit.jupiter.api.Assertions.assertEquals;
35+
import static org.owasp.dependencycheck.utils.AutoCloseableInputSource.fromResource;
3536

3637
/**
3738
*
@@ -47,24 +48,23 @@ class GrokHandlerTest extends BaseTest {
4748
@Test
4849
void testHandler() throws Exception {
4950
File file = BaseTest.getResourceAsFile(this, "assembly/sample-grok.xml");
50-
InputStream schemaStream = BaseTest.getResourceAsStream(this, "schema/grok-assembly.1.0.xsd");
5151

52-
GrokHandler handler = new GrokHandler();
53-
SAXParser saxParser = XmlUtils.buildSecureSaxParser(schemaStream);
54-
XMLReader xmlReader = saxParser.getXMLReader();
55-
xmlReader.setErrorHandler(new GrokErrorHandler());
56-
xmlReader.setContentHandler(handler);
52+
try (AutoCloseableInputSource schema = fromResource("schema/grok-assembly.1.0.xsd")) {
53+
GrokHandler handler = new GrokHandler();
54+
XMLReader xmlReader = XmlUtils.buildSecureValidatingXmlReader(schema);
55+
xmlReader.setErrorHandler(new GrokErrorHandler());
56+
xmlReader.setContentHandler(handler);
5757

58-
InputStream inputStream = new FileInputStream(file);
59-
Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
60-
InputSource in = new InputSource(reader);
58+
try (Reader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) {
59+
InputSource in = new InputSource(reader);
60+
xmlReader.parse(in);
61+
}
6162

62-
xmlReader.parse(in);
63-
64-
AssemblyData result = handler.getAssemblyData();
65-
assertEquals("OWASP Contributors", result.getCompanyName());
66-
assertEquals("GrokAssembly", result.getProductName());
67-
assertEquals("Inspects a .NET Assembly to determine Company, Product, and Version information", result.getComments());
68-
assertEquals(1, result.getNamespaces().size());
63+
AssemblyData result = handler.getAssemblyData();
64+
assertEquals("OWASP Contributors", result.getCompanyName());
65+
assertEquals("GrokAssembly", result.getProductName());
66+
assertEquals("Inspects a .NET Assembly to determine Company, Product, and Version information", result.getComments());
67+
assertEquals(1, result.getNamespaces().size());
68+
}
6969
}
7070
}

core/src/test/java/org/owasp/dependencycheck/xml/hints/HintHandlerTest.java

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@
1919

2020
import org.junit.jupiter.api.Test;
2121
import org.owasp.dependencycheck.BaseTest;
22+
import org.owasp.dependencycheck.utils.AutoCloseableInputSource;
23+
import org.owasp.dependencycheck.utils.XmlUtils;
2224
import org.xml.sax.InputSource;
2325
import org.xml.sax.SAXException;
2426
import org.xml.sax.XMLReader;
2527

2628
import javax.xml.parsers.ParserConfigurationException;
27-
import javax.xml.parsers.SAXParser;
28-
import javax.xml.parsers.SAXParserFactory;
2929
import java.io.File;
3030
import java.io.FileInputStream;
3131
import java.io.IOException;
@@ -36,6 +36,7 @@
3636
import java.util.List;
3737

3838
import static org.junit.jupiter.api.Assertions.assertEquals;
39+
import static org.owasp.dependencycheck.utils.AutoCloseableInputSource.fromResource;
3940

4041
/**
4142
*
@@ -46,26 +47,20 @@ class HintHandlerTest extends BaseTest {
4647
@Test
4748
void testHandler() throws ParserConfigurationException, SAXException, IOException {
4849
File file = BaseTest.getResourceAsFile(this, "hints.xml");
49-
File schema = BaseTest.getResourceAsFile(this, "schema/dependency-hint.1.1.xsd");
5050
HintHandler handler = new HintHandler();
5151

52-
SAXParserFactory factory = SAXParserFactory.newInstance();
53-
factory.setNamespaceAware(true);
54-
factory.setValidating(true);
55-
SAXParser saxParser = factory.newSAXParser();
56-
saxParser.setProperty(HintParser.JAXP_SCHEMA_LANGUAGE, HintParser.W3C_XML_SCHEMA);
57-
saxParser.setProperty(HintParser.JAXP_SCHEMA_SOURCE, schema);
58-
XMLReader xmlReader = saxParser.getXMLReader();
59-
xmlReader.setErrorHandler(new HintErrorHandler());
60-
xmlReader.setContentHandler(handler);
52+
try (AutoCloseableInputSource schemaResource = fromResource("schema/dependency-hint.1.4.xsd")) {
53+
XMLReader xmlReader = XmlUtils.buildSecureValidatingXmlReader(schemaResource);
54+
xmlReader.setErrorHandler(new HintErrorHandler());
55+
xmlReader.setContentHandler(handler);
6156

62-
InputStream inputStream = new FileInputStream(file);
63-
Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
64-
InputSource in = new InputSource(reader);
65-
xmlReader.parse(in);
66-
67-
List<HintRule> result = handler.getHintRules();
68-
assertEquals(2,result.size(),"two hint rules should have been loaded");
57+
try (Reader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) {
58+
InputSource in = new InputSource(reader);
59+
xmlReader.parse(in);
60+
}
61+
List<HintRule> result = handler.getHintRules();
62+
assertEquals(2, result.size(), "two hint rules should have been loaded");
63+
}
6964
}
7065

7166
}

0 commit comments

Comments
 (0)