XPath injection happens when an application builds an XPath query from unvalidated input, so crafted text changes the query's logic. It can bypass a login or expose parts of an XML document. The fix is a parameterized query, not careful escaping after the fact.
How does it work?
XPath is a query language for XML. Some applications keep users, settings or catalog data in XML files and look things up with XPath. If the query string is assembled by joining text, the user's input becomes part of the query.
OWASP notes that XPath has no access controls at the query level, so an attacker may be able to retrieve an entire XML document, not just one record. That is a sharper edge than SQL, where database permissions can limit what a query reaches.
What does a constructed example look like?
This one is constructed, not from a real incident. A small internal tool checks logins against an XML file of employees. The code concatenates the username and password into a query that looks for an employee node where both match.
An attacker types this as the username, with any password:
blah' or 1=1 or 'a'='a
The quote closes the string early. The 1=1 is always true, and because the conditions are joined with or, only one branch must hold. The password check stops mattering and the query matches every employee node. The login succeeds as the first user in the file, which is often an administrator.
This is the tautology pattern OWASP describes for XPath, and the same shape as classic SQL injection.
What should you look for in code review?
You are looking for strings that build queries. Search the codebase for XPath entry points in your language, such as evaluate, selectNodes, selectSingleNode, xpath( and compile. Then ask three questions at each hit.
- Is any part of the expression built with string concatenation, interpolation or a format call?
- Does any of that text come from a request, a file upload, a message queue or another service?
- Is the result used for an access decision, such as login, role lookup or tenant selection?
A yes to the first two is a finding. A yes to all three is a serious one. Also check error handling. Verbose parser errors that echo the query help an attacker shape the next attempt, so OWASP recommends custom error pages.
How do you fix it?
OWASP lists these defenses, in order of preference.
- Parameterized queries. Precompile the XPath with variables, and supply the user's value as a variable at run time. The query structure is fixed before input is added, so no escaping has to be remembered. Most XPath libraries support variable resolvers. Check yours.
- Escaping. If parameterization is not available, escape untrusted input by replacing the quote character that delimits your values with its XML entity equivalent. This is fragile, since one missed character or one wrong delimiter reopens the hole.
- Input validation. Restrict input to the expected type, such as a string of letters or an integer, and reject the rest. Validation limits damage but should not be the only control.
- Custom error pages. Do not show query text or document structure to users.
Also reconsider the design. Passwords in an XML file checked by query is a smell by itself. Store password hashes made with a slow hashing function, look up the record by a parameterized query, and compare the hash in code.
What to do
- List every XPath call in the codebase.
- Mark any expression built from text that includes outside input.
- Rewrite those with precompiled, parameterized expressions.
- Add unit tests that feed quote characters and
or 1=1style input and assert that the lookup fails. - Keep XML files that hold secrets or credentials out of query based lookups.
- Add a static analysis rule or review checklist line for string built XPath.
Safeguard's SAST scan covers injection patterns in source, which helps with step 1 and step 2. See the SAST code scan demo.
Quick check
Why does the injected condition 1=1 bypass the password check?
Because the conditions are joined with or, only one branch must be true. The always true branch makes the whole query match, so the password never matters.
Is escaping quotes enough?
It helps, but it is fragile. OWASP's preferred defense is a parameterized, precompiled XPath query, with escaping only as a fallback.
Sources
Last reviewed: 18 October 2026.