|
1 | 1 | /*
|
2 |
| - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. |
| 2 | + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. |
3 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
4 | 4 | *
|
5 | 5 | * The Universal Permissive License (UPL), Version 1.0
|
|
67 | 67 | import java.util.logging.Level;
|
68 | 68 | import java.util.stream.Collectors;
|
69 | 69 |
|
| 70 | +import javax.xml.XMLConstants; |
| 71 | +import javax.xml.parsers.DocumentBuilder; |
70 | 72 | import javax.xml.parsers.DocumentBuilderFactory;
|
71 | 73 | import javax.xml.parsers.ParserConfigurationException;
|
72 | 74 |
|
@@ -108,8 +110,7 @@ public void downloadDependencies(String repoUrl, String groupId, String artifact
|
108 | 110 | boolean mvnCentralFallback = !repoUrl.startsWith(DEFAULT_MAVEN_REPO);
|
109 | 111 | byte[] bytes = downloadMavenFile(repoUrl, artifactName, mvnCentralFallback);
|
110 | 112 |
|
111 |
| - var factory = DocumentBuilderFactory.newInstance(); |
112 |
| - var builder = factory.newDocumentBuilder(); |
| 113 | + var builder = createSecurePOMParser(); |
113 | 114 | var document = builder.parse(new ByteArrayInputStream(bytes));
|
114 | 115 |
|
115 | 116 | // We care only about a very small subset of the POM, and accept even malformed POMs if the
|
@@ -187,6 +188,36 @@ public void downloadDependencies(String repoUrl, String groupId, String artifact
|
187 | 188 | }
|
188 | 189 | }
|
189 | 190 |
|
| 191 | + /** |
| 192 | + * Creates a {@link DocumentBuilder} that is crafted to be safe while still not disallowing |
| 193 | + * valid Maven POM files. |
| 194 | + */ |
| 195 | + private static DocumentBuilder createSecurePOMParser() throws ParserConfigurationException { |
| 196 | + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); |
| 197 | + |
| 198 | + /* |
| 199 | + * Disallow potentially dangerous external entity resolutions. Compatible with Maven because |
| 200 | + * POM files do not need external entities. |
| 201 | + */ |
| 202 | + factory.setFeature("http://xml.org/sax/features/external-general-entities", false); |
| 203 | + factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); |
| 204 | + factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); |
| 205 | + |
| 206 | + /* |
| 207 | + * Injecting external XMLs is not allowed by the Maven POM schema, but we can still include |
| 208 | + * the rule to err on the side of safety. |
| 209 | + */ |
| 210 | + factory.setXIncludeAware(false); |
| 211 | + |
| 212 | + /* |
| 213 | + * We don't expect legitimate POMs to be huge, so use recommended defaults for max |
| 214 | + * processing limits. |
| 215 | + */ |
| 216 | + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); |
| 217 | + |
| 218 | + return factory.newDocumentBuilder(); |
| 219 | + } |
| 220 | + |
190 | 221 | private static byte[] downloadMavenFile(String repoUrl, String artefactName, boolean fallback) throws IOException, URISyntaxException {
|
191 | 222 | String url = repoUrl + artefactName;
|
192 | 223 | try {
|
|
0 commit comments