skills/xpath-injection-anti-pattern/SKILL.md
Security anti-pattern for XPath injection vulnerabilities (CWE-643). Use when generating or reviewing code that queries XML documents, constructs XPath expressions, or handles user input in XML operations. Detects unescaped quotes and special characters in XPath queries.
npx skillsauth add igbuend/grimbard xpath-injection-anti-patternInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Severity: High
XPath Injection occurs when applications insecurely embed user input into XPath queries without proper escaping or parameterization. XPath is used to navigate and query XML documents. Similar to SQL Injection, attackers can inject special characters into the input, manipulating the XPath query's logic. This can lead to authentication bypass, unauthorized access to sensitive XML data, or information disclosure about the XML document structure.
The anti-pattern is constructing XPath queries by concatenating user-controlled input directly into the XPath string without proper escaping or parameterization.
# VULNERABLE: User input is directly concatenated into an XPath query.
from lxml import etree
# Sample XML document
xml_doc = etree.fromstring('''
<users>
<user>
<name>admin</name>
<password>adminpass</password>
<role>administrator</role>
</user>
<user>
<name>guest</name>
<password>guestpass</password>
<role>user</role>
</user>
</users>
''')
def authenticate_user(username, password):
# The XPath query is constructed using string concatenation.
# Attacker can inject single quotes or boolean logic.
xpath_query = f"//user[name='{username}' and password='{password}']"
# Attacker's input:
# username = "admin' or '1'='1"
# password = "anything"
# Resulting XPath query:
# "//user[name='admin' or '1'='1' and password='anything']"
# This query will bypass authentication and return the 'admin' user,
# as '1'='1' is always true.
found_users = xml_doc.xpath(xpath_query)
return len(found_users) > 0
# Test the vulnerable function
# print(authenticate_user("admin' or '1'='1", "blah")) # Returns True!
# SECURE: Use a parameterization mechanism or escape user input for XPath.
from lxml import etree
xml_doc = etree.fromstring('''
<users>
<user>
<name>admin</name>
<password>adminpass</password>
<role>administrator</role>
</user>
<user>
<name>guest</name>
<password>guestpass</password>
<role>user</role>
</user>
</users>
''')
# lxml (and other libraries) support XPath parameterization.
# This separates the query structure from the user-provided data.
def authenticate_user_secure(username, password):
# Pass parameters separately using a variable binding mechanism.
# The library will handle proper escaping.
xpath_query = "//user[name=$username and password=$password]"
# Define the variables for the XPath expression.
variables = {'username': username, 'password': password}
found_users = xml_doc.xpath(xpath_query, **variables)
return len(found_users) > 0
# Test the secure function
# print(authenticate_user_secure("admin' or '1'='1", "blah")) # Returns False (correctly)
xpath(), evaluate(), selectNodes(), or similar methods in your XML processing library.', ", and, or, comment()) to see if they alter the query's behavior or cause unexpected results.concat() in XPath):def escape_xpath_string(s):
# Handle strings with both quotes using concat()
if "'" in s and '"' in s:
return "concat('" + s.replace("'", "',\"'\",'") + "')"
elif "'" in s:
return '"' + s + '"'
else:
return "'" + s + "'"
development
Security anti-pattern for Cross-Site Scripting vulnerabilities (CWE-79). Use when generating or reviewing code that renders HTML, handles user input in web pages, uses innerHTML/document.write, or builds dynamic web content. Covers Reflected, Stored, and DOM-based XSS. AI code has 86% XSS failure rate.
development
Security anti-pattern for weak password hashing (CWE-327, CWE-759). Use when generating or reviewing code that stores or verifies user passwords. Detects use of MD5, SHA1, SHA256 without salt, or missing password hashing entirely. Recommends bcrypt, Argon2, or scrypt.
development
Security anti-pattern for weak encryption (CWE-326, CWE-327). Use when generating or reviewing code that encrypts data, handles encryption keys, or uses cryptographic modes. Detects DES, ECB mode, static IVs, and custom crypto implementations.
development
Security pattern for self-contained token authentication (e.g., JWT). Use when implementing stateless authentication, designing tokens with embedded claims, or building systems where tokens contain principal information and can be verified without server-side storage. Specialization of Authentication pattern.