Skip to content

Add safe XML building and parsing to Script mediator#2531

Merged
GDLMadushanka merged 1 commit intowso2:masterfrom
GDLMadushanka:improveXMLBuildMaster
Apr 8, 2026
Merged

Add safe XML building and parsing to Script mediator#2531
GDLMadushanka merged 1 commit intowso2:masterfrom
GDLMadushanka:improveXMLBuildMaster

Conversation

@GDLMadushanka
Copy link
Copy Markdown
Contributor

@GDLMadushanka GDLMadushanka commented Apr 8, 2026

Purpose

Use safe methods from Axis2 and Axiom to build and parse XML inputs in the script mediator.

Summary by CodeRabbit

  • Security

    • Hardened XML handling in JavaScript mediators: parsing now uses a secured parser and a security-enabled XML builder to reduce XXE and related risks.
  • New Features

    • Added a centralized, secure XML parsing utility used by JavaScript mediation components.
  • Chores

    • Bumped Axis2-related component versions for alignment and compatibility.

@GDLMadushanka GDLMadushanka requested a review from chanikag as a code owner April 8, 2026 02:20
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 8, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c8521ca6-ecff-4451-8fec-9aaaca5d56cb

📥 Commits

Reviewing files that changed from the base of the PR and between f63c4a9 and 3f9bb26.

📒 Files selected for processing (7)
  • modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/ExtendedJavaScriptXmlHelper.java
  • modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/GraalVMJavaScriptMessageContext.java
  • modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/JavaScriptXmlHelper.java
  • modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/NashornJavaScriptMessageContext.java
  • modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/OpenJDKNashornJavaScriptMessageContext.java
  • modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/utils/ScriptUtils.java
  • pom.xml
🚧 Files skipped from review as they are similar to previous changes (4)
  • modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/ExtendedJavaScriptXmlHelper.java
  • modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/utils/ScriptUtils.java
  • modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/JavaScriptXmlHelper.java
  • pom.xml

Walkthrough

Adds a security-hardened XML parser utility (ScriptUtils.parseXml), refactors multiple JavaScript message contexts to delegate XML parsing to it, switches OM builder usage to the security-enabled createOMBuilderWithSec, updates AXIOM/XML conversion calls to include additional boolean flags, and bumps the axis2.version Maven property.

Changes

Cohort / File(s) Summary
XML Parsing Delegation
modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/GraalVMJavaScriptMessageContext.java, modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/NashornJavaScriptMessageContext.java, modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/OpenJDKNashornJavaScriptMessageContext.java
parseXml(String) now delegates to ScriptUtils.parseXml(String) instead of creating/using a local DOMParser. getParsedOMElement(InputStream) now uses OMXMLBuilderFactory.createOMBuilderWithSec(stream). Exception handling preserved.
OMElement Conversion Enhancement
modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/ExtendedJavaScriptXmlHelper.java, modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/JavaScriptXmlHelper.java
XML→OMElement conversions updated to pass security/processing boolean flags (e.g., AXIOMUtil.stringToOM(..., true), XMLUtils.toOM(..., true, true)).
Hardened XML Parser Utility
modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/utils/ScriptUtils.java
New public ScriptUtils with public static Document parseXml(String) that builds a Xerces DOMParser with disabled DOCTYPE, external entities, and external DTD loading, then parses and returns a normalized Document (throws IOException, SAXException).
Dependency Version Update
pom.xml
Bumped Maven property axis2.version from 1.6.1-wso2v1241.6.1-wso2v125.

Sequence Diagram(s)

