diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 5369d052223..a945c333200 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -8,6 +8,9 @@
+
+ Enable FEATURE_SECURE_PROCESSING for the XSLT processor.
+
Document disabling of website certificate check in the FAQ.
diff --git a/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XSLTProcessor.java b/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XSLTProcessor.java
index c22c87579e2..171226c1a15 100644
--- a/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XSLTProcessor.java
+++ b/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XSLTProcessor.java
@@ -26,6 +26,7 @@
import java.util.HashMap;
import java.util.Map;
+import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
@@ -128,6 +129,11 @@ private Object transform(final Node source) {
final TransformerFactory transformerFactory = TransformerFactory.newInstance();
+ // By default, the JDK turns on FSP for DOM and SAX parsers and XML schema validators,
+ // which sets a number of processing limits on the processors. Conversely, by default,
+ // the JDK turns off FSP for transformers and XPath, which enables extension functions for XSLT and XPath.
+ transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+
final SgmlPage page = sourceDomNode.getPage();
if (page != null && page.getWebClient().getBrowserVersion()
.hasFeature(JS_XSLT_TRANSFORM_INDENT)) {
diff --git a/src/test/java/com/gargoylesoftware/htmlunit/ErrorOutputChecker.java b/src/test/java/com/gargoylesoftware/htmlunit/ErrorOutputChecker.java
index 2540ec24b27..8b4e1da7f34 100644
--- a/src/test/java/com/gargoylesoftware/htmlunit/ErrorOutputChecker.java
+++ b/src/test/java/com/gargoylesoftware/htmlunit/ErrorOutputChecker.java
@@ -47,7 +47,12 @@ public class ErrorOutputChecker implements MethodRule {
// Quercus
Pattern.compile(".*com.caucho.quercus.servlet.QuercusServlet initImpl\r?\n"),
Pattern.compile(".*QuercusServlet starting as QuercusServletImpl\r?\n"),
- Pattern.compile(".*Quercus finished initialization in \\d*ms\r?\n")
+ Pattern.compile(".*Quercus finished initialization in \\d*ms\r?\n"),
+
+ // Xalan
+ Pattern.compile("ERROR:\\s*'Use of the extension function "
+ + "'http://xml\\.apache\\.org/xalan/java/.*' "
+ + "is not allowed when the secure processing feature is set to true\\.'\r?\n"),
};
/**
diff --git a/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XSLTProcessorTest.java b/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XSLTProcessorTest.java
index 4020d2783e4..43c37d983f5 100644
--- a/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XSLTProcessorTest.java
+++ b/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XSLTProcessorTest.java
@@ -23,6 +23,7 @@
import com.gargoylesoftware.htmlunit.WebDriverTestCase;
import com.gargoylesoftware.htmlunit.junit.BrowserRunner;
import com.gargoylesoftware.htmlunit.junit.BrowserRunner.Alerts;
+import com.gargoylesoftware.htmlunit.junit.BrowserRunner.HtmlUnitNYI;
import com.gargoylesoftware.htmlunit.util.MimeType;
/**
@@ -38,28 +39,49 @@ public class XSLTProcessorTest extends WebDriverTestCase {
* @throws Exception if the test fails
*/
@Test
- @Alerts("exception")
+ @Alerts(DEFAULT = ""
+ + " My CD Collection
"
+ + "- Empire Burlesque (Bob Dylan)
",
+ FF = ""
+ + "My CD Collection
"
+ + "- Empire Burlesque (Bob Dylan)
",
+ FF_ESR = ""
+ + "My CD Collection
"
+ + "- Empire Burlesque (Bob Dylan)
",
+ IE = "exception")
+ @HtmlUnitNYI(CHROME = "My CD Collection
"
+ + "- Empire Burlesque (Bob Dylan)
",
+ EDGE = "My CD Collection
"
+ + "- Empire Burlesque (Bob Dylan)
",
+ FF = "My CD Collection
"
+ + "- Empire Burlesque (Bob Dylan)
",
+ FF_ESR = "My CD Collection
"
+ + "- Empire Burlesque (Bob Dylan)
")
public void test() throws Exception {
final String html = "\n"
+ ""
+ + "\n"
+ + "";
+
+ final String xml
+ = "\n"
+ + "";
+
+ final String xsl
+ = " \r\n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \r\n"
+ + " ";
+
+ final MockWebConnection conn = getMockWebConnection();
+ conn.setResponse(new URL(URL_SECOND, "1"), xml, MimeType.TEXT_XML);
+ conn.setResponse(new URL(URL_SECOND, "2"), xsl, MimeType.TEXT_XML);
+
+ loadPageVerifyTitle2(html);
+ }
}