Skip to content

Conversation

@Patrykb0802
Copy link
Contributor

@Patrykb0802 Patrykb0802 commented Dec 12, 2025

Summary by CodeRabbit

  • New Features

    • Added backward compatibility support for DWR 2 functionality to ensure smooth integration with existing code.
    • Introduced a new JSP custom tag for serializing objects directly to JSON output.
  • Chores

    • Upgraded DWR framework from version 2.0 to 3.0 with updated DTD references.

✏️ Tip: You can customize this high-level summary in your review settings.

@github-actions
Copy link

github-actions bot commented Dec 12, 2025

Java Script Mocha Unit Test Results

268 tests   268 ✅  3s ⏱️
 70 suites    0 💤
  1 files      0 ❌

Results for commit 76d6d89.

♻️ This comment has been updated with latest results.

@github-actions
Copy link

github-actions bot commented Dec 12, 2025

Java JUnit Test Results

3 440 tests   3 440 ✅  51s ⏱️
  134 suites      0 💤
  134 files        0 ❌

Results for commit 76d6d89.

♻️ This comment has been updated with latest results.

@Limraj Limraj added this to the 2.8.2 milestone Jan 5, 2026
@Patrykb0802
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Jan 9, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link

coderabbitai bot commented Jan 9, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

📝 Walkthrough

Walkthrough

The pull request upgrades Direct Web Remoting (DWR) from version 2.0 to 3.0. Changes include updating the XML configuration doctype, refactoring converter method signatures to match DWR 3.0 specifications, adding JavaScript compatibility aliases for DWR 2 fallback behavior, delegating WebContext filter logic to a helper class, and introducing a new JSP custom tag for JSON serialization.

Changes

Cohort / File(s) Summary
DWR Configuration
WebContent/WEB-INF/dwr.xml
Updated doctype from Direct Web Remoting 2.0 to 3.0, including public DTD reference and system identifier updates
DWR Converter Refactoring
src/com/serotonin/mango/web/dwr/OpcUaDataTypeConverter.java, src/com/serotonin/mango/web/dwr/ProtocolVersionConverter.java
Removed InboundContext parameter from convertInbound method signatures; changed decoding from LocalUtil.decode() to LocalUtil.urlDecode()
Web Filter Refactoring
src/com/serotonin/mango/web/filter/WebContextFilter.java
Replaced manual WebContext wiring with delegate pattern using DwrWebContextFilter; removed direct usage of DefaultWebContextBuilder and ServletContext; added exception declaration to init() and delegated destruction in destroy()
JavaScript Compatibility
WebContent/resources/common.js
Added DWR 2 compatibility global alias for $ with safe fallback chain: preserves existing window.$ if available, attempts dwr.util.byId, or falls back to getElementById implementation
New JSP Tag Library
src/com/serotonin/web/taglib/DwrConvertTag.java
Introduced new custom JSP tag for serializing objects to JSON output, supporting primitives, strings, LocalizableMessage, collections, maps, arrays, and null values with proper type dispatch and localization handling

Possibly related issues

  • Update DWR library to version 3.0 #3227: This PR directly implements the DWR 3.0 upgrade requested, updating configuration and refactoring converters to align with the new DWR 3.0 API specifications.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes


🐰 Hop along to DWR 3.0, where converters dance anew,
JavaScript falls back with grace, and tags serialize true,
Filter patterns shift to delegates, cleaner by design,
Forward-bound and backward-compatible, a version upgrade so fine!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main objective of the changeset: updating the DWR library to version 3.0, which is directly reflected in the DWR doctype change and related converter/compatibility updates.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
WebContent/WEB-INF/dwr.xml (1)

253-293: Missing import and malformed import syntax in DWR signatures block.

Two syntax errors must be fixed:

  1. Line 279: import br.org.scadabr.web.dwr.UsersProfilesDwr is missing a semicolon
  2. Line 292: SystemSettingsDwr.saveSystemEventAlarmLevels(...) references a class with no import statement (missing import com.serotonin.mango.web.dwr.SystemSettingsDwr;)

Both are required for DWR 3 compatibility.