sequenceDiagram
    participant Context as JavaScript Message Context
    participant ScriptUtils as ScriptUtils.parseXml
    participant DOMParser as Hardened DOMParser
    participant OMBuilder as OMXMLBuilderFactory.createOMBuilderWithSec

    rect rgba(200,200,150,0.5)
    Note over Context,DOMParser: Old inline parsing flow (prior to change)
    Context->>DOMParser: new DOMParser()\nparse(InputSource)
    DOMParser-->>Context: Document
    end

    rect rgba(150,200,255,0.5)
    Note over Context,ScriptUtils: New delegated, hardened flow
    Context->>ScriptUtils: parseXml(text)
    ScriptUtils->>DOMParser: new DOMParser() with secure features\nparse(InputSource)
    DOMParser-->>ScriptUtils: Document (normalized)
    ScriptUtils-->>Context: Document
    Context->>OMBuilder: createOMBuilderWithSec(stream)
    OMBuilder-->>Context: OMElement
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I hopped through tags with gentle care,

hardened roots and parsers fair.
I passed my utils to contexts new,
trimmed loose entities from view.
🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description only includes the Purpose section with a brief statement. It is missing most required sections (Goals, Approach, User stories, Release note, Documentation, etc.) from the template. Complete the PR description by adding the missing required sections: Goals, Approach, User stories, Release note, Documentation, Training, Certification, Marketing, Automation tests, Security checks, Samples, Related PRs, Test environment, and Learning.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding safe XML building and parsing to the Script mediator, which matches the core changes across multiple files.
Docstring Coverage ✅ Passed Docstring coverage is 88.89% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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
Copy Markdown

@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.

🧹 Nitpick comments (2)
modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/utils/ScriptUtils.java (1)

31-45: Please lock this in with XXE regression tests.

This helper is now the single DOM parsing path for the script engines. A happy-path XML test plus explicit <!DOCTYPE> / external-entity rejection cases would make future dependency changes much safer.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/utils/ScriptUtils.java`
around lines 31 - 45, Add JUnit XXE regression tests for ScriptUtils.parseXml:
one happy-path test that passes a simple well-formed XML string and asserts a
non-null Document with expected root element, and two negative tests that supply
XML containing a DOCTYPE with an external ENTITY and a DOCTYPE with
parameter/external entities and assert that parseXml throws a
SAXException/IOException (or otherwise rejects the input) due to the configured
features; implement tests using the same class/method name ScriptUtils.parseXml
and include explicit assertions about exception type/message to lock in the XXE
protections.
modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/GraalVMJavaScriptMessageContext.java (1)

278-280: Consider centralizing secure OM parsing to ScriptUtils.

The call OMXMLBuilderFactory.createOMBuilderWithSec(stream) is duplicated identically across GraalVMJavaScriptMessageContext, NashornJavaScriptMessageContext, and OpenJDKNashornJavaScriptMessageContext. Since parseXml was centralized to ScriptUtils, extracting this secure OM builder call there as well would keep the XML parsing logic consistent and reduce maintenance drift across engine-specific implementations.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/GraalVMJavaScriptMessageContext.java`
around lines 278 - 280, getParsedOMElement currently duplicates
OMXMLBuilderFactory.createOMBuilderWithSec(stream) — centralize this secure OM
parsing in ScriptUtils to avoid repetition; add a new helper in ScriptUtils
(e.g., parseSecureOm(InputStream) or reuse parseXml to call
OMXMLBuilderFactory.createOMBuilderWithSec and return
builder.getDocumentElement()), then update
GraalVMJavaScriptMessageContext.getParsedOMElement (and the other
engine-specific classes) to call the new ScriptUtils helper instead of calling
OMXMLBuilderFactory.createOMBuilderWithSec directly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/GraalVMJavaScriptMessageContext.java`:
- Around line 278-280: getParsedOMElement currently duplicates
OMXMLBuilderFactory.createOMBuilderWithSec(stream) — centralize this secure OM
parsing in ScriptUtils to avoid repetition; add a new helper in ScriptUtils
(e.g., parseSecureOm(InputStream) or reuse parseXml to call
OMXMLBuilderFactory.createOMBuilderWithSec and return
builder.getDocumentElement()), then update
GraalVMJavaScriptMessageContext.getParsedOMElement (and the other
engine-specific classes) to call the new ScriptUtils helper instead of calling
OMXMLBuilderFactory.createOMBuilderWithSec directly.

In
`@modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/utils/ScriptUtils.java`:
- Around line 31-45: Add JUnit XXE regression tests for ScriptUtils.parseXml:
one happy-path test that passes a simple well-formed XML string and asserts a
non-null Document with expected root element, and two negative tests that supply
XML containing a DOCTYPE with an external ENTITY and a DOCTYPE with
parameter/external entities and assert that parseXml throws a
SAXException/IOException (or otherwise rejects the input) due to the configured
features; implement tests using the same class/method name ScriptUtils.parseXml
and include explicit assertions about exception type/message to lock in the XXE
protections.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9d6f34b5-28d6-4dc5-b06c-6ceee04306c7

📥 Commits

Reviewing files that changed from the base of the PR and between 7622a30 and 43ebc1a.

📒 Files selected for processing (7)
  • modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/ExtendedJavaScriptXmlHelper.java
  • modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/GraalVMJavaScriptMessageContext.java
  • modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/JavaScriptXmlHelper.java
  • modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/NashornJavaScriptMessageContext.java
  • modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/OpenJDKNashornJavaScriptMessageContext.java
  • modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/utils/ScriptUtils.java
  • pom.xml

@GDLMadushanka GDLMadushanka force-pushed the improveXMLBuildMaster branch 2 times, most recently from f63c4a9 to c43f941 Compare April 8, 2026 02:40
Copy link
Copy Markdown

@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: 1

🧹 Nitpick comments (2)
modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/utils/ScriptUtils.java (1)

31-45: Add regression coverage for the hardened XML paths.

This is the core XXE hardening point now. Please add tests that reject DOCTYPE/external-entity payloads and still accept normal XML, so a later refactor can't silently weaken the parser configuration.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/utils/ScriptUtils.java`
around lines 31 - 45, Add regression tests for ScriptUtils.parseXml to ensure
the hardened XML parser rejects DOCTYPE/external-entity payloads and still
accepts normal XML: create unit tests that call ScriptUtils.parseXml with a
malicious XML string containing a DOCTYPE/external-entity and assert it throws a
parsing exception (e.g., SAXException or an IOException), and another test that
calls parseXml with a simple well-formed XML and asserts a non-null Document
with expected root element; place tests alongside other module tests and
reference parseXml (ScriptUtils) to prevent future regressions of the security
features.
modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/GraalVMJavaScriptMessageContext.java (1)

