Skip to content

Commit cbdab99

Browse files
committed
Rust: Add XSS sink for Axum HTML response creation
1 parent fbf9f7e commit cbdab99

File tree

3 files changed

+32
-2
lines changed

3 files changed

+32
-2
lines changed

rust/ql/lib/codeql/rust/security/XssExtensions.qll

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,14 @@ module Xss {
5959
)
6060
}
6161
}
62+
63+
// TODO: Convert this to MaD once MaD supports sink for tuple struct expressions.
64+
private class AxumHtmlSink extends Sink {
65+
AxumHtmlSink() {
66+
exists(TupleStructExpr call |
67+
call.getResolvedTarget().getCanonicalPath() = "axum::response::Html" and
68+
this.asExpr() = call.getSyntacticPositionalArgument(0)
69+
)
70+
}
71+
}
6272
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,24 @@
11
#select
2+
| main.rs:10:10:10:21 | html_content | main.rs:15:51:15:53 | get | main.rs:10:10:10:21 | html_content | Cross-site scripting vulnerability due to a $@. | main.rs:15:51:15:53 | get | user-provided value |
23
edges
4+
| main.rs:8:24:8:59 | ...: Query::<...> | main.rs:9:32:9:63 | MacroExpr | provenance | |
5+
| main.rs:9:9:9:20 | html_content | main.rs:10:10:10:21 | html_content | provenance | |
6+
| main.rs:9:32:9:63 | ...::format(...) | main.rs:9:32:9:63 | { ... } | provenance | |
7+
| main.rs:9:32:9:63 | ...::must_use(...) | main.rs:9:9:9:20 | html_content | provenance | |
8+
| main.rs:9:32:9:63 | MacroExpr | main.rs:9:32:9:63 | ...::format(...) | provenance | MaD:2 |
9+
| main.rs:9:32:9:63 | { ... } | main.rs:9:32:9:63 | ...::must_use(...) | provenance | MaD:3 |
10+
| main.rs:15:51:15:53 | get | main.rs:8:24:8:59 | ...: Query::<...> | provenance | Src:MaD:1 |
11+
models
12+
| 1 | Source: axum::routing::method_routing::get; Argument[0].Parameter[0..7]; remote |
13+
| 2 | Summary: alloc::fmt::format; Argument[0]; ReturnValue; taint |
14+
| 3 | Summary: core::hint::must_use; Argument[0]; ReturnValue; value |
315
nodes
16+
| main.rs:8:24:8:59 | ...: Query::<...> | semmle.label | ...: Query::<...> |
17+
| main.rs:9:9:9:20 | html_content | semmle.label | html_content |
18+
| main.rs:9:32:9:63 | ...::format(...) | semmle.label | ...::format(...) |
19+
| main.rs:9:32:9:63 | ...::must_use(...) | semmle.label | ...::must_use(...) |
20+
| main.rs:9:32:9:63 | MacroExpr | semmle.label | MacroExpr |
21+
| main.rs:9:32:9:63 | { ... } | semmle.label | { ... } |
22+
| main.rs:10:10:10:21 | html_content | semmle.label | html_content |
23+
| main.rs:15:51:15:53 | get | semmle.label | get |
424
subpaths

rust/ql/test/query-tests/security/CWE-079/axum/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ struct GreetingParams {
77

88
async fn greet_handler(Query(params): Query<GreetingParams>) -> Html<String> {
99
let html_content = format!("<p>Hello, {}!</p>", params.name);
10-
Html(html_content) // $ MISSING: Alert[rust/xss]
10+
Html(html_content) // $ Alert[rust/xss]=greet
1111
}
1212

1313
#[tokio::main]
1414
pub async fn main() {
15-
let app = Router::<()>::new().route("/greet", get(greet_handler));
15+
let app = Router::<()>::new().route("/greet", get(greet_handler)); // $ Source=greet
1616
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
1717
.await
1818
.unwrap();

0 commit comments

Comments
 (0)