Skip to content

CWE-91: XML Injection

Overview

This guidance helps interpret DAST findings for CWE-91: XML Injection. During dynamic scanning, the scanner detected that XML structure could be manipulated by injecting XML syntax into user-controlled data fields, altering the parsed document structure.

What the DAST scanner detected:

  • XML metacharacters (<, >, </tag>, <!--, <![CDATA[) in input parameters reflected unescaped in XML responses
  • Modified XML structure observable in responses (e.g., injected <admin>true</admin> tags appear in parsed output)
  • XML parsing errors or malformed structures when injection payloads are submitted
  • Application logic changes based on injected XML elements (e.g., privilege escalation via injected <role>admin</role>)
  • Different behavior when XML-valid vs XML-invalid input is provided

Key DAST evidence:

  • Input: name=John</name><role>admin</role><name>Doe results in parsed XML containing unexpected <role>admin</role> element
  • Response XML shows injected elements: <user><name>Alice</name><isAdmin>true</isAdmin><!--- injected --></user>
  • Application grants unauthorized access after XML structure manipulation
  • Error: XML Parsing Error: mismatched tag. Expected: </user> when invalid XML submitted
  • CDATA injection: name=Bob]]><admin>true</admin><![CDATA[x breaks out of CDATA section

Note: CWE-91 (XML Injection) involves modifying XML structure. External entity expansion and DTD processing are covered under CWE-611 (XXE).

Analyzing the Dynamic Scan Result

What the DAST Scanner Found

When reviewing your security scan results, you'll see:

HTTP Request Details

  • URL and endpoint that triggered the finding
  • HTTP method (GET, POST, etc.)
  • Query parameters or form data with test payloads
  • Request headers and body content

HTTP Response Evidence

  • Response showing the vulnerability manifestation
  • Evidence of improper handling or injection
  • Runtime behavior indicators

Attack Vector

  • Which parameter or input is vulnerable
  • Type of exploitation possible
  • Context where the vulnerability appears

Mapping DAST Findings to Source Code

Find the Vulnerable Endpoint

Use the HTTP request URL to locate the code:

# Search for the URL path in your codebase
grep -r "/api/xml" src/
grep -r "/export" src/
grep -r "/generate" src/
grep -r "/rss" src/
grep -r "route.*export" src/

Locate the Route Handler

Common patterns to search for:

  • Python Flask/Django: @app.route('/export'), path('api/xml/', ...)
  • Node.js Express: app.post('/generate', ...), router.get('/rss', ...)
  • Java Spring: @PostMapping("/export"), @GetMapping("/api/xml")
  • ASP.NET: [Route("export")], [HttpPost("generate")]
  • PHP: $_POST['name'], XML generation from user input

Find the Parameter Handling

Search for the vulnerable parameter name:

# Find where the parameter is accessed
grep -r "request.form.get('name')" src/      # Python Flask
grep -r "req.body.title" src/                # Node.js
grep -r "@RequestParam.*name" src/           # Java Spring
grep -r "Request.Form['description']" src/   # ASP.NET
grep -r "$_POST['content']" src/             # PHP

Trace to Vulnerable Operation

Look for where the parameter is used in:

  • XML construction: String concatenation to build XML
  • Template rendering: XML templates with user data
  • SOAP message generation: Building SOAP envelopes
  • RSS/Atom feed generation: User content in XML feeds
  • XML serialization: Converting objects to XML with user-controlled fields

Remediation

Core principle: Never construct XML by concatenating untrusted input; use XML libraries that treat user input as data and automatically escape it so it cannot alter document structure.

→ For comprehensive remediation guidance, see Static CWE-91 Guidance

Language-Specific Guidance

The static guidance provides detailed remediation steps for many languages. If you need language-specific examples:

Verification and Follow-Up Testing

After applying the fix:

Reproduce the Vulnerability

# Use curl to test XML injection
curl -X POST "http://localhost:3000/export" \

  -d "name=John</name><role>admin</role><name>Doe"

curl -X POST "http://localhost:3000/generate" \

  -d "title=Test</title><admin>true</admin><title>Article"

# Or use browser DevTools Network tab to copy as cURL

XML Injection Payloads:

# Tag injection
John</name><admin>true</admin><name>Doe

# Comment injection
value--><admin>true</admin><!--

# CDATA injection
]]><admin>true</admin><![CDATA[

# Attribute injection
" role="admin

Verify the Fix

  • Confirm no XML is built via string concatenation
  • Confirm user input is passed as data nodes / attributes via XML APIs
  • Confirm XML serializers perform automatic escaping
  • Confirm attackers cannot inject tags, attributes, namespaces, or CDATA
  • Confirm malformed XML does not leak parser errors

Test Edge Cases

# Tag closure injection
/export?name=</name><role>admin</role><name>

# Multiple field injection
/generate?title=Test&author=</author><isPublic>true</isPublic><author>

# Namespace injection
/api/xml?data=</item><item xmlns:evil="http://evil.com">

# Or use browser DevTools Network tab to copy as cURL

Re-run DAST Scanner

Run your dynamic scanner again on the fixed endpoint to confirm remediation.

Additional Resources