259-262: Nice parser consolidation; consider sharing the secure OM builder too.

parseXml(...) is centralized now, but getParsedOMElement(...) is still duplicated here, OpenJDKNashornJavaScriptMessageContext, and NashornJavaScriptMessageContext. Moving the createOMBuilderWithSec(...) call into ScriptUtils as well would keep the hardening choice from drifting across runtimes.

Also applies to: 278-280

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/GraalVMJavaScriptMessageContext.java`
around lines 259 - 262, The getParsedOMElement duplication should call a
centralized secure OM builder in ScriptUtils: add a new method in ScriptUtils
(e.g., createOMBuilderWithSec or getSecureOMBuilder) that encapsulates the
hardening/secure builder logic, then update
GraalVMJavaScriptMessageContext.getParsedOMElement,
OpenJDKNashornJavaScriptMessageContext.getParsedOMElement, and
NashornJavaScriptMessageContext.getParsedOMElement to use
ScriptUtils.createOMBuilderWithSec instead of each creating their own builder;
also ensure parseXml continues to call ScriptUtils.parseXml and reuse the same
secure builder helper where applicable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/utils/ScriptUtils.java`:
- Around line 31-32: parseXml currently constructs an InputSource from the
incoming String without guarding for a null payload which causes a
NullPointerException to bubble up; update ScriptUtils.parseXml to check if the
incoming text is null (or empty if desired) and explicitly throw a SAXException
(or another checked exception already handled by the JavaScriptMessageContext
wrappers) with a clear message instead of letting an NPE occur so that parse
failures are translated into the expected ScriptException; locate the parseXml
method and add the null check before creating the InputSource.

---

