Xpath Injection in Axum with Cockroachdb
Xpath Injection in Axum with Cockroachdb — how this specific combination creates or exposes the vulnerability
XPath Injection occurs when an application dynamically constructs XPath expressions using untrusted input without proper sanitization or parameterization. In an Axum application using CockroachDB, this typically arises when building XPath queries in Rust code to query or filter XML data stored in the database. CockroachDB supports XML data types and XPath functions, and if Axum routes or handler code interpolates user-controlled values directly into XPath strings, an attacker can manipulate node selection, bypass authentication checks, or extract sensitive data.
Consider an endpoint in Axum that receives a user ID via query parameters and uses it to select user-specific XML documents from a CockroachDB column:
// UNSAFE: direct string interpolation into XPath
let user_id = req.query_params()["user_id"];
let xpath_expr = format!("/users/user[id='{}']", user_id);
let result = xpath_evaluate(&xml_column, &xpath_expr);
If user_id is supplied by an attacker as ' or 1=1 or ', the resulting XPath becomes /users/user[id='' or 1=1 or ''], which can return all user nodes. In CockroachDB, this could allow an attacker to read XML documents belonging to other users. Additionally, XPath functions like contains() or starts-with() can be abused for blind injection if the application infers results from timing or error behavior. Because Axum does not enforce a strict separation between code and data, developers must explicitly parameterize XPath inputs. The combination of Axum’s routing flexibility, Rust’s string handling, and CockroachDB’s XML/XPath support creates a scenario where unchecked concatenation leads to injection.
Another common pattern involves using XPath to enforce role-based access control over XML documents. For example, an application might construct an XPath to verify that a user owns a resource:
// UNSAFE: role-based XPath construction
let role = req.query_params()["role"];
let access_xpath = format!("/resources/resource[role='{}' and owner='{}']", role, user_id);
An attacker supplying role as admin or '1'='1 can bypass intended authorization checks. Since Cockroachdb stores the XML payloads and Axum evaluates the XPath at runtime, malicious input can change the logical structure of the query. This specific stack does not introduce a unique vulnerability, but it amplifies risk when secure coding practices are omitted. Mitigations include using parameterized XPath APIs when available, validating input against strict patterns, and avoiding dynamic concatenation entirely.
Cockroachdb-Specific Remediation in Axum — concrete code fixes
To prevent XPath Injection in an Axum application with CockroachDB, prefer parameterized approaches and strict input validation. CockroachDB does not expose a native parameterized XPath API in SQL, so the safest strategy is to avoid constructing XPath expressions from untrusted input. Instead, filter data using SQL predicates and retrieve full XML documents, then process them in Rust using a safe XML library that supports parameterized queries.
1. Use SQL filtering instead of dynamic XPath: Move filtering logic into SQL WHERE clauses, which support parameterized queries. This removes XPath injection surface entirely.
// Safe: parameterized SQL query
let user_id = req.query_params()["user_id"];
let sql = "SELECT xml_data FROM user_resources WHERE id = $1 AND (xpath('/users/user/id', xml_data))[1]::text = $2";
let row = db_client.query_one(&sql, &[&user_id, &expected_id]).await?;
Here, db_client represents a CockroachDB connection pool. The XPath evaluation is performed on the retrieved XML column using a Rust XML library, while SQL handles authentication and row selection with bound parameters.
2. Validate and restrict input patterns: If XPath must be used, strictly validate input against an allowlist (e.g., alphanumeric user IDs) and encode special characters.
// Safe: strict validation before any XPath usage
let user_id = req.query_params()["user_id"];
if !USER_ID_REGEX.is_match(user_id) {
return Err(Error::bad_request("invalid user_id"));
}
// Use a dedicated XML library that supports namespace-aware, parameterized evaluation
let safe_xpath = format!("/users/user[id='{}']", escaping::escape_xml(user_id));
let result = xpath_evaluate_safe(&xml_column, &safe_xpath);
3. Use Rust XML libraries with explicit parameterization: Libraries like roxmltree or xml-rs allow traversing parsed documents without string-based XPath construction. Parse the XML once, then navigate with safe APIs.
// Safe: parse and traverse without dynamic XPath
let doc = roxmltree::Document::parse(&xml_column)?;
for node in doc.descendants() {
if node.has_tag_name("user") {
let id = node.attribute("id");
if id == Some(user_id) { /* process safely */ }
}
}
By combining CockroachDB’s SQL parameterization with careful XML processing in Rust, Axum applications can avoid XPath Injection while retaining the ability to work with structured XML data. Defense in depth includes logging suspicious inputs, applying least-privilege database permissions, and regularly scanning with middleBrick to detect accidental exposure of XML endpoints in the unauthenticated attack surface.