AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Sast Xxe

skill-utkusen-sast-skills-sast-xxe · by utkusen

>-

No reviews yet
0 installs
31 views
0.0% view→install

Install

$ agentstack add skill-utkusen-sast-skills-sast-xxe

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-utkusen-sast-skills-sast-xxe)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
5mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Sast Xxe? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

XML External Entity (XXE) Detection

You are performing a focused security assessment to find XXE vulnerabilities in a codebase. This skill uses a three-phase approach with subagents: recon (find XML parsing sites where external entities are not safely disabled), batched verify (trace whether user-supplied input reaches those parsers, in parallel batches of 3), and merge (consolidate batch results into one report).

Prerequisites: sast/architecture.md must exist. Run the analysis skill first if it doesn't.


What is XXE

XXE occurs when an XML parser processes a document containing a reference to an external entity and the parser has external entity resolution enabled. An attacker who can supply XML input can use this to read arbitrary local files, perform server-side request forgery (internal network probing), trigger denial-of-service via entity expansion (Billion Laughs), or in some stacks execute OS commands.

The core pattern: user-controlled XML reaches an XML parser that has not disabled DTD processing or external entity resolution.

What XXE IS

  • XML parsed with external entity resolution enabled by default and no explicit hardening applied
  • SYSTEM entity declarations that reference file:// or http:// URIs: ``
  • DTD processing not explicitly disabled in parsers where it is on by default (Java DOM/SAX, PHP SimpleXML/DOMDocument, libxml2-backed parsers)
  • Parameter entity injection in DTDs: %xxe;
  • XInclude injection when XInclude processing is enabled
  • SSRF via XXE: using http:// or https:// external entity URLs to reach internal services
  • Blind XXE via out-of-band exfiltration (DNS, HTTP callback to attacker-controlled server)

What XXE is NOT

Do not flag these as XXE:

  • XSS via XML: XML data rendered as HTML without escaping — that's XSS
  • SSRF via non-XML: HTTP requests triggered by other mechanisms — that's SSRF
  • XML parsing of fully server-controlled data: Config files, bundled resources, migration scripts with no user influence — not exploitable
  • Safe parsers: Libraries that disable external entities by default and provide no way to re-enable them (e.g. defusedxml in Python, nokogiri with default settings in Ruby for untrusted input)

Patterns That Prevent XXE

When you see these patterns, the parser is likely not vulnerable:

1. Disabling DTD / external entities (Java DOM)

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
dbf.setXIncludeAware(false);
dbf.setExpandEntityReferences(false);

2. Disabling external entities (Java SAX)

SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);

3. Disabling external entities (Java StAX / XMLInputFactory)

XMLInputFactory xif = XMLInputFactory.newInstance();
xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);

4. Python — defusedxml (always safe)

import defusedxml.ElementTree as ET
tree = ET.parse(source)  # external entities, DTD, entity expansion all blocked

5. Python — lxml with resolve_entities=False

from lxml import etree
parser = etree.XMLParser(resolve_entities=False, no_network=True)
tree = etree.parse(source, parser)

