Safeguard
Application Security•

ASVS 5.0 V1.2.7: Parameterize XPath Queries

ASVS V1.2.7 requires XPath queries to use parameterization or precompiled expressions. See a safe Java and Python pattern and how to test for injection.

Safeguard Security Team
2 min read

ASVS 5.0 V1.2.7 (Level 2) requires that XPath queries are built with query parameterization or precompiled queries, never by pasting user input into the expression text. It is the XML equivalent of using prepared statements for SQL.

Why it matters

If a lookup is //user[name='INPUT' and pass='SECRET'], then an input of ' or '1'='1 turns the condition true for every node (CWE-643). Unlike SQL, XPath has no access control layer, so an injected expression can read the whole document.

How to implement it

Bind variables with a resolver. In Java:

XPath xp = XPathFactory.newInstance().newXPath();
xp.setXPathVariableResolver(name -> {
    if ("name".equals(name.getLocalPart())) return userName;
    throw new IllegalArgumentException("unknown variable");
});
XPathExpression expr = xp.compile("//user[name=$name]/role");
String role = (String) expr.evaluate(doc, XPathConstants.STRING);

In Python with lxml, pass variables as keyword arguments:

roles = tree.xpath("//user[name=$n]/role/text()", n=user_name)

Compile expressions once and reuse them. Where your library has no variable support, move the filtering to code: select all candidate nodes and compare values in the host language.

How to test it

Submit ' or '1'='1, ' or ''=' and x'] | //*[name()='password as the lookup value. The expected result is no match, not extra nodes. Search the codebase for xpath( and evaluate( calls that take concatenated strings.

Common mistakes

  • Escaping single quotes only, which fails when the expression uses double quotes.
  • Passing numeric inputs without casting.
  • Disabling parameterization to support dynamic element names. Use an allowlist for those.

Where this goes wrong in practice

XPath shows up in older SOAP services, XML configuration stores and document search features. Because XML data stores usually have no per user permissions, a successful injection exposes everything in the document, including password hashes or API keys kept in other nodes. Since the exposure is total, parameterizing is worth the small extra effort even in internal tools.

Keep an eye on libraries that offer a convenience method taking a format string, because they feel like parameterization but only substitute text. Check the documentation for words like "variable" or "binding", and run the injection test strings against the real endpoint.

Quick check

What is the XPath equivalent of a prepared statement?

A compiled expression with bound variables, such as $name, supplied through a variable resolver or keyword arguments.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.