Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions rules/S8378/javascript/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"title": "DOM XPath queries should not be vulnerable to injection attacks",
"type": "VULNERABILITY",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "5min"
},
"tags": [
"cwe"
],
"securityStandards": {
"CWE": [
20,
643
],
"OWASP": [
"A1"
],
"OWASP Top 10 2021": [
"A3"
],
"PCI DSS 3.2": [
"6.5.1"
],
"PCI DSS 4.0": [
"6.2.4"
],
"ASVS 4.0": [
"5.1.3",
"5.1.4",
"5.3.10"
],
"STIG ASD_V5R3": [
"V-222608",
"V-222609"
]
},
"defaultSeverity": "Minor",
"ruleSpecification": "RSPEC-8378",
"sqKey": "S8378",
"scope": "All",
"defaultQualityProfiles": ["Sonar way"],
"quickfix": "unknown",
"code": {
"impacts": {
"MAINTAINABILITY": "LOW",
"RELIABILITY": "LOW",
"SECURITY": "MEDIUM"
},
"attribute": "TRUSTWORTHY"
}
}
118 changes: 118 additions & 0 deletions rules/S8378/javascript/rule.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@

== Why is this an issue?

DOM-based XPath injection occurs when untrusted user input is directly
incorporated into XPath queries executed on the client side. This vulnerability
allows attackers to manipulate XPath expressions to access unauthorized data, or
extract sensitive information from XML documents processed in the browser.

In the long run, this practice progressively increases the likelihood of
introducing other DOM-based vulnerabilities, such as XSS or open redirects.

== How to fix it

=== Code examples

==== Noncompliant code example

[source,javascript,diff-id=1,diff-type=noncompliant]
----
// User input directly concatenated into XPath query
const userInput = document.getElementById('searchInput').value;
const xpath = "//user[@name='" + userInput + "']";

// Evaluate the XPath expression
const result = document.evaluate(xpath, document, null, // Noncompliant
XPathResult.FIRST_ORDERED_NODE_TYPE, null);
const userNode = result.singleNodeValue;
----

==== Compliant solution

[source,javascript,diff-id=1,diff-type=compliant]
----
// Validate and sanitize user input before use
const userInput = document.getElementById('searchInput').value;

// Option 1: Use allowlist validation
if (!/^[a-zA-Z0-9_]+$/.test(userInput)) {
throw new Error('Invalid input');
}

// Option 2: Escape XPath special characters
function escapeXPath(value) {
if (!value.includes("'")) {
return "'" + value + "'";
}
if (!value.includes('"')) {
return '"' + value + '"';
}
// If both quotes exist, use concat()
return "concat('" + value.replace(/'/g, "',\"'\",'") + "')";
}

const xpath = "//user[@name=" + escapeXPath(userInput) + "]";
const result = document.evaluate(xpath, document, null,
XPathResult.FIRST_ORDERED_NODE_TYPE, null);
const userNode = result.singleNodeValue;
----

=== How does this work?

As a rule of thumb, the best approach to protect against injections is to
systematically ensure that untrusted data cannot break out of the initially
intended logic.

For DOM-based Xpath injection in particular, consider whether XPath is
necessary for your use case, as simpler DOM traversal methods may be sufficient
and safer. For example, DOM manipulation methods like `querySelector()` or
`getElementById()`.

==== Validation

In case XPath parameterized queries are not available, the most secure way to
protect against injections is to validate the input before using it in an XPath
query.

Input can be validated in multiple ways:

* By checking against a list of authorized and secure strings that the application is allowed to use in a query.
* By ensuring user input is restricted to a specific range of characters (e.g., the regex `/^[a-zA-Z0-9]*$/` only allows alphanumeric characters.)
* By ensuring user input does not include any XPath metacharacters, such as `"`, `'`, `/`, `@`, `=`, `*`, `[`, `]`, `(` and `)`.

If user input is not considered valid, it should be rejected as it is unsafe.

In the example, a validation mechanism is applied to untrusted input to ensure
it is strictly composed of alphabetic characters.

== Resources

=== Standards

* OWASP - https://owasp.org/Top10/A03_2021-Injection/[Top 10 2021 Category A3 - Injection]
* OWASP - https://owasp.org/www-project-top-ten/2017/A1_2017-Injection[Top 10 2017 Category A1 - Injection]
* CWE - https://cwe.mitre.org/data/definitions/20[CWE-20 - Improper Input Validation]
* CWE - https://cwe.mitre.org/data/definitions/643[CWE-643 - Improper Neutralization of Data within XPath Expressions]
* STIG Viewer - https://stigviewer.com/stigs/application_security_and_development/2024-12-06/finding/V-222608[Application Security and Development: V-222608] - The application must not be vulnerable to XML-oriented attacks.
* STIG Viewer - https://stigviewer.com/stigs/application_security_and_development/2024-12-06/finding/V-222609[Application Security and Development: V-222609] - The application must not be subject to input handling vulnerabilities.

ifdef::env-github,rspecator-view[]

'''
== Implementation Specification
(visible only on this page)

=== Message

Make sure executing a dynamically formatted template is safe here.

=== Highlighting

* Primary: on the template execution call
* Secondary: on each assignment / format of the template string variable
** message when formatting: "Template is dynamically formatted and assigned to \{variable_name}"
** message for an assignment: "Template is assigned to \{variable_name}"

'''

endif::env-github,rspecator-view[]
2 changes: 2 additions & 0 deletions rules/S8378/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{
}
Loading