Copilot commented on code in PR #16310:
URL: https://github.com/apache/grails-core/pull/16310#discussion_r3928957052


##########
grails-testing-support-http-client/src/main/groovy/org/apache/grails/testing/http/client/utils/XmlUtils.groovy:
##########
@@ -224,6 +223,7 @@ class XmlUtils {
         def saxParserFactory = FactorySupport.createSaxParserFactory().tap {
             it.namespaceAware = true
             it.validating = false
+            it.XIncludeAware = false
         }

Review Comment:
   Setting `XIncludeAware` can throw `UnsupportedOperationException` on SAX 
parser implementations that don't support XInclude, which would currently fail 
XML parsing even though the rest of the security features are handled 
defensively. Consider wrapping `XIncludeAware = false` in a try/catch like the 
feature toggles so unsupported parsers still work (with XInclude simply left at 
the default).



##########
grails-gradle/model/src/main/groovy/org/grails/io/support/SpringIOUtils.java:
##########
@@ -423,19 +423,20 @@ private static SAXParserFactory createParserFactory() 
throws ParserConfiguration
             saxParserFactory = FactorySupport.createSaxParserFactory();
             saxParserFactory.setNamespaceAware(true);
             saxParserFactory.setValidating(false);
+            saxParserFactory.setXIncludeAware(false);

Review Comment:
   `SAXParserFactory#setXIncludeAware(false)` can throw 
`UnsupportedOperationException` if XInclude isn't supported by the underlying 
parser implementation. Since `createParserFactory()` currently doesn't guard 
this call, XML parsing can fail entirely on such implementations; wrapping this 
in a try/catch (similar to the feature setters) preserves compatibility while 
still disabling XInclude where supported.



##########
grails-gradle/model/src/test/groovy/org/grails/io/support/SpringIOUtilsSpec.groovy:
##########
@@ -0,0 +1,44 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    https://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.grails.io.support
+
+import org.xml.sax.SAXParseException
+import spock.lang.Specification
+
+class SpringIOUtilsSpec extends Specification {
+
+    void 'createXmlSlurper parses documents without a doctype'() {
+        when:
+        def xml = 
SpringIOUtils.createXmlSlurper().parseText('<root><child>ok</child></root>')
+
+        then:
+        xml.child.text() == 'ok'
+    }
+
+    void 'createXmlSlurper rejects doctype declarations with external 
entities'() {
+        when:
+        SpringIOUtils.createXmlSlurper().parseText('''<!DOCTYPE root [
+<!ENTITY ext SYSTEM "file:///not-resolved">
+]>
+<root>&ext;</root>''')
+
+        then:
+        thrown(SAXParseException)
+    }

Review Comment:
   The new test only exercises a DOCTYPE that defines an external entity; 
depending on parser behavior, that can fail even if DOCTYPE declarations are 
still allowed. Adding an internal-subset DOCTYPE case helps ensure the intended 
behavior (“reject DOCTYPE declarations”) is actually enforced by 
`createXmlSlurper()`.



##########
grails-testing-support-http-client/src/test/groovy/org/apache/grails/testing/http/client/utils/XmlUtilsSpec.groovy:
##########
@@ -278,37 +276,15 @@ class XmlUtilsSpec extends Specification {
         xml == "<?xml version='1.1' encoding='UTF-16'?><product />"
     }
 
-    void 'newXmlSlurper allows inline doctype declarations with internal 
entities'() {
+    void 'newXmlSlurper rejects doctype declarations with external entities'() 
{
         when:
         def parsed = XmlUtils.newXmlSlurper().parseText('''<!DOCTYPE root [
-<!ENTITY msg "safe">
-]>
-<root>&msg;</root>''')
+ <!ENTITY ext SYSTEM "file:///not-resolved">
+ ]>

Review Comment:
   The updated DOCTYPE test only uses an external entity, which can still throw 
for multiple reasons even if DOCTYPE declarations are not actually rejected 
(e.g., unresolved entity handling). Adding a second test case with an internal 
entity and asserting a parse failure more directly validates the intended 
behavior change (“reject DOCTYPE declarations”) and guards against regressions.



##########
grails-testing-support-http-client/src/test/groovy/org/apache/grails/testing/http/client/TestHttpResponseSpec.groovy:
##########
@@ -199,36 +198,18 @@ class TestHttpResponseSpec extends Specification {
         xmlResponse.xml().item.text() == 'value'
     }
 
-    void 'xml uses a secure default slurper that does not resolve external 
entities'() {
+    void 'xml rejects doctype declarations with external entities'() {
         given:
-        def secretFile = Files.createTempFile('test-http-response-xml', '.txt')
-        Files.writeString(secretFile, 'top-secret-token')
-        def uri = secretFile.toUri().toASCIIString()
-        def response = mockResponse(200, """<!DOCTYPE root [
-<!ENTITY ext SYSTEM '${uri}'>
-]>
-<root>&ext;</root>""")
+        def response = mockResponse(200, '''<!DOCTYPE root [
+ <!ENTITY ext SYSTEM "file:///not-resolved">
+ ]>

Review Comment:
   This spec previously verified that the response XML slurper still allowed 
internal DOCTYPEs; after the behavioral change to reject DOCTYPE declarations, 
adding an explicit internal-subset DOCTYPE rejection test would better validate 
the new default behavior (and is less dependent on external-entity resolution 
mechanics).



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to