Minimal fix (inside the CDATA block)
-      import br.org.scadabr.web.dwr.UsersProfilesDwr
+      import br.org.scadabr.web.dwr.UsersProfilesDwr;
+      import com.serotonin.mango.web.dwr.SystemSettingsDwr;
🤖 Fix all issues with AI agents
In @src/com/serotonin/web/taglib/DwrConvertTag.java:
- Around line 14-16: Replace usage of the internal log4j JsonUtils.quoteAsString
and raw Number.toString in DwrConvertTag by wiring in Jackson's ObjectMapper:
create/configure a shared ObjectMapper (or use existing project one) and call
writeValueAsString(...) to produce JSON strings instead of manual quoting;
before serializing Numbers, detect Float/Double and if
Double.isNaN/Double.isInfinite (or Float equivalents) handle them
deterministically (e.g., serialize as null or throw a clear
IllegalArgumentException) so invalid JSON tokens like NaN/Infinity are not
emitted; also configure the ObjectMapper/JsonFactory with a CharacterEscapes
implementation (or use StdSerializer that escapes HTML-sensitive chars) to
ensure '<', '>', '&' are escaped for safe embedding in HTML/script; finally
remove imports of org.apache.logging.log4j.core.util.JsonUtils and replace all
calls in DwrConvertTag (the methods that previously used JsonUtils.quoteAsString
and Number.toString) with the new ObjectMapper-based serialization and the
NaN/Infinity guard.
- Around line 18-47: The DwrConvertTag (class DwrConvertTag) is declared in the
TLD as tag name "convert" but no JSP usage was found; either add example
usages/docs showing where to use <escape:convert> (e.g., demonstrate import of
the escape taglib and use within a <script type="application/json"> or other
appropriate context) and a short JSP snippet in the project docs or a sample
JSP, or remove the tag and its TLD entry if truly unused; update the TLD
(escape.tld) and project docs or delete the DwrConvertTag class accordingly to
keep code and configuration in sync.