**6. PHP — libxmldisableentityloader (PHP loadXML($xml, LIBXMLNOENT | LIBXMLNONET); // LIBXMLNONET blocks network // Note: LIBXML_NOENT alone EXPANDS entities — it does NOT disable them


**7. .NET — XmlReaderSettings with DtdProcessing.Prohibit**
```csharp
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Prohibit;
settings.XmlResolver = null;
XmlReader reader = XmlReader.Create(stream, settings);

8. Node.js — xml2js (safe by default in v0.5+)

const xml2js = require('xml2js');
// xml2js does not resolve external entities by default — safe
xml2js.parseString(xmlInput, callback);

Vulnerable vs. Secure Examples

Python — stdlib xml.etree.ElementTree (vulnerable by default in CPython importXml(@RequestBody String xml) throws Exception {

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(new InputSource(new StringReader(xml))); return ResponseEntity.ok(process(doc)); }

// SECURE: disable DTD and external entity features @PostMapping("/import") public ResponseEntity importXml(@RequestBody String xml) throws Exception { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); dbf.setExpandEntityReferences(false); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(new InputSource(new StringReader(xml))); return ResponseEntity.ok(process(doc)); }


### Java — SAXParser

```java
// VULNERABLE: default SAXParser allows external entities
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
parser.parse(inputStream, handler);

// SECURE: disable external entities
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
SAXParser parser = factory.newSAXParser();
parser.parse(inputStream, handler);

Java — XMLInputFactory (StAX)

// VULNERABLE: default XMLInputFactory supports external entities
XMLInputFactory xif = XMLInputFactory.newInstance();
XMLStreamReader xsr = xif.createXMLStreamReader(inputStream);

// SECURE: disable external entity support
XMLInputFactory xif = XMLInputFactory.newInstance();
xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
XMLStreamReader xsr = xif.createXMLStreamReader(inputStream);

PHP — SimpleXML / DOMDocument

// VULNERABLE: simplexml_load_string with no entity loader disabled
function parseXml($xml) {
    return simplexml_load_string($xml);  // resolves external entities
}

// VULNERABLE: DOMDocument without protection
function parseXml($xml) {
    $doc = new DOMDocument();
    $doc->loadXML($xml);   // external entities enabled by default
    return $doc;
}

// SECURE (PHP 7.x): disable entity loader before parsing
function parseXml($xml) {
    libxml_disable_entity_loader(true);
    $doc = new DOMDocument();
    $doc->loadXML($xml, LIBXML_NONET);
    return $doc;
}

.NET — XmlDocument / XmlTextReader

// VULNERABLE: XmlDocument with default XmlUrlResolver resolves external entities
XmlDocument doc = new XmlDocument();
doc.Load(stream);   // external entities resolved

// VULNERABLE: XmlTextReader (legacy) — DTD processing on by default in old .NET
XmlTextReader reader = new XmlTextReader(stream);

// SECURE: XmlDocument with null resolver and prohibited DTD
XmlDocument doc = new XmlDocument();
doc.XmlResolver = null;   // disables external entity resolution
doc.Load(stream);

// SECURE: XmlReader with DtdProcessing.Prohibit
XmlReaderSettings settings = new XmlReaderSettings {
    DtdProcessing = DtdProcessing.Prohibit,
    XmlResolver = null
};
XmlReader reader = XmlReader.Create(stream, settings);

Node.js — libxmljs

// VULNERABLE: libxmljs parses with entity resolution on by default
const libxml = require('libxmljs');
app.post('/parse', (req, res) => {
    const doc = libxml.parseXmlString(req.body);
    res.send(doc.toString());
});

// SAFER: no built-in safe flag — avoid libxmljs for untrusted input entirely
// Prefer xml2js or a non-libxml2-backed parser

Ruby — Nokogiri

# VULNERABLE: Nokogiri with NOENT option enables entity substitution
def parse_xml(xml_input)
  Nokogiri::XML(xml_input) { |config| config.noent }
end

# SECURE: default Nokogiri (no options) — safe for untrusted input
def parse_xml(xml_input)
  Nokogiri::XML(xml_input)
end

Go — encoding/xml

// VULNERABLE: Go's encoding/xml does not resolve external entities
// but if combined with a third-party parser like etree with network enabled:
import "github.com/beevik/etree"

func parseXML(data []byte) {
    doc := etree.NewDocument()
    doc.ReadFromBytes(data)   // check library's entity resolution behaviour
}

// Go's standard encoding/xml: does not resolve external entities — generally safe.
// Flag only if a third-party XML library with entity support is used.

Execution

This skill runs in three phases using subagents. Pass the contents of sast/architecture.md to all subagents as context.

Phase 1: Find Vulnerable XML Parsing Sites

Launch a subagent with the following instructions:

> Goal: Find every location in the codebase where XML is parsed without external entity resolution being explicitly disabled. Write results to sast/xxe-recon.md. > > Context: You will be given the project's architecture summary. Use it to understand the tech stack, XML libraries in use, and any XML-accepting endpoints. > > What to search for — vulnerable XML parsing patterns: > > Flag any XML parsing call where there is no adjacent, paired hardening (disabling DTD / external entity features). You are not yet tracing whether the input is user-controlled; that is Phase 2's job. > > 1. Python — stdlib parsers (flag unless defusedxml is used as a drop-in): > - xml.etree.ElementTree.parse(...), ET.fromstring(...), ET.iterparse(...) > - xml.dom.minidom.parseString(...), xml.dom.minidom.parse(...) > - xml.sax.parseString(...), xml.sax.parse(...) > - xmltodict.parse(...) (backed by expat — generally safe for entity expansion, but flag for review) > > 2. Python — lxml (flag unless resolve_entities=False and no_network=True are set): > - etree.parse(...), etree.fromstring(...), etree.XML(...) > - etree.XMLParser(...) without resolve_entities=False > - objectify.parse(...), objectify.fromstring(...) > > 3. Java — flag any instantiation of these without the matching hardening features set: > - DocumentBuilderFactory.newInstance()newDocumentBuilder()parse(...) > - SAXParserFactory.newInstance()newSAXParser()parse(...) > - XMLInputFactory.newInstance()createXMLStreamReader(...) > - TransformerFactory.newInstance()newTransformer() used with XML source > - SchemaFactory.newInstance(...)newSchema(...) > - Spring: MarshallingHttpMessageConverter with Jaxb2Marshaller if entity expansion not disabled > > 4. PHP — flag any of these without libxml_disable_entity_loader(true) immediately before (PHP 7.x), or without LIBXML_NONET flag (PHP 8.x): > - simplexml_load_string(...), simplexml_load_file(...) > - DOMDocument::loadXML(...), DOMDocument::load(...) > - xml_parse(...) with xml_parser_create() > - SimpleXMLElement::__construct(...) with raw string > > 5. .NET — flag any of these without DtdProcessing.Prohibit and XmlResolver = null: > - new XmlDocument() followed by .Load(...) or .LoadXml(...) > - new XmlTextReader(...) (legacy — DTD on by default in older .NET) > - XPathDocument(...), XDocument.Load(...), XElement.Load(...) > - XmlReader.Create(...) without XmlReaderSettings { DtdProcessing = DtdProcessing.Prohibit } > > 6. Node.js — flag these libraries when parsing untrusted input: > - libxmljs.parseXmlString(...), libxmljs.parseXml(...) > - node-expat parser instantiation > - sax.createStream(...) / sax.parser(...) — check if entity expansion is used > - xml2js.parseString(...) — generally safe in v0.5+; flag only if explicitArray or other options suggest an older version or entity expansion is re-enabled > > 7. Ruby — flag these when used with options that enable entity expansion: > - Nokogiri::XML(input) { |config| config.noent }noent enables entity substitution > - REXML::Document.new(input) — REXML is vulnerable to entity expansion DoS; check for entity expansion usage > - LibXML::XML::Document.string(input) — check entity options > > 8. Go — flag third-party XML libraries that support entity resolution: > - github.com/beevik/etree usage — check if network/entity resolution is configured > - Standard encoding/xml is generally safe (does not resolve external entities) — flag only if combined with custom entity handling > > What to skip (these are safe patterns — do not flag): > - import defusedxml used as the XML parser (Python) > - etree.XMLParser(resolve_entities=False, no_network=True) (lxml) > - Java DocumentBuilderFactory with disallow-doctype-decl feature set to true > - Java XMLInputFactory with IS_SUPPORTING_EXTERNAL_ENTITIES = false > - .NET XmlReaderSettings { DtdProcessing = DtdProcessing.Prohibit, XmlResolver = null } > - Nokogiri default usage without noent or other entity-expansion options > - Parsing of fully static, bundled, non-user-influenced XML files (e.g. reading config from disk at startup with no user input involved) > > Output format — write to sast/xxe-recon.md: > > ``markdown > # XXE Recon: [Project Name] > > ## Summary > Found [N] XML parsing sites without explicit external entity hardening. > > ## Vulnerable Parsing Sites > > ### 1. [Descriptive name — e.g., "lxml.etree.fromstring without resolve_entities=False in upload handler"] > - **File**: path/to/file.ext (lines X-Y) > - **Function / endpoint**: [function name or route] > - **Parser / library**: [e.g., lxml etree / Java DocumentBuilder / PHP DOMDocument] > - **Missing hardening**: [what protection is absent — e.g., "resolve_entities not set to False", "disallow-doctype-decl feature not set"] > - **Input variable(s)**: var_name — [brief note on what it appears to be, e.g., "HTTP request body" or "file upload content" or "unknown origin"] > - **Code snippet**: > ` > [the XML parsing call and surrounding context] > ` > > [Repeat for each site] > ``

Between Phases: Check Recon Results

After Phase 1 completes, read sast/xxe-recon.md. If the summary states zero vulnerable parsing sites were found (or the file contains no entries under "Vulnerable Parsing Sites"), do not launch Phase 2 or Phase 3. Instead, write the following to sast/xxe-results.md, delete sast/xxe-recon.md, and stop:

No vulnerabilities found.

Only proceed to Phase 2 if at least one vulnerable parsing site was identified in the recon output.

Phase 2: Verify — Trace User Input (Batched)

After Phase 1 completes, read sast/xxe-recon.md and split the entries under "Vulnerable Parsing Sites" into batches of up to 3 sites each (use the numbered ### sections: ### 1., ### 2., etc.). Launch one subagent per batch in parallel. Each subagent traces taint only for its assigned sites and writes results to its own batch file.

Batching procedure (you, the orchestrator, do this — not a subagent):

  1. Read sast/xxe-recon.md and count the numbered site sections (### 1., ### 2., etc.).
  2. Divide them into batches of up to 3. For exa

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.