Skip to content

Commit f204f49

Browse files
committed
Document XML parser usage against security false positives
Prior to this commit, our XML parser usage would be already haredened against XXE (XML External Entities) attacks. Still, we recently received several invalid security reports claiming that our setup should be hardened. This commit documents a few usages of XML parsers to add some more context and hopefully prevent future invalid reports. Closes gh-33713
1 parent 166714c commit f204f49

File tree

6 files changed

+20
-2
lines changed

6 files changed

+20
-2
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/xml/DefaultDocumentLoader.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
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.
@@ -88,6 +88,9 @@ public Document loadDocument(InputSource inputSource, EntityResolver entityResol
8888
protected DocumentBuilderFactory createDocumentBuilderFactory(int validationMode, boolean namespaceAware)
8989
throws ParserConfigurationException {
9090

91+
// This document loader is used for loading application configuration files.
92+
// As a result, attackers would need complete write access to application configuration
93+
// to leverage XXE attacks. This does not qualify as privilege escalation.
9194
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
9295
factory.setNamespaceAware(namespaceAware);
9396

spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/PersistenceUnitReader.java

+3
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ public SpringPersistenceUnitInfo[] readPersistenceUnitInfos(String[] persistence
157157
Document buildDocument(ErrorHandler handler, InputStream stream)
158158
throws ParserConfigurationException, SAXException, IOException {
159159

160+
// This document loader is used for loading application configuration files.
161+
// As a result, attackers would need complete write access to application configuration
162+
// to leverage XXE attacks. This does not qualify as privilege escalation.
160163
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
161164
dbf.setNamespaceAware(true);
162165
DocumentBuilder parser = dbf.newDocumentBuilder();

spring-oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java

+5
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,9 @@ private Schema loadSchema(Resource[] resources, String schemaLanguage) throws IO
603603
Assert.hasLength(schemaLanguage, "No schema language provided");
604604
Source[] schemaSources = new Source[resources.length];
605605

606+
// This parser is used to read the schema resources provided by the application.
607+
// The parser used for reading the source is protected against XXE attacks.
608+
// See "processSource(Source source)".
606609
SAXParserFactory saxParserFactory = this.schemaParserFactory;
607610
if (saxParserFactory == null) {
608611
saxParserFactory = SAXParserFactory.newInstance();
@@ -907,6 +910,8 @@ else if (streamSource.getReader() != null) {
907910
}
908911

909912
try {
913+
// By default, Spring will prevent the processing of external entities.
914+
// This is a mitigation against XXE attacks.
910915
if (xmlReader == null) {
911916
SAXParserFactory saxParserFactory = this.sourceParserFactory;
912917
if (saxParserFactory == null) {

spring-web/src/main/java/org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverter.java

+2
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ protected Source processSource(Source source) {
164164
if (source instanceof StreamSource streamSource) {
165165
InputSource inputSource = new InputSource(streamSource.getInputStream());
166166
try {
167+
// By default, Spring will prevent the processing of external entities.
168+
// This is a mitigation against XXE attacks.
167169
SAXParserFactory saxParserFactory = this.sourceParserFactory;
168170
if (saxParserFactory == null) {
169171
saxParserFactory = SAXParserFactory.newInstance();

spring-web/src/main/java/org/springframework/http/converter/xml/SourceHttpMessageConverter.java

+2
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,8 @@ else if (StreamSource.class == clazz || Source.class == clazz) {
177177

178178
private DOMSource readDOMSource(InputStream body, HttpInputMessage inputMessage) throws IOException {
179179
try {
180+
// By default, Spring will prevent the processing of external entities.
181+
// This is a mitigation against XXE attacks.
180182
DocumentBuilderFactory builderFactory = this.documentBuilderFactory;
181183
if (builderFactory == null) {
182184
builderFactory = DocumentBuilderFactory.newInstance();

spring-webmvc/src/main/java/org/springframework/web/servlet/view/xslt/XsltView.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
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.
@@ -215,6 +215,9 @@ protected TransformerFactory newTransformerFactory(
215215
}
216216
}
217217
else {
218+
// This transformer is used for local XSLT views only.
219+
// As a result, attackers would need complete write access to application configuration
220+
// to leverage XXE attacks. This does not qualify as privilege escalation.
218221
return TransformerFactory.newInstance();
219222
}
220223
}

0 commit comments

Comments
 (0)