From 249d6f7d3756bb50849da43d0c8dd9b90c8c2ddd Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Mon, 16 Feb 2026 12:37:28 -0800 Subject: [PATCH 1/2] Only send HTML to browser-type clients --- api/src/org/labkey/api/action/ExtFormResponseWriter.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/api/src/org/labkey/api/action/ExtFormResponseWriter.java b/api/src/org/labkey/api/action/ExtFormResponseWriter.java index 5c04008ff34..d8affb86daa 100644 --- a/api/src/org/labkey/api/action/ExtFormResponseWriter.java +++ b/api/src/org/labkey/api/action/ExtFormResponseWriter.java @@ -19,6 +19,7 @@ import org.labkey.api.query.PropertyValidationError; import org.labkey.api.query.ValidationError; import org.labkey.api.query.ValidationException; +import org.labkey.api.util.HttpUtil; import org.labkey.api.util.MimeMap; import org.springframework.validation.Errors; import org.springframework.validation.FieldError; @@ -70,7 +71,8 @@ public class ExtFormResponseWriter extends ApiJsonWriter public ExtFormResponseWriter(HttpServletRequest request, HttpServletResponse response) throws IOException { boolean sendHtml = !"XMLHttpRequest".equals(request.getHeader("X-Requested-With")) && - request instanceof MultipartHttpServletRequest; + request instanceof MultipartHttpServletRequest && + HttpUtil.isBrowser(request); super(response, sendHtml ? MimeMap.MimeType.HTML.getContentType() : CONTENT_TYPE_JSON); setErrorResponseStatus(HttpServletResponse.SC_OK); } From fce765caead525015b24b01b621454f4377943a4 Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Mon, 16 Feb 2026 12:52:14 -0800 Subject: [PATCH 2/2] Comments and consistency --- api/src/org/labkey/api/util/XmlBeansUtil.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/api/src/org/labkey/api/util/XmlBeansUtil.java b/api/src/org/labkey/api/util/XmlBeansUtil.java index 048a8f7bb72..9645be51dae 100644 --- a/api/src/org/labkey/api/util/XmlBeansUtil.java +++ b/api/src/org/labkey/api/util/XmlBeansUtil.java @@ -139,7 +139,13 @@ public static void addComment(XmlTokenSource doc, String comment) SAX_PARSER_FACTORY.setNamespaceAware(true); SAX_PARSER_FACTORY.setFeature("http://xml.org/sax/features/validation", false); SAX_PARSER_FACTORY.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + + // Disable features that could lead to XXE or other vulnerabilities + // Keep in sync with ModuleArchive.nameFromModuleXML() SAX_PARSER_FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + SAX_PARSER_FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false); + SAX_PARSER_FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + SAX_PARSER_FACTORY.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); DOCUMENT_BUILDER_FACTORY = DocumentBuilderFactory.newInstance(); DOCUMENT_BUILDER_FACTORY.setNamespaceAware(true);