Nitpick comments:
In
`@modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/GraalVMJavaScriptMessageContext.java`:
- Around line 259-262: The getParsedOMElement duplication should call a
centralized secure OM builder in ScriptUtils: add a new method in ScriptUtils
(e.g., createOMBuilderWithSec or getSecureOMBuilder) that encapsulates the
hardening/secure builder logic, then update
GraalVMJavaScriptMessageContext.getParsedOMElement,
OpenJDKNashornJavaScriptMessageContext.getParsedOMElement, and
NashornJavaScriptMessageContext.getParsedOMElement to use
ScriptUtils.createOMBuilderWithSec instead of each creating their own builder;
also ensure parseXml continues to call ScriptUtils.parseXml and reuse the same
secure builder helper where applicable.

In
`@modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/utils/ScriptUtils.java`:
- Around line 31-45: Add regression tests for ScriptUtils.parseXml to ensure the
hardened XML parser rejects DOCTYPE/external-entity payloads and still accepts
normal XML: create unit tests that call ScriptUtils.parseXml with a malicious
XML string containing a DOCTYPE/external-entity and assert it throws a parsing
exception (e.g., SAXException or an IOException), and another test that calls
parseXml with a simple well-formed XML and asserts a non-null Document with
expected root element; place tests alongside other module tests and reference
parseXml (ScriptUtils) to prevent future regressions of the security features.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: af88c162-ef75-45b0-ac6f-1e01a8fbea90

📥 Commits

Reviewing files that changed from the base of the PR and between 43ebc1a and f63c4a9.

📒 Files selected for processing (7)
  • modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/ExtendedJavaScriptXmlHelper.java
  • modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/GraalVMJavaScriptMessageContext.java
  • modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/JavaScriptXmlHelper.java
  • modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/NashornJavaScriptMessageContext.java
  • modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/OpenJDKNashornJavaScriptMessageContext.java
  • modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/utils/ScriptUtils.java
  • pom.xml
🚧 Files skipped from review as they are similar to previous changes (3)
  • modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/JavaScriptXmlHelper.java
  • modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/ExtendedJavaScriptXmlHelper.java
  • pom.xml

Comment on lines +31 to +32
public static Document parseXml(String text) throws IOException, SAXException {
InputSource sax = new InputSource(new java.io.StringReader(text));
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Guard null before constructing the parser input.

Line 32 will throw NullPointerException for a null payload, and the parseXml(...) wrappers in the *JavaScriptMessageContext classes only translate SAXException | IOException into ScriptException. That leaks an unexpected runtime exception back to scripts instead of a normal parse failure.

Proposed fix
 public static Document parseXml(String text) throws IOException, SAXException {
+    if (text == null) {
+        throw new SAXException("XML payload cannot be null");
+    }
     InputSource sax = new InputSource(new java.io.StringReader(text));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public static Document parseXml(String text) throws IOException, SAXException {
InputSource sax = new InputSource(new java.io.StringReader(text));
public static Document parseXml(String text) throws IOException, SAXException {
if (text == null) {
throw new SAXException("XML payload cannot be null");
}
InputSource sax = new InputSource(new java.io.StringReader(text));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/utils/ScriptUtils.java`
around lines 31 - 32, parseXml currently constructs an InputSource from the
incoming String without guarding for a null payload which causes a
NullPointerException to bubble up; update ScriptUtils.parseXml to check if the
incoming text is null (or empty if desired) and explicitly throw a SAXException
(or another checked exception already handled by the JavaScriptMessageContext
wrappers) with a clear message instead of letting an NPE occur so that parse
failures are translated into the expected ScriptException; locate the parseXml
method and add the null check before creating the InputSource.

Use safe methods from Axis2 and Axiom to build and parse XML inputs in the script mediator.
@GDLMadushanka GDLMadushanka force-pushed the improveXMLBuildMaster branch from c43f941 to 3f9bb26 Compare April 8, 2026 02:57
@GDLMadushanka GDLMadushanka merged commit ebe4576 into wso2:master Apr 8, 2026
1 of 2 checks passed
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.

2 participants