In @WebContent/WEB-INF/dwr.xml:
- Line 19: The DOCTYPE line in dwr.xml references an external DTD ("-//GetAhead
Limited//DTD Direct Web Remoting 3.0//EN" "http://getahead.org/dwr/dwr30.dtd")
which can cause XXE/SSRF and runtime failures; update your configuration to
either (a) remove the external system URL and point the DOCTYPE to a bundled
local copy of dwr30.dtd included with the application, or (b) keep the PUBLIC id
but configure your XML parser/Factory to disable external entity/DTD loading and
enable a local EntityResolver/resource resolver that returns the bundled
dwr30.dtd; ensure the change targets the XML parsing code that reads dwr.xml (or
the deployment parser) so external fetching is prevented.
🧹 Nitpick comments (1)
WebContent/resources/common.js (1)

26-43: Global $ alias is helpful, but consider avoiding clobbering any pre-existing non-function $.
Right now, any existing window.$ that isn’t a function gets overwritten; that’s usually fine, but it can still be a surprising global collision.

Safer guard (only define if truly absent)
 (function () {
-    if (typeof window.$ === 'function') {
+    if (window.$ != null) {
         return;
     }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ec8e185 and a7b3fd8.

⛔ Files ignored due to path filters (1)
  • WebContent/WEB-INF/lib/dwr.jar is excluded by !**/*.jar
📒 Files selected for processing (6)
  • WebContent/WEB-INF/dwr.xml
  • WebContent/resources/common.js
  • src/com/serotonin/mango/web/dwr/OpcUaDataTypeConverter.java
  • src/com/serotonin/mango/web/dwr/ProtocolVersionConverter.java
  • src/com/serotonin/mango/web/filter/WebContextFilter.java
  • src/com/serotonin/web/taglib/DwrConvertTag.java
🔇 Additional comments (3)
src/com/serotonin/mango/web/dwr/OpcUaDataTypeConverter.java (1)

12-18: The code is correct. The convertInbound(Class, InboundVariable) signature matches DWR 3's EnumConverter contract, and LocalUtil.urlDecode() is the correct method for decoding inbound values—DWR's own LocaleConverter uses the same pattern. The @Override annotation confirms proper inheritance.

src/com/serotonin/mango/web/dwr/ProtocolVersionConverter.java (1)

12-18: The implementation is correct. DWR 3 converters use LocalUtil.urlDecode() to decode inbound values, which is what both ProtocolVersionConverter and OpcUaDataTypeConverter already do. The signature convertInbound(Class paramType, InboundVariable iv) with MarshallException is consistent with the DWR 3 EnumConverter SPI and follows the same pattern as other DWR 3 implementations (e.g., LocaleConverter).

src/com/serotonin/mango/web/filter/WebContextFilter.java (1)

30-54: Delegate to DwrWebContextFilter is the correct approach for DWR 3.

Filter ordering in web.xml ensures WebContext is initialized before request processing. Extensive codebase usage of WebContextFactory.get() confirms the implementation works correctly—no prior manual set/unset behavior was relied upon by application code. The simplification from custom lifecycle management to delegation is valid and reduces maintenance burden.

Comment on lines 14 to 16
import org.apache.logging.log4j.core.util.JsonUtils;
import com.serotonin.web.i18n.I18NUtils;
import com.serotonin.web.i18n.LocalizableMessage;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Check for project dependencies - look for pom.xml or gradle.build
git ls-files | grep -E "(pom\.xml|build\.gradle|ivy\.xml)" | head -5

Repository: SCADA-LTS/Scada-LTS

Length of output: 100


🏁 Script executed:

# Check the full DwrConvertTag.java file
find . -name "DwrConvertTag.java" -type f

Repository: SCADA-LTS/Scada-LTS

Length of output: 112


🏁 Script executed:

# Check for taglib descriptor files
git ls-files | grep -E "\.(tld|xml)$" | grep -i tag | head -10

Repository: SCADA-LTS/Scada-LTS

Length of output: 45


🏁 Script executed:

# Check main build.gradle for log4j-core dependency
cat build.gradle | grep -A 50 -B 5 -i "log4j"

Repository: SCADA-LTS/Scada-LTS

Length of output: 45


🏁 Script executed:

# Check the full DwrConvertTag.java file
cat -n src/com/serotonin/web/taglib/DwrConvertTag.java

Repository: SCADA-LTS/Scada-LTS

Length of output: 5900


🏁 Script executed:

# Read the full build.gradle to check dependencies
cat build.gradle | head -200

Repository: SCADA-LTS/Scada-LTS

Length of output: 6341


🏁 Script executed:

# Search for any mention of log4j or json libraries more broadly
rg "log4j|jackson|gson|json-p|org\.json" build.gradle

Repository: SCADA-LTS/Scada-LTS

Length of output: 45


🏁 Script executed:

# Check if there's any usage of JsonUtils in the codebase
rg "JsonUtils" --type java

Repository: SCADA-LTS/Scada-LTS

Length of output: 570


🏁 Script executed:

# Check what's in WEB-INF/lib to see if log4j-core is there
find WebContent/WEB-INF/lib -name "*log4j*" 2>/dev/null | head -20

Repository: SCADA-LTS/Scada-LTS

Length of output: 291


🏁 Script executed:

# Check the lib directory as well
find lib -name "*log4j*" 2>/dev/null | head -20

Repository: SCADA-LTS/Scada-LTS

Length of output: 45


🏁 Script executed:

# Search for any JSON-related libraries in the project that might be better options
find WebContent/WEB-INF/lib lib -name "*.jar" 2>/dev/null | grep -iE "(jackson|gson|json)" | head -20

Repository: SCADA-LTS/Scada-LTS

Length of output: 484


🏁 Script executed:

# Check if there are any .tld files at all
find . -name "*.tld" -o -name "*.xml" | grep -i taglib 2>/dev/null | head -10

Repository: SCADA-LTS/Scada-LTS

Length of output: 45


🏁 Script executed:

# Verify JsonUtils.quoteAsString escaping by checking log4j source or docs
# Check if there are any tests or usages that show what characters it escapes
rg "quoteAsString" -A 5 -B 5 --type java

Repository: SCADA-LTS/Scada-LTS

Length of output: 783


🏁 Script executed:

# Check if Jackson ObjectMapper is used elsewhere in the codebase
rg "ObjectMapper|Jackson|writeValueAsString" --type java | head -15

Repository: SCADA-LTS/Scada-LTS

Length of output: 2305


Replace log4j-core's internal JsonUtils with Jackson and fix Number serialization.

The project includes log4j-core-2.16.0.jar and jackson-databind-2.17.2.jar. Using JsonUtils.quoteAsString() is problematic because:

  1. It's an internal API (org.apache.logging.log4j.core.util.*), not part of log4j's public contract, while Jackson is already the established pattern in the codebase (see SystemSettingsUtils and test usage).
  2. Number.toString() (line 57–59) emits invalid JSON: values like NaN, Infinity, and -Infinity are not valid JSON numbers.
  3. Limited HTML-safe escaping: The current escaping does not encode <, >, or &, risking XSS if JSON is embedded in HTML/script contexts without extra precautions.

Use Jackson's ObjectMapper (already integrated and available via the project's dependency chain). Jackson correctly rejects or safely handles NaN/Infinity, and allows configuration of proper JSON escaping for both syntax and HTML contexts.

🤖 Prompt for AI Agents
In @src/com/serotonin/web/taglib/DwrConvertTag.java around lines 14 - 16,
Replace usage of the internal log4j JsonUtils.quoteAsString and raw
Number.toString in DwrConvertTag by wiring in Jackson's ObjectMapper:
create/configure a shared ObjectMapper (or use existing project one) and call
writeValueAsString(...) to produce JSON strings instead of manual quoting;
before serializing Numbers, detect Float/Double and if
Double.isNaN/Double.isInfinite (or Float equivalents) handle them
deterministically (e.g., serialize as null or throw a clear
IllegalArgumentException) so invalid JSON tokens like NaN/Infinity are not
emitted; also configure the ObjectMapper/JsonFactory with a CharacterEscapes
implementation (or use StdSerializer that escapes HTML-sensitive chars) to
ensure '<', '>', '&' are escaped for safe embedding in HTML/script; finally
remove imports of org.apache.logging.log4j.core.util.JsonUtils and replace all
calls in DwrConvertTag (the methods that previously used JsonUtils.quoteAsString
and Number.toString) with the new ObjectMapper-based serialization and the
NaN/Infinity guard.

Comment on lines 18 to 47
public class DwrConvertTag extends TagSupport {

private Object obj;

public DwrConvertTag() {
// no-op
}

public void setObj(Object obj) {
this.obj = obj;
}

@Override
public int doStartTag() throws JspException {
try {
JspWriter out = pageContext.getOut();
String json = toJson(obj);
out.write(json);
return SKIP_BODY;
} catch (IOException e) {
throw new JspException("Error writing DwrConvertTag JSON content", e);
}
}

@Override
public void release() {
super.release();
this.obj = null;
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find tag registration and usage
rg -n --fixed-strings "DwrConvertTag" -C2
rg -n --glob='**/*.tld' -C2 "com.serotonin.web.taglib.DwrConvertTag"
rg -n --glob='**/*.jsp' -C2 "dwrConvert" "DwrConvertTag"

Repository: SCADA-LTS/Scada-LTS

Length of output: 1917


🏁 Script executed:

#!/bin/bash
# View the full TLD descriptor entry for the convert tag
cat -n WebContent/WEB-INF/tld/escape.tld | sed -n '550,570p'

# Search for actual usage in JSP files
fd --type f -e jsp -e jspx | head -20 | xargs -I {} rg -l "convert" {} 2>/dev/null

Repository: SCADA-LTS/Scada-LTS

Length of output: 839


🏁 Script executed:

#!/bin/bash
# Find JSP files and search for the convert tag usage
# The tag would typically be used with a namespace prefix like <escape:convert ...>
find . -name "*.jsp" -o -name "*.jspx" | xargs rg -l "convert" 2>/dev/null | head -10
# Also search explicitly for the tag pattern
rg -n "escape:convert|<convert" --type jsp 2>/dev/null | head -20

Repository: SCADA-LTS/Scada-LTS

Length of output: 420


🏁 Script executed:

#!/bin/bash
# Search for escape:convert tag usage in JSP files
rg -n "escape:convert" --type jsp 2>/dev/null

# Also check for the tag declaration in JSP files
rg -n "<%@ taglib.*escape" --type jsp 2>/dev/null | head -5

Repository: SCADA-LTS/Scada-LTS

Length of output: 45


🏁 Script executed:

#!/bin/bash
# Check if any JSP files actually import the escape taglib
rg -n "taglib.*escape" --type jsp 2>/dev/null | head -10

# Search for any test files or usage
find . -name "*Test*.java" -o -name "*test*.java" | xargs rg -l "DwrConvertTag\|escape:convert" 2>/dev/null

# Check for documentation or examples
find . -name "*.md" -o -name "*.txt" -o -name "*.rst" | xargs rg -l "DwrConvertTag\|dwrConvert" 2>/dev/null

Repository: SCADA-LTS/Scada-LTS

Length of output: 47


🏁 Script executed:

#!/bin/bash
# Simpler search for taglib imports
rg "taglib" --type jsp 2>/dev/null | grep -i escape | head -10

# Check for any JSP importing the escape TLD
rg -n "escape.tld\|uri=\".*escape" --type jsp 2>/dev/null | head -10

# Count occurrences of "convert" in JSP files to understand context
rg -n "convert" --type jsp 2>/dev/null | head -20

Repository: SCADA-LTS/Scada-LTS

Length of output: 45


🏁 Script executed:

#!/bin/bash
# Check web.xml for TLD references
rg -n "escape.tld" --type xml 2>/dev/null

# Check if there's a web.xml file
find . -name "web.xml" -type f | head -3

# Look for taglib-uri declarations
rg -n "taglib-uri" --type xml 2>/dev/null | head -20

# Check escape.tld header to see URI
head -20 WebContent/WEB-INF/tld/escape.tld

Repository: SCADA-LTS/Scada-LTS

Length of output: 963


🏁 Script executed:

#!/bin/bash
# List all TLD files
ls -la WebContent/WEB-INF/tld/

# Verify which file contains the convert tag
rg -l "convert" WebContent/WEB-INF/tld/

Repository: SCADA-LTS/Scada-LTS

Length of output: 335


🏁 Script executed:

#!/bin/bash
# Check if escape.tld is referenced in web.xml
cat WebContent/WEB-INF/web.xml | grep -i "escape\|serotonin" | head -20

# Check the URI declared in escape.tld
head -15 WebContent/WEB-INF/tld/escape.tld | grep -i uri

# Search for JSP imports with the URI pattern
rg -n "http://www.serotoninsoftware.com" --type jsp 2>/dev/null

Repository: SCADA-LTS/Scada-LTS

Length of output: 1757


🏁 Script executed:

#!/bin/bash
# Check escape.tld for its declared URI
grep -n "uri" WebContent/WEB-INF/tld/escape.tld | head -3

# Search JSP files for taglib imports with escape or serotonin URIs
rg -n "<%@ taglib" --type jsp 2>/dev/null | head -30

Repository: SCADA-LTS/Scada-LTS

Length of output: 118


🏁 Script executed:

#!/bin/bash
# Search for taglib directives in JSP using different pattern
rg "<%@.*taglib" --type jsp 2>/dev/null | head -20

# Also search for URI mappings in web.xml
grep -n "taglib-uri\|taglib-location" WebContent/WEB-INF/web.xml 2>/dev/null

Repository: SCADA-LTS/Scada-LTS

Length of output: 45


🏁 Script executed:

#!/bin/bash
# Final check: search for any reference to "dwrConvert" or "dwr" that might indicate usage
rg -i "dwr" --type jsp --type java 2>/dev/null | head -20

# Also check comments in the TLD
grep -A 2 -B 2 "convert" WebContent/WEB-INF/tld/escape.tld

Repository: SCADA-LTS/Scada-LTS

Length of output: 215


The tag IS properly registered in the TLD but appears unused in JSP pages.
The tag is correctly wired in WebContent/WEB-INF/tld/escape.tld (lines 552–561) with the name convert, required obj attribute, and proper configuration. However, no usage of this tag (e.g., <escape:convert> or imports of the escape taglib) was found in any JSP files. If this tag is genuinely needed, add JSP usage examples or documentation specifying its output context (e.g., only within <script type="application/json"> blocks). If unused, consider removing it.

🤖 Prompt for AI Agents
In @src/com/serotonin/web/taglib/DwrConvertTag.java around lines 18 - 47, The
DwrConvertTag (class DwrConvertTag) is declared in the TLD as tag name "convert"
but no JSP usage was found; either add example usages/docs showing where to use
<escape:convert> (e.g., demonstrate import of the escape taglib and use within a
<script type="application/json"> or other appropriate context) and a short JSP
snippet in the project docs or a sample JSP, or remove the tag and its TLD entry
if truly unused; update the TLD (escape.tld) and project docs or delete the
DwrConvertTag class accordingly to keep code and configuration in sync.

along with this program. If not, see http://www.gnu.org/licenses/.
-->
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://getahead.org/dwr/dwr20.dtd">
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN" "http://getahead.org/dwr/dwr30.dtd">
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

DWR 3.0 Direct Web Remoting dwr.xml DOCTYPE DTD reference specification

💡 Result:

Use this DOCTYPE in dwr.xml for DWR 3.0:

(Older examples also reference "http://getahead.org/dwr/dwr30.dtd" with the same public id.) [1][2]


🌐 Web query:

getahead.org dwr30.dtd external DTD remote fetch best practices

💡 Result:

Short answer: avoid letting XML parsers fetch external DTDs (like getahead.org/dwr30.dtd) from the network. Either disable external DTD/ENTITY loading or resolve DTDs locally and tightly control when/what the parser may fetch. Key practices:

  • Disable DTDs or external-entity resolution in your parser (best): disallow DOCTYPE, disable external entities and external DTD loading. [1][2][3]
  • If DTDs are required, use a local, versioned copy (vendor bundle or internal repository) and configure the parser to resolve only that local store (catalog resolver/whitelist). Do not permit arbitrary HTTP fetches. [6][2]
  • Set parser attributes to block network access: e.g. set XMLConstants.ACCESS_EXTERNAL_DTD and ACCESS_EXTERNAL_SCHEMA to "" or set apache feature http://apache.org/xml/features/nonvalidating/load-external-dtd to false. Also enable secure-processing features. [2][3][4]
  • Harden entity handling: disable entity expansion or limit expansions to prevent Billion‑Laughs/DoS. [1][3]
  • Network/operational controls: block outbound HTTP(S) from parse-time processes (egress rules) or allow only trusted hosts; log/alert any attempts to fetch external DTDs. [1][5]
  • Input validation and safe libraries: treat incoming XML as untrusted, validate against schemas that do not require external fetches and prefer parsers/libraries built with XXE protections (or use JSON instead if feasible). [1][3][5]
  • Fail-safe defaults and testing: audit code for DOCTYPE/entity handling, add unit tests and security tests that exercise XXE/SSRF and remote-DTD cases. Monitor dependencies for references to remote DTDs like getahead.org/dwr30.dtd and replace them. [1][4]

Sources: OWASP XML-External-Entity cheat sheet; Oracle Java XML guidance; Semgrep/secure-coding guidance; SecureCodingPractices article; general DTD pitfalls. [1][2][3][4][5]

References
[1] OWASP XML External Entity Prevention Cheat Sheet.
[2] Oracle — Java Technology and XML (reduce external entity/DTD cost and controls).
[3] Semgrep / XML Security guidance (disable DTDs / external entities).
[4] SecureCodingPractices — Avoid XXE in Java parsers (features/attributes examples).
[5] Article on DTD pitfalls and availability/performance/security trade-offs.


Disable external DTD loading or use local DTD resolution.
While the PUBLIC identifier is correct for DWR 3.0, fetching the DTD from an external URL (http://getahead.org/dwr/dwr30.dtd) introduces security risks (XXE/SSRF vulnerabilities) and operational fragility (network failures, offline/restricted environments). Configure your XML parser to disable external DTD/entity loading, or replace with a local, versioned copy of the DTD.

🤖 Prompt for AI Agents
In @WebContent/WEB-INF/dwr.xml at line 19, The DOCTYPE line in dwr.xml
references an external DTD ("-//GetAhead Limited//DTD Direct Web Remoting
3.0//EN" "http://getahead.org/dwr/dwr30.dtd") which can cause XXE/SSRF and
runtime failures; update your configuration to either (a) remove the external
system URL and point the DOCTYPE to a bundled local copy of dwr30.dtd included
with the application, or (b) keep the PUBLIC id but configure your XML
parser/Factory to disable external entity/DTD loading and enable a local
EntityResolver/resource resolver that returns the bundled dwr30.dtd; ensure the
change targets the XML parsing code that reads dwr.xml (or the deployment
parser) so external fetching is prevented.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants