mirror of
https://github.com/github/codeql.git
synced 2026-07-08 21:15:32 +02:00
Compare commits
20 Commits
codeql-cli
...
copilot/ad
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a820776f7c | ||
|
|
125fe7b2fa | ||
|
|
37c61982b8 | ||
|
|
8e1a7e1789 | ||
|
|
ecfd19c506 | ||
|
|
578c8a2c01 | ||
|
|
4f4271d1f2 | ||
|
|
ae5896416e | ||
|
|
a322744ee2 | ||
|
|
3523670dd0 | ||
|
|
2f3bd41216 | ||
|
|
c3bbe94501 | ||
|
|
71942b54b3 | ||
|
|
975843889a | ||
|
|
0cb077cd66 | ||
|
|
bd195e59a5 | ||
|
|
6f64839305 | ||
|
|
dce8bcdf2b | ||
|
|
eb4d30de7f | ||
|
|
65f74635ca |
@@ -19,6 +19,7 @@ ql/rust/ql/src/queries/security/CWE-312/CleartextStorageDatabase.ql
|
||||
ql/rust/ql/src/queries/security/CWE-319/UseOfHttp.ql
|
||||
ql/rust/ql/src/queries/security/CWE-327/BrokenCryptoAlgorithm.ql
|
||||
ql/rust/ql/src/queries/security/CWE-327/WeakSensitiveDataHashing.ql
|
||||
ql/rust/ql/src/queries/security/CWE-611/Xxe.ql
|
||||
ql/rust/ql/src/queries/security/CWE-614/InsecureCookie.ql
|
||||
ql/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.ql
|
||||
ql/rust/ql/src/queries/security/CWE-798/HardcodedCryptographicValue.ql
|
||||
|
||||
@@ -20,6 +20,7 @@ ql/rust/ql/src/queries/security/CWE-312/CleartextStorageDatabase.ql
|
||||
ql/rust/ql/src/queries/security/CWE-319/UseOfHttp.ql
|
||||
ql/rust/ql/src/queries/security/CWE-327/BrokenCryptoAlgorithm.ql
|
||||
ql/rust/ql/src/queries/security/CWE-327/WeakSensitiveDataHashing.ql
|
||||
ql/rust/ql/src/queries/security/CWE-611/Xxe.ql
|
||||
ql/rust/ql/src/queries/security/CWE-614/InsecureCookie.ql
|
||||
ql/rust/ql/src/queries/security/CWE-696/BadCtorInitialization.ql
|
||||
ql/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.ql
|
||||
|
||||
@@ -20,6 +20,7 @@ ql/rust/ql/src/queries/security/CWE-312/CleartextStorageDatabase.ql
|
||||
ql/rust/ql/src/queries/security/CWE-319/UseOfHttp.ql
|
||||
ql/rust/ql/src/queries/security/CWE-327/BrokenCryptoAlgorithm.ql
|
||||
ql/rust/ql/src/queries/security/CWE-327/WeakSensitiveDataHashing.ql
|
||||
ql/rust/ql/src/queries/security/CWE-611/Xxe.ql
|
||||
ql/rust/ql/src/queries/security/CWE-614/InsecureCookie.ql
|
||||
ql/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.ql
|
||||
ql/rust/ql/src/queries/security/CWE-798/HardcodedCryptographicValue.ql
|
||||
|
||||
16
rust/ql/lib/codeql/rust/frameworks/libxml.model.yml
Normal file
16
rust/ql/lib/codeql/rust/frameworks/libxml.model.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/rust-all
|
||||
extensible: sinkModel
|
||||
data:
|
||||
- ["libxml::bindings::xmlReadFile", "Argument[0].Reference", "xxe", "manual"]
|
||||
- ["libxml::bindings::xmlCtxtReadFile", "Argument[1].Reference", "xxe", "manual"]
|
||||
- ["libxml::bindings::xmlReadDoc", "Argument[0].Reference", "xxe", "manual"]
|
||||
- ["libxml::bindings::xmlCtxtReadDoc", "Argument[1].Reference", "xxe", "manual"]
|
||||
- ["libxml::bindings::xmlReadFd", "Argument[0]", "xxe", "manual"]
|
||||
- ["libxml::bindings::xmlCtxtReadFd", "Argument[1]", "xxe", "manual"]
|
||||
- ["libxml::bindings::xmlReadMemory", "Argument[0].Reference", "xxe", "manual"]
|
||||
- ["libxml::bindings::xmlCtxtReadMemory", "Argument[1].Reference", "xxe", "manual"]
|
||||
- ["libxml::bindings::xmlReadIO", "Argument[0].Reference", "xxe", "manual"]
|
||||
- ["libxml::bindings::xmlCtxtReadIO", "Argument[1].Reference", "xxe", "manual"]
|
||||
- ["libxml::bindings::xmlParseInNodeContext", "Argument[1].Reference", "xxe", "manual"]
|
||||
@@ -126,6 +126,8 @@ extensions:
|
||||
# Str
|
||||
- ["<core::str>::as_str", "Argument[self].Reference", "ReturnValue.Reference", "taint", "manual"]
|
||||
- ["<core::str>::as_bytes", "Argument[self].Reference", "ReturnValue.Reference", "taint", "manual"]
|
||||
- ["<core::str>::as_ptr", "Argument[self].Reference", "ReturnValue.Reference", "taint", "manual"]
|
||||
- ["<core::str>::as_mut_ptr", "Argument[self].Reference", "ReturnValue.Reference", "taint", "manual"]
|
||||
- ["<core::str>::parse", "Argument[self].Reference", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<core::str>::trim", "Argument[self].Reference", "ReturnValue.Reference", "taint", "manual"]
|
||||
- ["<core::str>::to_string", "Argument[self].Reference", "ReturnValue", "taint", "manual"]
|
||||
|
||||
110
rust/ql/lib/codeql/rust/security/XxeExtensions.qll
Normal file
110
rust/ql/lib/codeql/rust/security/XxeExtensions.qll
Normal file
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* Provides classes and predicates to reason about XML external entity (XXE)
|
||||
* vulnerabilities.
|
||||
*/
|
||||
|
||||
import rust
|
||||
private import codeql.rust.dataflow.DataFlow
|
||||
private import codeql.rust.dataflow.FlowBarrier
|
||||
private import codeql.rust.dataflow.FlowSink
|
||||
private import codeql.rust.Concepts
|
||||
private import codeql.rust.dataflow.internal.Node as Node
|
||||
|
||||
/**
|
||||
* Provides default sources, sinks and barriers for detecting XML external
|
||||
* entity (XXE) vulnerabilities, as well as extension points for adding your
|
||||
* own.
|
||||
*/
|
||||
module Xxe {
|
||||
/**
|
||||
* A data flow source for XXE vulnerabilities.
|
||||
*/
|
||||
abstract class Source extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A data flow sink for XXE vulnerabilities.
|
||||
*/
|
||||
abstract class Sink extends QuerySink::Range {
|
||||
override string getSinkType() { result = "Xxe" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A barrier for XXE vulnerabilities.
|
||||
*/
|
||||
abstract class Barrier extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* An active threat-model source, considered as a flow source.
|
||||
*/
|
||||
private class ActiveThreatModelSourceAsSource extends Source, ActiveThreatModelSource { }
|
||||
|
||||
/**
|
||||
* A sink for XXE from model data.
|
||||
*/
|
||||
private class ModelsAsDataSink extends Sink {
|
||||
ModelsAsDataSink() {
|
||||
exists(Call call |
|
||||
// an XML parse call
|
||||
sinkNode(this, "xxe") and
|
||||
call = this.(Node::FlowSummaryNode).getSinkElement().getCall() and
|
||||
// with an unsafe option
|
||||
hasXxeOption(call.getAnArgument(), _)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A heuristic sink for XXE.
|
||||
*/
|
||||
private class HeuristicSink extends Sink {
|
||||
HeuristicSink() {
|
||||
exists(Call call |
|
||||
// a call that looks it might do XML parsing (this is broad)
|
||||
call.getStaticTarget().getName().getText().regexpMatch("(?i).*(xml|parse).*") and
|
||||
// with an unsafe option; we require the option to be named (e.g. `XML_PARSE_NOENT`), not a literal value
|
||||
// (e.g. `2`), to provide additional confidence that we're actually looking at XML parsing)
|
||||
hasXxeOption(call.getAnArgument(), true) and
|
||||
// the sink is any input argument
|
||||
this.asExpr() = call.getAnArgument() and
|
||||
// don't duplicate modeled sinks
|
||||
not exists(ModelsAsDataSink s | s.(Node::FlowSummaryNode).getSinkElement().getCall() = call)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A barrier for XXE vulnerabilities from model data.
|
||||
*/
|
||||
private class ModelsAsDataBarrier extends Barrier {
|
||||
ModelsAsDataBarrier() { barrierNode(this, "xxe") }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e` is an expression that includes an unsafe `xmlParserOption`,
|
||||
* specifically `XML_PARSE_NOENT` (value 2, enables entity substitution) or
|
||||
* `XML_PARSE_DTDLOAD` (value 4, loads external DTD subsets).
|
||||
*
|
||||
* `named` is true if the expression is a named constant, false if it is an
|
||||
* integer literal.
|
||||
*/
|
||||
private predicate hasXxeOption(Expr e, boolean named) {
|
||||
// named constant XML_PARSE_NOENT or XML_PARSE_DTDLOAD (or very similar)
|
||||
e.(PathExpr).getPath().getText().matches(["%_PARSE_NOENT", "%_PARSE_DTDLOAD"]) and
|
||||
named = true
|
||||
or
|
||||
// integer literal with XML_PARSE_NOENT (bit 1) or XML_PARSE_DTDLOAD (bit 2) set
|
||||
exists(string value |
|
||||
e.(IntegerLiteralExpr).getTextValue() = value + concat(e.(IntegerLiteralExpr).getSuffix()) and
|
||||
value.toInt().bitAnd(6) != 0 // 6 = 2 | 4 = XML_PARSE_NOENT | XML_PARSE_DTDLOAD
|
||||
) and
|
||||
named = false
|
||||
or
|
||||
// bitwise OR expression
|
||||
hasXxeOption(e.(BinaryExpr).getLhs(), named)
|
||||
or
|
||||
hasXxeOption(e.(BinaryExpr).getRhs(), named)
|
||||
or
|
||||
// cast expression (e.g., `XML_PARSE_NOENT as i32`)
|
||||
hasXxeOption(e.(CastExpr).getExpr(), named)
|
||||
}
|
||||
4
rust/ql/src/change-notes/2026-02-20-xxe.md
Normal file
4
rust/ql/src/change-notes/2026-02-20-xxe.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: newQuery
|
||||
---
|
||||
* Added a new query, `rust/xxe`, to detect XML external entity (XXE) vulnerabilities in Rust code that uses the `libxml` crate (bindings to C's `libxml2`). The query flags calls to `libxml2` parsing functions with unsafe options (`XML_PARSE_NOENT` or `XML_PARSE_DTDLOAD`) when the XML input comes from a user-controlled source.
|
||||
50
rust/ql/src/queries/security/CWE-611/Xxe.qhelp
Normal file
50
rust/ql/src/queries/security/CWE-611/Xxe.qhelp
Normal file
@@ -0,0 +1,50 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Parsing XML input with external entity (XXE) expansion enabled while the input
|
||||
is controlled by a user can lead to a variety of attacks. An attacker who
|
||||
controls the XML input may be able to use an XML external entity declaration
|
||||
to read the contents of arbitrary files from the server's file system, perform
|
||||
server-side request forgery (SSRF), or perform denial-of-service attacks.
|
||||
</p>
|
||||
<p>
|
||||
The Rust <code>libxml</code> crate (bindings to C's <code>libxml2</code>
|
||||
library) exposes several XML parsing functions that accept a parser options
|
||||
argument. The options <code>XML_PARSE_NOENT</code> and
|
||||
<code>XML_PARSE_DTDLOAD</code> enable external entity expansion and loading of
|
||||
external DTD subsets, respectively. Enabling these options when parsing
|
||||
user-controlled XML is dangerous.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Do not enable <code>XML_PARSE_NOENT</code> or <code>XML_PARSE_DTDLOAD</code>
|
||||
when parsing user-controlled XML. Parse XML with safe options (for example,
|
||||
using <code>0</code> as the options argument) to disable external entity
|
||||
expansion.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
In the following example, the program reads an XML document supplied by the
|
||||
user and parses it with external entity expansion enabled:
|
||||
</p>
|
||||
<sample src="examples/XxeBad.rs"/>
|
||||
<p>
|
||||
The following example shows a corrected version that parses with safe options:
|
||||
</p>
|
||||
<sample src="examples/XxeGood.rs"/>
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>OWASP: <a href="https://owasp.org/www-community/vulnerabilities/XML_External_Entity_(XXE)_Processing">XML External Entity (XXE) Processing</a>.</li>
|
||||
<li>CWE: <a href="https://cwe.mitre.org/data/definitions/611.html">CWE-611: Improper Restriction of XML External Entity Reference</a>.</li>
|
||||
</references>
|
||||
|
||||
</qhelp>
|
||||
52
rust/ql/src/queries/security/CWE-611/Xxe.ql
Normal file
52
rust/ql/src/queries/security/CWE-611/Xxe.ql
Normal file
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* @name XML external entity expansion
|
||||
* @description Parsing user-controlled XML with external entity expansion
|
||||
* enabled may lead to disclosure of confidential data or
|
||||
* server-side request forgery.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 9.1
|
||||
* @precision high
|
||||
* @id rust/xxe
|
||||
* @tags security
|
||||
* external/cwe/cwe-611
|
||||
* external/cwe/cwe-776
|
||||
* external/cwe/cwe-827
|
||||
*/
|
||||
|
||||
import rust
|
||||
import codeql.rust.dataflow.DataFlow
|
||||
import codeql.rust.dataflow.TaintTracking
|
||||
import codeql.rust.security.XxeExtensions
|
||||
|
||||
/**
|
||||
* A taint configuration for user-controlled data reaching an XML parser with
|
||||
* external entity expansion enabled.
|
||||
*/
|
||||
module XxeConfig implements DataFlow::ConfigSig {
|
||||
import Xxe
|
||||
|
||||
predicate isSource(DataFlow::Node node) { node instanceof Source }
|
||||
|
||||
predicate isSink(DataFlow::Node node) { node instanceof Sink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node barrier) { barrier instanceof Barrier }
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
// we need flow through casts as a *value* step, not just the default taint step,
|
||||
// to get flow on reference content when the pointer itself is cast.
|
||||
pred.asExpr() = succ.asExpr().(CastExpr).getExpr()
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
}
|
||||
|
||||
module XxeFlow = TaintTracking::Global<XxeConfig>;
|
||||
|
||||
import XxeFlow::PathGraph
|
||||
|
||||
from XxeFlow::PathNode sourceNode, XxeFlow::PathNode sinkNode
|
||||
where XxeFlow::flowPath(sourceNode, sinkNode)
|
||||
select sinkNode.getNode(), sourceNode, sinkNode,
|
||||
"XML parsing depends on a $@ without guarding against external entity expansion.",
|
||||
sourceNode.getNode(), "user-provided value"
|
||||
16
rust/ql/src/queries/security/CWE-611/examples/XxeBad.rs
Normal file
16
rust/ql/src/queries/security/CWE-611/examples/XxeBad.rs
Normal file
@@ -0,0 +1,16 @@
|
||||
use libxml::bindings::{xmlReadMemory, XML_PARSE_NOENT};
|
||||
use std::ffi::CString;
|
||||
|
||||
fn parse_user_xml(user_input: &str) {
|
||||
let c_input = CString::new(user_input).unwrap();
|
||||
// BAD: external entity expansion is enabled via XML_PARSE_NOENT
|
||||
unsafe {
|
||||
xmlReadMemory(
|
||||
c_input.as_ptr(),
|
||||
c_input.as_bytes().len() as i32,
|
||||
std::ptr::null(),
|
||||
std::ptr::null(),
|
||||
XML_PARSE_NOENT as i32,
|
||||
);
|
||||
}
|
||||
}
|
||||
16
rust/ql/src/queries/security/CWE-611/examples/XxeGood.rs
Normal file
16
rust/ql/src/queries/security/CWE-611/examples/XxeGood.rs
Normal file
@@ -0,0 +1,16 @@
|
||||
use libxml::bindings::xmlReadMemory;
|
||||
use std::ffi::CString;
|
||||
|
||||
fn parse_user_xml(user_input: &str) {
|
||||
let c_input = CString::new(user_input).unwrap();
|
||||
// GOOD: safe options (0) disable external entity expansion
|
||||
unsafe {
|
||||
xmlReadMemory(
|
||||
c_input.as_ptr(),
|
||||
c_input.as_bytes().len() as i32,
|
||||
std::ptr::null(),
|
||||
std::ptr::null(),
|
||||
0,
|
||||
);
|
||||
}
|
||||
}
|
||||
234
rust/ql/test/query-tests/security/CWE-611/Cargo.lock
generated
Normal file
234
rust/ql/test/query-tests/security/CWE-611/Cargo.lock
generated
Normal file
@@ -0,0 +1,234 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.72.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"itertools",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
|
||||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"libc",
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.186"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libxml"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3e969617eea4e728856e3629229ed5ee92aa0b0a8cc2b7b42171b8a9ba4916e"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4"
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.46"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "2.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.118"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"libxml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
231
rust/ql/test/query-tests/security/CWE-611/Xxe.expected
Normal file
231
rust/ql/test/query-tests/security/CWE-611/Xxe.expected
Normal file
@@ -0,0 +1,231 @@
|
||||
#select
|
||||
| main.rs:9:5:9:27 | ...::xmlReadMemory | main.rs:120:20:120:33 | ...::args | main.rs:9:5:9:27 | ...::xmlReadMemory | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:120:20:120:33 | ...::args | user-provided value |
|
||||
| main.rs:14:5:14:27 | ...::xmlReadMemory | main.rs:120:20:120:33 | ...::args | main.rs:14:5:14:27 | ...::xmlReadMemory | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:120:20:120:33 | ...::args | user-provided value |
|
||||
| main.rs:19:5:19:27 | ...::xmlReadMemory | main.rs:120:20:120:33 | ...::args | main.rs:19:5:19:27 | ...::xmlReadMemory | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:120:20:120:33 | ...::args | user-provided value |
|
||||
| main.rs:24:5:24:25 | ...::xmlReadFile | main.rs:121:25:121:38 | ...::args | main.rs:24:5:24:25 | ...::xmlReadFile | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:121:25:121:38 | ...::args | user-provided value |
|
||||
| main.rs:29:5:29:24 | ...::xmlReadDoc | main.rs:120:20:120:33 | ...::args | main.rs:29:5:29:24 | ...::xmlReadDoc | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:120:20:120:33 | ...::args | user-provided value |
|
||||
| main.rs:34:5:34:23 | ...::xmlReadFd | main.rs:122:21:122:39 | ...::open | main.rs:34:5:34:23 | ...::xmlReadFd | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:122:21:122:39 | ...::open | user-provided value |
|
||||
| main.rs:39:5:39:29 | ...::xmlCtxtReadFile | main.rs:121:25:121:38 | ...::args | main.rs:39:5:39:29 | ...::xmlCtxtReadFile | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:121:25:121:38 | ...::args | user-provided value |
|
||||
| main.rs:44:5:44:28 | ...::xmlCtxtReadDoc | main.rs:120:20:120:33 | ...::args | main.rs:44:5:44:28 | ...::xmlCtxtReadDoc | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:120:20:120:33 | ...::args | user-provided value |
|
||||
| main.rs:49:5:49:31 | ...::xmlCtxtReadMemory | main.rs:120:20:120:33 | ...::args | main.rs:49:5:49:31 | ...::xmlCtxtReadMemory | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:120:20:120:33 | ...::args | user-provided value |
|
||||
| main.rs:61:5:61:27 | ...::xmlReadMemory | main.rs:120:20:120:33 | ...::args | main.rs:61:5:61:27 | ...::xmlReadMemory | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:120:20:120:33 | ...::args | user-provided value |
|
||||
| main.rs:64:5:64:27 | ...::xmlReadMemory | main.rs:120:20:120:33 | ...::args | main.rs:64:5:64:27 | ...::xmlReadMemory | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:120:20:120:33 | ...::args | user-provided value |
|
||||
| main.rs:111:23:111:30 | user_xml | main.rs:120:20:120:33 | ...::args | main.rs:111:23:111:30 | user_xml | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:120:20:120:33 | ...::args | user-provided value |
|
||||
| main.rs:112:23:112:30 | user_xml | main.rs:120:20:120:33 | ...::args | main.rs:112:23:112:30 | user_xml | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:120:20:120:33 | ...::args | user-provided value |
|
||||
| main.rs:113:23:113:30 | user_xml | main.rs:120:20:120:33 | ...::args | main.rs:113:23:113:30 | user_xml | XML parsing depends on a $@ without guarding against external entity expansion. | main.rs:120:20:120:33 | ...::args | user-provided value |
|
||||
edges
|
||||
| main.rs:7:32:7:45 | ...: ... [&ref] | main.rs:9:29:9:36 | user_xml [&ref] | provenance | |
|
||||
| main.rs:9:29:9:36 | user_xml [&ref] | main.rs:9:29:9:45 | user_xml.as_ptr() [&ref] | provenance | MaD:15 |
|
||||
| main.rs:9:29:9:45 | user_xml.as_ptr() [&ref] | main.rs:9:29:9:62 | ... as ... | provenance | |
|
||||
| main.rs:9:29:9:45 | user_xml.as_ptr() [&ref] | main.rs:9:29:9:62 | ... as ... | provenance | Config |
|
||||
| main.rs:9:29:9:62 | ... as ... | main.rs:9:5:9:27 | ...::xmlReadMemory | provenance | MaD:7 Sink:MaD:7 |
|
||||
| main.rs:12:34:12:47 | ...: ... [&ref] | main.rs:14:29:14:36 | user_xml [&ref] | provenance | |
|
||||
| main.rs:14:29:14:36 | user_xml [&ref] | main.rs:14:29:14:45 | user_xml.as_ptr() [&ref] | provenance | MaD:15 |
|
||||
| main.rs:14:29:14:45 | user_xml.as_ptr() [&ref] | main.rs:14:29:14:62 | ... as ... | provenance | |
|
||||
| main.rs:14:29:14:45 | user_xml.as_ptr() [&ref] | main.rs:14:29:14:62 | ... as ... | provenance | Config |
|
||||
| main.rs:14:29:14:62 | ... as ... | main.rs:14:5:14:27 | ...::xmlReadMemory | provenance | MaD:7 Sink:MaD:7 |
|
||||
| main.rs:17:35:17:48 | ...: ... [&ref] | main.rs:19:29:19:36 | user_xml [&ref] | provenance | |
|
||||
| main.rs:19:29:19:36 | user_xml [&ref] | main.rs:19:29:19:45 | user_xml.as_ptr() [&ref] | provenance | MaD:15 |
|
||||
| main.rs:19:29:19:45 | user_xml.as_ptr() [&ref] | main.rs:19:29:19:62 | ... as ... | provenance | |
|
||||
| main.rs:19:29:19:45 | user_xml.as_ptr() [&ref] | main.rs:19:29:19:62 | ... as ... | provenance | Config |
|
||||
| main.rs:19:29:19:62 | ... as ... | main.rs:19:5:19:27 | ...::xmlReadMemory | provenance | MaD:7 Sink:MaD:7 |
|
||||
| main.rs:22:34:22:52 | ...: ... [&ref] | main.rs:24:27:24:39 | user_filename [&ref] | provenance | |
|
||||
| main.rs:24:27:24:39 | user_filename [&ref] | main.rs:24:27:24:48 | user_filename.as_ptr() [&ref] | provenance | MaD:15 |
|
||||
| main.rs:24:27:24:48 | user_filename.as_ptr() [&ref] | main.rs:24:27:24:65 | ... as ... | provenance | |
|
||||
| main.rs:24:27:24:48 | user_filename.as_ptr() [&ref] | main.rs:24:27:24:65 | ... as ... | provenance | Config |
|
||||
| main.rs:24:27:24:65 | ... as ... | main.rs:24:5:24:25 | ...::xmlReadFile | provenance | MaD:6 Sink:MaD:6 |
|
||||
| main.rs:27:33:27:46 | ...: ... [&ref] | main.rs:29:26:29:33 | user_xml [&ref] | provenance | |
|
||||
| main.rs:29:26:29:33 | user_xml [&ref] | main.rs:29:26:29:42 | user_xml.as_ptr() [&ref] | provenance | MaD:15 |
|
||||
| main.rs:29:26:29:42 | user_xml.as_ptr() [&ref] | main.rs:29:26:29:60 | ... as ... | provenance | |
|
||||
| main.rs:29:26:29:42 | user_xml.as_ptr() [&ref] | main.rs:29:26:29:60 | ... as ... | provenance | Config |
|
||||
| main.rs:29:26:29:60 | ... as ... | main.rs:29:5:29:24 | ...::xmlReadDoc | provenance | MaD:4 Sink:MaD:4 |
|
||||
| main.rs:32:32:32:43 | ...: i32 [&ref] | main.rs:34:25:34:31 | user_fd [&ref] | provenance | |
|
||||
| main.rs:34:25:34:31 | user_fd [&ref] | main.rs:34:5:34:23 | ...::xmlReadFd | provenance | MaD:5 Sink:MaD:5 |
|
||||
| main.rs:37:39:37:57 | ...: ... [&ref] | main.rs:39:53:39:65 | user_filename [&ref] | provenance | |
|
||||
| main.rs:39:53:39:65 | user_filename [&ref] | main.rs:39:53:39:74 | user_filename.as_ptr() [&ref] | provenance | MaD:15 |
|
||||
| main.rs:39:53:39:74 | user_filename.as_ptr() [&ref] | main.rs:39:53:39:91 | ... as ... | provenance | |
|
||||
| main.rs:39:53:39:74 | user_filename.as_ptr() [&ref] | main.rs:39:53:39:91 | ... as ... | provenance | Config |
|
||||
| main.rs:39:53:39:91 | ... as ... | main.rs:39:5:39:29 | ...::xmlCtxtReadFile | provenance | MaD:2 Sink:MaD:2 |
|
||||
| main.rs:42:38:42:51 | ...: ... [&ref] | main.rs:44:52:44:59 | user_xml [&ref] | provenance | |
|
||||
| main.rs:44:52:44:59 | user_xml [&ref] | main.rs:44:52:44:68 | user_xml.as_ptr() [&ref] | provenance | MaD:15 |
|
||||
| main.rs:44:52:44:68 | user_xml.as_ptr() [&ref] | main.rs:44:52:44:86 | ... as ... | provenance | |
|
||||
| main.rs:44:52:44:68 | user_xml.as_ptr() [&ref] | main.rs:44:52:44:86 | ... as ... | provenance | Config |
|
||||
| main.rs:44:52:44:86 | ... as ... | main.rs:44:5:44:28 | ...::xmlCtxtReadDoc | provenance | MaD:1 Sink:MaD:1 |
|
||||
| main.rs:47:41:47:54 | ...: ... [&ref] | main.rs:51:9:51:16 | user_xml [&ref] | provenance | |
|
||||
| main.rs:51:9:51:16 | user_xml [&ref] | main.rs:51:9:51:25 | user_xml.as_ptr() [&ref] | provenance | MaD:15 |
|
||||
| main.rs:51:9:51:25 | user_xml.as_ptr() [&ref] | main.rs:51:9:51:42 | ... as ... | provenance | |
|
||||
| main.rs:51:9:51:25 | user_xml.as_ptr() [&ref] | main.rs:51:9:51:42 | ... as ... | provenance | Config |
|
||||
| main.rs:51:9:51:42 | ... as ... | main.rs:49:5:49:31 | ...::xmlCtxtReadMemory | provenance | MaD:3 Sink:MaD:3 |
|
||||
| main.rs:59:33:59:46 | ...: ... [&ref] | main.rs:61:29:61:36 | user_xml [&ref] | provenance | |
|
||||
| main.rs:59:33:59:46 | ...: ... [&ref] | main.rs:64:29:64:36 | user_xml [&ref] | provenance | |
|
||||
| main.rs:61:29:61:36 | user_xml [&ref] | main.rs:61:29:61:45 | user_xml.as_ptr() [&ref] | provenance | MaD:15 |
|
||||
| main.rs:61:29:61:45 | user_xml.as_ptr() [&ref] | main.rs:61:29:61:62 | ... as ... | provenance | |
|
||||
| main.rs:61:29:61:45 | user_xml.as_ptr() [&ref] | main.rs:61:29:61:62 | ... as ... | provenance | Config |
|
||||
| main.rs:61:29:61:62 | ... as ... | main.rs:61:5:61:27 | ...::xmlReadMemory | provenance | MaD:7 Sink:MaD:7 |
|
||||
| main.rs:64:29:64:36 | user_xml [&ref] | main.rs:64:29:64:45 | user_xml.as_ptr() [&ref] | provenance | MaD:15 |
|
||||
| main.rs:64:29:64:45 | user_xml.as_ptr() [&ref] | main.rs:64:29:64:62 | ... as ... | provenance | |
|
||||
| main.rs:64:29:64:45 | user_xml.as_ptr() [&ref] | main.rs:64:29:64:62 | ... as ... | provenance | Config |
|
||||
| main.rs:64:29:64:62 | ... as ... | main.rs:64:5:64:27 | ...::xmlReadMemory | provenance | MaD:7 Sink:MaD:7 |
|
||||
| main.rs:109:23:109:36 | ...: ... [&ref] | main.rs:111:23:111:30 | user_xml | provenance | |
|
||||
| main.rs:109:23:109:36 | ...: ... [&ref] | main.rs:112:23:112:30 | user_xml | provenance | |
|
||||
| main.rs:109:23:109:36 | ...: ... [&ref] | main.rs:113:23:113:30 | user_xml | provenance | |
|
||||
| main.rs:120:9:120:16 | user_xml | main.rs:126:31:126:38 | user_xml | provenance | |
|
||||
| main.rs:120:9:120:16 | user_xml | main.rs:127:33:127:40 | user_xml | provenance | |
|
||||
| main.rs:120:9:120:16 | user_xml | main.rs:128:34:128:41 | user_xml | provenance | |
|
||||
| main.rs:120:9:120:16 | user_xml | main.rs:130:32:130:39 | user_xml | provenance | |
|
||||
| main.rs:120:9:120:16 | user_xml | main.rs:133:37:133:44 | user_xml | provenance | |
|
||||
| main.rs:120:9:120:16 | user_xml | main.rs:134:40:134:47 | user_xml | provenance | |
|
||||
| main.rs:120:9:120:16 | user_xml | main.rs:135:32:135:39 | user_xml | provenance | |
|
||||
| main.rs:120:9:120:16 | user_xml | main.rs:139:29:139:36 | user_xml | provenance | |
|
||||
| main.rs:120:20:120:33 | ...::args | main.rs:120:20:120:35 | ...::args(...) [element] | provenance | Src:MaD:9 |
|
||||
| main.rs:120:20:120:35 | ...::args(...) [element] | main.rs:120:20:120:42 | ... .nth(...) [Some] | provenance | MaD:10 |
|
||||
| main.rs:120:20:120:42 | ... .nth(...) [Some] | main.rs:120:20:120:62 | ... .unwrap_or_default() | provenance | MaD:13 |
|
||||
| main.rs:120:20:120:62 | ... .unwrap_or_default() | main.rs:120:9:120:16 | user_xml | provenance | |
|
||||
| main.rs:121:9:121:21 | user_filename | main.rs:129:33:129:45 | user_filename | provenance | |
|
||||
| main.rs:121:9:121:21 | user_filename | main.rs:132:38:132:50 | user_filename | provenance | |
|
||||
| main.rs:121:25:121:38 | ...::args | main.rs:121:25:121:40 | ...::args(...) [element] | provenance | Src:MaD:9 |
|
||||
| main.rs:121:25:121:40 | ...::args(...) [element] | main.rs:121:25:121:47 | ... .nth(...) [Some] | provenance | MaD:10 |
|
||||
| main.rs:121:25:121:47 | ... .nth(...) [Some] | main.rs:121:25:121:67 | ... .unwrap_or_default() | provenance | MaD:13 |
|
||||
| main.rs:121:25:121:67 | ... .unwrap_or_default() | main.rs:121:9:121:21 | user_filename | provenance | |
|
||||
| main.rs:122:9:122:17 | user_file [Some] | main.rs:123:19:123:27 | user_file [Some] | provenance | |
|
||||
| main.rs:122:21:122:39 | ...::open | main.rs:122:21:122:55 | ...::open(...) [Ok] | provenance | Src:MaD:8 |
|
||||
| main.rs:122:21:122:55 | ...::open(...) [Ok] | main.rs:122:21:122:60 | ... .ok() [Some] | provenance | MaD:14 |
|
||||
| main.rs:122:21:122:60 | ... .ok() [Some] | main.rs:122:9:122:17 | user_file [Some] | provenance | |
|
||||
| main.rs:123:9:123:15 | user_fd [&ref] | main.rs:131:30:131:36 | user_fd [&ref] | provenance | |
|
||||
| main.rs:123:19:123:27 | user_file [Some] | main.rs:123:19:123:36 | user_file.as_ref() [Some, &ref] | provenance | MaD:11 |
|
||||
| main.rs:123:19:123:36 | user_file.as_ref() [Some, &ref] | main.rs:123:19:123:72 | ... .map_or(...) [&ref] | provenance | MaD:12 |
|
||||
| main.rs:123:19:123:72 | ... .map_or(...) [&ref] | main.rs:123:9:123:15 | user_fd [&ref] | provenance | |
|
||||
| main.rs:126:30:126:38 | &user_xml [&ref] | main.rs:7:32:7:45 | ...: ... [&ref] | provenance | |
|
||||
| main.rs:126:31:126:38 | user_xml | main.rs:126:30:126:38 | &user_xml [&ref] | provenance | |
|
||||
| main.rs:127:32:127:40 | &user_xml [&ref] | main.rs:12:34:12:47 | ...: ... [&ref] | provenance | |
|
||||
| main.rs:127:33:127:40 | user_xml | main.rs:127:32:127:40 | &user_xml [&ref] | provenance | |
|
||||
| main.rs:128:33:128:41 | &user_xml [&ref] | main.rs:17:35:17:48 | ...: ... [&ref] | provenance | |
|
||||
| main.rs:128:34:128:41 | user_xml | main.rs:128:33:128:41 | &user_xml [&ref] | provenance | |
|
||||
| main.rs:129:32:129:45 | &user_filename [&ref] | main.rs:22:34:22:52 | ...: ... [&ref] | provenance | |
|
||||
| main.rs:129:33:129:45 | user_filename | main.rs:129:32:129:45 | &user_filename [&ref] | provenance | |
|
||||
| main.rs:130:31:130:39 | &user_xml [&ref] | main.rs:27:33:27:46 | ...: ... [&ref] | provenance | |
|
||||
| main.rs:130:32:130:39 | user_xml | main.rs:130:31:130:39 | &user_xml [&ref] | provenance | |
|
||||
| main.rs:131:30:131:36 | user_fd [&ref] | main.rs:32:32:32:43 | ...: i32 [&ref] | provenance | |
|
||||
| main.rs:132:37:132:50 | &user_filename [&ref] | main.rs:37:39:37:57 | ...: ... [&ref] | provenance | |
|
||||
| main.rs:132:38:132:50 | user_filename | main.rs:132:37:132:50 | &user_filename [&ref] | provenance | |
|
||||
| main.rs:133:36:133:44 | &user_xml [&ref] | main.rs:42:38:42:51 | ...: ... [&ref] | provenance | |
|
||||
| main.rs:133:37:133:44 | user_xml | main.rs:133:36:133:44 | &user_xml [&ref] | provenance | |
|
||||
| main.rs:134:39:134:47 | &user_xml [&ref] | main.rs:47:41:47:54 | ...: ... [&ref] | provenance | |
|
||||
| main.rs:134:40:134:47 | user_xml | main.rs:134:39:134:47 | &user_xml [&ref] | provenance | |
|
||||
| main.rs:135:31:135:39 | &user_xml [&ref] | main.rs:59:33:59:46 | ...: ... [&ref] | provenance | |
|
||||
| main.rs:135:32:135:39 | user_xml | main.rs:135:31:135:39 | &user_xml [&ref] | provenance | |
|
||||
| main.rs:139:28:139:36 | &user_xml [&ref] | main.rs:109:23:109:36 | ...: ... [&ref] | provenance | |
|
||||
| main.rs:139:29:139:36 | user_xml | main.rs:139:28:139:36 | &user_xml [&ref] | provenance | |
|
||||
models
|
||||
| 1 | Sink: libxml::bindings::xmlCtxtReadDoc; Argument[1].Reference; xxe |
|
||||
| 2 | Sink: libxml::bindings::xmlCtxtReadFile; Argument[1].Reference; xxe |
|
||||
| 3 | Sink: libxml::bindings::xmlCtxtReadMemory; Argument[1].Reference; xxe |
|
||||
| 4 | Sink: libxml::bindings::xmlReadDoc; Argument[0].Reference; xxe |
|
||||
| 5 | Sink: libxml::bindings::xmlReadFd; Argument[0]; xxe |
|
||||
| 6 | Sink: libxml::bindings::xmlReadFile; Argument[0].Reference; xxe |
|
||||
| 7 | Sink: libxml::bindings::xmlReadMemory; Argument[0].Reference; xxe |
|
||||
| 8 | Source: <std::fs::File>::open; ReturnValue.Field[core::result::Result::Ok(0)]; file |
|
||||
| 9 | Source: std::env::args; ReturnValue.Element; commandargs |
|
||||
| 10 | Summary: <_ as core::iter::traits::iterator::Iterator>::nth; Argument[self].Reference.Element; ReturnValue.Field[core::option::Option::Some(0)]; value |
|
||||
| 11 | Summary: <core::option::Option>::as_ref; Argument[self].Reference.Field[core::option::Option::Some(0)]; ReturnValue.Field[core::option::Option::Some(0)].Reference; value |
|
||||
| 12 | Summary: <core::option::Option>::map_or; Argument[self].Field[core::option::Option::Some(0)]; ReturnValue; value |
|
||||
| 13 | Summary: <core::option::Option>::unwrap_or_default; Argument[self].Field[core::option::Option::Some(0)]; ReturnValue; value |
|
||||
| 14 | Summary: <core::result::Result>::ok; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue.Field[core::option::Option::Some(0)]; value |
|
||||
| 15 | Summary: <core::str>::as_ptr; Argument[self].Reference; ReturnValue.Reference; taint |
|
||||
nodes
|
||||
| main.rs:7:32:7:45 | ...: ... [&ref] | semmle.label | ...: ... [&ref] |
|
||||
| main.rs:9:5:9:27 | ...::xmlReadMemory | semmle.label | ...::xmlReadMemory |
|
||||
| main.rs:9:29:9:36 | user_xml [&ref] | semmle.label | user_xml [&ref] |
|
||||
| main.rs:9:29:9:45 | user_xml.as_ptr() [&ref] | semmle.label | user_xml.as_ptr() [&ref] |
|
||||
| main.rs:9:29:9:62 | ... as ... | semmle.label | ... as ... |
|
||||
| main.rs:12:34:12:47 | ...: ... [&ref] | semmle.label | ...: ... [&ref] |
|
||||
| main.rs:14:5:14:27 | ...::xmlReadMemory | semmle.label | ...::xmlReadMemory |
|
||||
| main.rs:14:29:14:36 | user_xml [&ref] | semmle.label | user_xml [&ref] |
|
||||
| main.rs:14:29:14:45 | user_xml.as_ptr() [&ref] | semmle.label | user_xml.as_ptr() [&ref] |
|
||||
| main.rs:14:29:14:62 | ... as ... | semmle.label | ... as ... |
|
||||
| main.rs:17:35:17:48 | ...: ... [&ref] | semmle.label | ...: ... [&ref] |
|
||||
| main.rs:19:5:19:27 | ...::xmlReadMemory | semmle.label | ...::xmlReadMemory |
|
||||
| main.rs:19:29:19:36 | user_xml [&ref] | semmle.label | user_xml [&ref] |
|
||||
| main.rs:19:29:19:45 | user_xml.as_ptr() [&ref] | semmle.label | user_xml.as_ptr() [&ref] |
|
||||
| main.rs:19:29:19:62 | ... as ... | semmle.label | ... as ... |
|
||||
| main.rs:22:34:22:52 | ...: ... [&ref] | semmle.label | ...: ... [&ref] |
|
||||
| main.rs:24:5:24:25 | ...::xmlReadFile | semmle.label | ...::xmlReadFile |
|
||||
| main.rs:24:27:24:39 | user_filename [&ref] | semmle.label | user_filename [&ref] |
|
||||
| main.rs:24:27:24:48 | user_filename.as_ptr() [&ref] | semmle.label | user_filename.as_ptr() [&ref] |
|
||||
| main.rs:24:27:24:65 | ... as ... | semmle.label | ... as ... |
|
||||
| main.rs:27:33:27:46 | ...: ... [&ref] | semmle.label | ...: ... [&ref] |
|
||||
| main.rs:29:5:29:24 | ...::xmlReadDoc | semmle.label | ...::xmlReadDoc |
|
||||
| main.rs:29:26:29:33 | user_xml [&ref] | semmle.label | user_xml [&ref] |
|
||||
| main.rs:29:26:29:42 | user_xml.as_ptr() [&ref] | semmle.label | user_xml.as_ptr() [&ref] |
|
||||
| main.rs:29:26:29:60 | ... as ... | semmle.label | ... as ... |
|
||||
| main.rs:32:32:32:43 | ...: i32 [&ref] | semmle.label | ...: i32 [&ref] |
|
||||
| main.rs:34:5:34:23 | ...::xmlReadFd | semmle.label | ...::xmlReadFd |
|
||||
| main.rs:34:25:34:31 | user_fd [&ref] | semmle.label | user_fd [&ref] |
|
||||
| main.rs:37:39:37:57 | ...: ... [&ref] | semmle.label | ...: ... [&ref] |
|
||||
| main.rs:39:5:39:29 | ...::xmlCtxtReadFile | semmle.label | ...::xmlCtxtReadFile |
|
||||
| main.rs:39:53:39:65 | user_filename [&ref] | semmle.label | user_filename [&ref] |
|
||||
| main.rs:39:53:39:74 | user_filename.as_ptr() [&ref] | semmle.label | user_filename.as_ptr() [&ref] |
|
||||
| main.rs:39:53:39:91 | ... as ... | semmle.label | ... as ... |
|
||||
| main.rs:42:38:42:51 | ...: ... [&ref] | semmle.label | ...: ... [&ref] |
|
||||
| main.rs:44:5:44:28 | ...::xmlCtxtReadDoc | semmle.label | ...::xmlCtxtReadDoc |
|
||||
| main.rs:44:52:44:59 | user_xml [&ref] | semmle.label | user_xml [&ref] |
|
||||
| main.rs:44:52:44:68 | user_xml.as_ptr() [&ref] | semmle.label | user_xml.as_ptr() [&ref] |
|
||||
| main.rs:44:52:44:86 | ... as ... | semmle.label | ... as ... |
|
||||
| main.rs:47:41:47:54 | ...: ... [&ref] | semmle.label | ...: ... [&ref] |
|
||||
| main.rs:49:5:49:31 | ...::xmlCtxtReadMemory | semmle.label | ...::xmlCtxtReadMemory |
|
||||
| main.rs:51:9:51:16 | user_xml [&ref] | semmle.label | user_xml [&ref] |
|
||||
| main.rs:51:9:51:25 | user_xml.as_ptr() [&ref] | semmle.label | user_xml.as_ptr() [&ref] |
|
||||
| main.rs:51:9:51:42 | ... as ... | semmle.label | ... as ... |
|
||||
| main.rs:59:33:59:46 | ...: ... [&ref] | semmle.label | ...: ... [&ref] |
|
||||
| main.rs:61:5:61:27 | ...::xmlReadMemory | semmle.label | ...::xmlReadMemory |
|
||||
| main.rs:61:29:61:36 | user_xml [&ref] | semmle.label | user_xml [&ref] |
|
||||
| main.rs:61:29:61:45 | user_xml.as_ptr() [&ref] | semmle.label | user_xml.as_ptr() [&ref] |
|
||||
| main.rs:61:29:61:62 | ... as ... | semmle.label | ... as ... |
|
||||
| main.rs:64:5:64:27 | ...::xmlReadMemory | semmle.label | ...::xmlReadMemory |
|
||||
| main.rs:64:29:64:36 | user_xml [&ref] | semmle.label | user_xml [&ref] |
|
||||
| main.rs:64:29:64:45 | user_xml.as_ptr() [&ref] | semmle.label | user_xml.as_ptr() [&ref] |
|
||||
| main.rs:64:29:64:62 | ... as ... | semmle.label | ... as ... |
|
||||
| main.rs:109:23:109:36 | ...: ... [&ref] | semmle.label | ...: ... [&ref] |
|
||||
| main.rs:111:23:111:30 | user_xml | semmle.label | user_xml |
|
||||
| main.rs:112:23:112:30 | user_xml | semmle.label | user_xml |
|
||||
| main.rs:113:23:113:30 | user_xml | semmle.label | user_xml |
|
||||
| main.rs:120:9:120:16 | user_xml | semmle.label | user_xml |
|
||||
| main.rs:120:20:120:33 | ...::args | semmle.label | ...::args |
|
||||
| main.rs:120:20:120:35 | ...::args(...) [element] | semmle.label | ...::args(...) [element] |
|
||||
| main.rs:120:20:120:42 | ... .nth(...) [Some] | semmle.label | ... .nth(...) [Some] |
|
||||
| main.rs:120:20:120:62 | ... .unwrap_or_default() | semmle.label | ... .unwrap_or_default() |
|
||||
| main.rs:121:9:121:21 | user_filename | semmle.label | user_filename |
|
||||
| main.rs:121:25:121:38 | ...::args | semmle.label | ...::args |
|
||||
| main.rs:121:25:121:40 | ...::args(...) [element] | semmle.label | ...::args(...) [element] |
|
||||
| main.rs:121:25:121:47 | ... .nth(...) [Some] | semmle.label | ... .nth(...) [Some] |
|
||||
| main.rs:121:25:121:67 | ... .unwrap_or_default() | semmle.label | ... .unwrap_or_default() |
|
||||
| main.rs:122:9:122:17 | user_file [Some] | semmle.label | user_file [Some] |
|
||||
| main.rs:122:21:122:39 | ...::open | semmle.label | ...::open |
|
||||
| main.rs:122:21:122:55 | ...::open(...) [Ok] | semmle.label | ...::open(...) [Ok] |
|
||||
| main.rs:122:21:122:60 | ... .ok() [Some] | semmle.label | ... .ok() [Some] |
|
||||
| main.rs:123:9:123:15 | user_fd [&ref] | semmle.label | user_fd [&ref] |
|
||||
| main.rs:123:19:123:27 | user_file [Some] | semmle.label | user_file [Some] |
|
||||
| main.rs:123:19:123:36 | user_file.as_ref() [Some, &ref] | semmle.label | user_file.as_ref() [Some, &ref] |
|
||||
| main.rs:123:19:123:72 | ... .map_or(...) [&ref] | semmle.label | ... .map_or(...) [&ref] |
|
||||
| main.rs:126:30:126:38 | &user_xml [&ref] | semmle.label | &user_xml [&ref] |
|
||||
| main.rs:126:31:126:38 | user_xml | semmle.label | user_xml |
|
||||
| main.rs:127:32:127:40 | &user_xml [&ref] | semmle.label | &user_xml [&ref] |
|
||||
| main.rs:127:33:127:40 | user_xml | semmle.label | user_xml |
|
||||
| main.rs:128:33:128:41 | &user_xml [&ref] | semmle.label | &user_xml [&ref] |
|
||||
| main.rs:128:34:128:41 | user_xml | semmle.label | user_xml |
|
||||
| main.rs:129:32:129:45 | &user_filename [&ref] | semmle.label | &user_filename [&ref] |
|
||||
| main.rs:129:33:129:45 | user_filename | semmle.label | user_filename |
|
||||
| main.rs:130:31:130:39 | &user_xml [&ref] | semmle.label | &user_xml [&ref] |
|
||||
| main.rs:130:32:130:39 | user_xml | semmle.label | user_xml |
|
||||
| main.rs:131:30:131:36 | user_fd [&ref] | semmle.label | user_fd [&ref] |
|
||||
| main.rs:132:37:132:50 | &user_filename [&ref] | semmle.label | &user_filename [&ref] |
|
||||
| main.rs:132:38:132:50 | user_filename | semmle.label | user_filename |
|
||||
| main.rs:133:36:133:44 | &user_xml [&ref] | semmle.label | &user_xml [&ref] |
|
||||
| main.rs:133:37:133:44 | user_xml | semmle.label | user_xml |
|
||||
| main.rs:134:39:134:47 | &user_xml [&ref] | semmle.label | &user_xml [&ref] |
|
||||
| main.rs:134:40:134:47 | user_xml | semmle.label | user_xml |
|
||||
| main.rs:135:31:135:39 | &user_xml [&ref] | semmle.label | &user_xml [&ref] |
|
||||
| main.rs:135:32:135:39 | user_xml | semmle.label | user_xml |
|
||||
| main.rs:139:28:139:36 | &user_xml [&ref] | semmle.label | &user_xml [&ref] |
|
||||
| main.rs:139:29:139:36 | user_xml | semmle.label | user_xml |
|
||||
subpaths
|
||||
4
rust/ql/test/query-tests/security/CWE-611/Xxe.qlref
Normal file
4
rust/ql/test/query-tests/security/CWE-611/Xxe.qlref
Normal file
@@ -0,0 +1,4 @@
|
||||
query: queries/security/CWE-611/Xxe.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
141
rust/ql/test/query-tests/security/CWE-611/main.rs
Normal file
141
rust/ql/test/query-tests/security/CWE-611/main.rs
Normal file
@@ -0,0 +1,141 @@
|
||||
use libxml::bindings;
|
||||
use std::os::fd::AsRawFd;
|
||||
use std::os::raw::{c_char, c_uchar};
|
||||
|
||||
// --- BAD: user-controlled XML with unsafe parser options ---
|
||||
|
||||
unsafe fn test_xml_parse_noent(user_xml: &str) {
|
||||
// BAD: XML_PARSE_NOENT enables external entity substitution
|
||||
bindings::xmlReadMemory(user_xml.as_ptr() as *const c_char, user_xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_NOENT as i32); // $ Alert[rust/xxe]
|
||||
}
|
||||
|
||||
unsafe fn test_xml_parse_dtdload(user_xml: &str) {
|
||||
// BAD: XML_PARSE_DTDLOAD enables loading of external DTD subsets
|
||||
bindings::xmlReadMemory(user_xml.as_ptr() as *const c_char, user_xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_DTDLOAD as i32); // $ Alert[rust/xxe]
|
||||
}
|
||||
|
||||
unsafe fn test_xml_parse_combined(user_xml: &str) {
|
||||
// BAD: combining both unsafe options
|
||||
bindings::xmlReadMemory(user_xml.as_ptr() as *const c_char, user_xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_NOENT as i32 | bindings::xmlParserOption_XML_PARSE_DTDLOAD as i32); // $ Alert[rust/xxe]
|
||||
}
|
||||
|
||||
unsafe fn test_xml_read_file_bad(user_filename: &str) {
|
||||
// BAD: user-controlled filename with XML_PARSE_NOENT
|
||||
bindings::xmlReadFile(user_filename.as_ptr() as *const c_char, std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_NOENT as i32); // $ Alert[rust/xxe]
|
||||
}
|
||||
|
||||
unsafe fn test_xml_read_doc_bad(user_xml: &str) {
|
||||
// BAD: user-controlled XML document with XML_PARSE_DTDLOAD
|
||||
bindings::xmlReadDoc(user_xml.as_ptr() as *const c_uchar, std::ptr::null_mut(), std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_DTDLOAD as i32); // $ Alert[rust/xxe]
|
||||
}
|
||||
|
||||
unsafe fn test_xml_read_fd_bad(user_fd: i32) {
|
||||
// BAD: user-controlled file descriptor with XML_PARSE_DTDLOAD
|
||||
bindings::xmlReadFd(user_fd, std::ptr::null_mut(), std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_DTDLOAD as i32); // $ Alert[rust/xxe]
|
||||
}
|
||||
|
||||
unsafe fn test_xml_ctxt_read_file_bad(user_filename: &str) {
|
||||
// BAD: user-controlled filename with XML_PARSE_NOENT via ctxt variant
|
||||
bindings::xmlCtxtReadFile(std::ptr::null_mut(), user_filename.as_ptr() as *const c_char, std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_NOENT as i32); // $ Alert[rust/xxe]
|
||||
}
|
||||
|
||||
unsafe fn test_xml_ctxt_read_doc_bad(user_xml: &str) {
|
||||
// BAD: user-controlled XML with unsafe options via ctxt variant
|
||||
bindings::xmlCtxtReadDoc(std::ptr::null_mut(), user_xml.as_ptr() as *const c_uchar, std::ptr::null_mut(), std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_NOENT as i32); // $ Alert[rust/xxe]
|
||||
}
|
||||
|
||||
unsafe fn test_xml_ctxt_read_memory_bad(user_xml: &str) {
|
||||
// BAD: user-controlled XML with unsafe options via ctxt variant
|
||||
bindings::xmlCtxtReadMemory( // $ Alert[rust/xxe]
|
||||
std::ptr::null_mut(),
|
||||
user_xml.as_ptr() as *const c_char,
|
||||
user_xml.len() as i32,
|
||||
std::ptr::null_mut(),
|
||||
std::ptr::null_mut(),
|
||||
bindings::xmlParserOption_XML_PARSE_NOENT as i32,
|
||||
);
|
||||
}
|
||||
|
||||
unsafe fn test_integer_literals(user_xml: &str) {
|
||||
// BAD: literal value 2 = XML_PARSE_NOENT
|
||||
bindings::xmlReadMemory(user_xml.as_ptr() as *const c_char, user_xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), 2); // $ Alert[rust/xxe]
|
||||
|
||||
// BAD: literal value 4 = XML_PARSE_DTDLOAD
|
||||
bindings::xmlReadMemory(user_xml.as_ptr() as *const c_char, user_xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), 4i32); // $ Alert[rust/xxe]
|
||||
|
||||
// BAD: literal value 4 = XML_PARSE_DTDLOAD
|
||||
bindings::xmlReadMemory(user_xml.as_ptr() as *const c_char, user_xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), 0x4i32); // $ MISSING: Alert[rust/xxe]
|
||||
|
||||
// GOOD: literal value 0 = no entity expansion
|
||||
bindings::xmlReadMemory(user_xml.as_ptr() as *const c_char, user_xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), 0);
|
||||
|
||||
// GOOD: literal value 2048 = no entity expansion
|
||||
bindings::xmlReadMemory(user_xml.as_ptr() as *const c_char, user_xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), 2_048);
|
||||
}
|
||||
|
||||
unsafe fn test_dataflow_bad(user_xml: &str) {
|
||||
// BAD: user-controlled XML with unsafe parser options via dataflow
|
||||
let flags = bindings::xmlParserOption_XML_PARSE_NOENT as i32 | 1024;
|
||||
bindings::xmlReadMemory(user_xml.as_ptr() as *const c_char, user_xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), flags); // $ MISSING: Alert[rust/xxe]
|
||||
}
|
||||
|
||||
// --- GOOD: user-controlled XML with safe parser options ---
|
||||
|
||||
unsafe fn test_xml_parse_safe_options(user_xml: &str) {
|
||||
// GOOD: options = 0 means no entity expansion
|
||||
bindings::xmlReadMemory(user_xml.as_ptr() as *const c_char, user_xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), 0);
|
||||
bindings::xmlReadFile(user_xml.as_ptr() as *const c_char, std::ptr::null_mut(), 0);
|
||||
bindings::xmlReadDoc(user_xml.as_ptr() as *const c_uchar, std::ptr::null_mut(), std::ptr::null_mut(), 0);
|
||||
}
|
||||
|
||||
// --- GOOD: hardcoded (non-user-controlled) XML with unsafe parser options ---
|
||||
|
||||
unsafe fn test_xml_hardcoded_unsafe() {
|
||||
let xml = "<root/>";
|
||||
// GOOD: XML content is not user-controlled
|
||||
bindings::xmlReadMemory(xml.as_ptr() as *const c_char, xml.len() as i32, std::ptr::null_mut(), std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_NOENT as i32);
|
||||
bindings::xmlReadFile("trusted/input.xml".as_ptr() as *const c_char, std::ptr::null_mut(), bindings::xmlParserOption_XML_PARSE_NOENT as i32);
|
||||
}
|
||||
|
||||
// --- custom parser (requires heuristic match) ---
|
||||
|
||||
const XML_PARSE_NOENT: i32 = 2;
|
||||
const XML_PARSE_DTDLOAD: i32 = 4;
|
||||
|
||||
fn custom_xml_parser(xml: &str, options: i32) {
|
||||
// ...
|
||||
}
|
||||
|
||||
fn test_custom_parser(user_xml: &str) {
|
||||
custom_xml_parser(user_xml, 0);
|
||||
custom_xml_parser(user_xml, XML_PARSE_NOENT); // $ Alert[rust/xxe]
|
||||
custom_xml_parser(user_xml, XML_PARSE_DTDLOAD); // $ Alert[rust/xxe]
|
||||
custom_xml_parser(user_xml, XML_PARSE_NOENT | XML_PARSE_DTDLOAD); // $ Alert[rust/xxe]
|
||||
custom_xml_parser("<root/>", XML_PARSE_NOENT | XML_PARSE_DTDLOAD);
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
fn main() {
|
||||
let user_xml = std::env::args().nth(1).unwrap_or_default(); // $ Source
|
||||
let user_filename = std::env::args().nth(2).unwrap_or_default(); // $ Source
|
||||
let user_file = std::fs::File::open(&user_filename).ok(); // $ Source
|
||||
let user_fd = user_file.as_ref().map_or(-1, |file| file.as_raw_fd());
|
||||
|
||||
unsafe {
|
||||
test_xml_parse_noent(&user_xml);
|
||||
test_xml_parse_dtdload(&user_xml);
|
||||
test_xml_parse_combined(&user_xml);
|
||||
test_xml_read_file_bad(&user_filename);
|
||||
test_xml_read_doc_bad(&user_xml);
|
||||
test_xml_read_fd_bad(user_fd);
|
||||
test_xml_ctxt_read_file_bad(&user_filename);
|
||||
test_xml_ctxt_read_doc_bad(&user_xml);
|
||||
test_xml_ctxt_read_memory_bad(&user_xml);
|
||||
test_integer_literals(&user_xml);
|
||||
test_dataflow_bad(&user_xml);
|
||||
test_xml_parse_safe_options(&user_xml);
|
||||
test_xml_hardcoded_unsafe();
|
||||
test_custom_parser(&user_xml);
|
||||
}
|
||||
}
|
||||
3
rust/ql/test/query-tests/security/CWE-611/options.yml
Normal file
3
rust/ql/test/query-tests/security/CWE-611/options.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
qltest_cargo_check: true
|
||||
qltest_dependencies:
|
||||
- libxml = { version = "0.3.8" }
|
||||
Reference in New Issue
Block a user