Skip to content

Commit 87fb764

Browse files
committed
Rust: Add XSS sinks for Actix and Warp
1 parent 3dc7a05 commit 87fb764

File tree

6 files changed

+66
-5
lines changed

6 files changed

+66
-5
lines changed

rust/ql/lib/codeql/rust/frameworks/actix-web.model.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ extensions:
66
- ["<actix_web::route::Route>::to", "Argument[0].Parameter[0..7]", "remote", "manual"]
77
# Actix attributes such as `get` expand to this `to` call on the handler.
88
- ["<actix_web::resource::Resource>::to", "Argument[0].Parameter[0..7]", "remote", "manual"]
9+
- addsTo:
10+
pack: codeql/rust-all
11+
extensible: sinkModel
12+
data:
13+
- ["<actix_web::types::html::Html>::new", "Argument[0]", "html-injection", "manual"]
914
- addsTo:
1015
pack: codeql/rust-all
1116
extensible: summaryModel

rust/ql/lib/codeql/rust/frameworks/warp.model.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,9 @@ extensions:
55
data:
66
- ["<_ as warp::filter::Filter>::then", "Argument[0].Parameter[0..7]", "remote", "manual"]
77
- ["<_ as warp::filter::Filter>::map", "Argument[0].Parameter[0..7]", "remote", "manual"]
8-
- ["<_ as warp::filter::Filter>::and_then", "Argument[0].Parameter[0..7]", "remote", "manual"]
8+
- ["<_ as warp::filter::Filter>::and_then", "Argument[0].Parameter[0..7]", "remote", "manual"]
9+
- addsTo:
10+
pack: codeql/rust-all
11+
extensible: sinkModel
12+
data:
13+
- ["warp::reply::html", "Argument[0]", "html-injection", "manual"]
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,32 @@
11
#select
2+
| main.rs:25:5:25:13 | ...::new | main.rs:8:1:8:18 | to | main.rs:25:5:25:13 | ...::new | Cross-site scripting vulnerability due to a $@. | main.rs:8:1:8:18 | to | user-provided value |
23
edges
4+
| main.rs:8:1:8:18 | to | main.rs:9:29:9:51 | ...: ...::Path::<...> | provenance | Src:MaD:2 |
5+
| main.rs:9:29:9:51 | ...: ...::Path::<...> | main.rs:10:22:10:38 | path.into_inner() | provenance | MaD:3 |
6+
| main.rs:10:9:10:18 | user_input | main.rs:13:9:22:18 | MacroExpr | provenance | |
7+
| main.rs:10:22:10:38 | path.into_inner() | main.rs:10:9:10:18 | user_input | provenance | |
8+
| main.rs:12:9:12:12 | html | main.rs:25:15:25:18 | html | provenance | |
9+
| main.rs:13:9:22:18 | ...::format(...) | main.rs:13:9:22:18 | { ... } | provenance | |
10+
| main.rs:13:9:22:18 | ...::must_use(...) | main.rs:12:9:12:12 | html | provenance | |
11+
| main.rs:13:9:22:18 | MacroExpr | main.rs:13:9:22:18 | ...::format(...) | provenance | MaD:4 |
12+
| main.rs:13:9:22:18 | { ... } | main.rs:13:9:22:18 | ...::must_use(...) | provenance | MaD:5 |
13+
| main.rs:25:15:25:18 | html | main.rs:25:5:25:13 | ...::new | provenance | MaD:1 Sink:MaD:1 |
14+
models
15+
| 1 | Sink: <actix_web::types::html::Html>::new; Argument[0]; html-injection |
16+
| 2 | Source: <actix_web::resource::Resource>::to; Argument[0].Parameter[0..7]; remote |
17+
| 3 | Summary: <actix_web::types::path::Path>::into_inner; Argument[self]; ReturnValue; taint |
18+
| 4 | Summary: alloc::fmt::format; Argument[0]; ReturnValue; taint |
19+
| 5 | Summary: core::hint::must_use; Argument[0]; ReturnValue; value |
320
nodes
21+
| main.rs:8:1:8:18 | to | semmle.label | to |
22+
| main.rs:9:29:9:51 | ...: ...::Path::<...> | semmle.label | ...: ...::Path::<...> |
23+
| main.rs:10:9:10:18 | user_input | semmle.label | user_input |
24+
| main.rs:10:22:10:38 | path.into_inner() | semmle.label | path.into_inner() |
25+
| main.rs:12:9:12:12 | html | semmle.label | html |
26+
| main.rs:13:9:22:18 | ...::format(...) | semmle.label | ...::format(...) |
27+
| main.rs:13:9:22:18 | ...::must_use(...) | semmle.label | ...::must_use(...) |
28+
| main.rs:13:9:22:18 | MacroExpr | semmle.label | MacroExpr |
29+
| main.rs:13:9:22:18 | { ... } | semmle.label | { ... } |
30+
| main.rs:25:5:25:13 | ...::new | semmle.label | ...::new |
31+
| main.rs:25:15:25:18 | html | semmle.label | html |
432
subpaths

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use actix_web::{
55
};
66

77
// The "bad" example from the qldoc
8-
#[get("/bad/{a}")]
8+
#[get("/bad/{a}")] // $ Source
99
async fn vulnerable_handler(path: web::Path<String>) -> impl Responder {
1010
let user_input = path.into_inner();
1111

@@ -22,7 +22,7 @@ async fn vulnerable_handler(path: web::Path<String>) -> impl Responder {
2222
user_input
2323
);
2424

25-
Html::new(html) // $ MISSING: Alert[rust/xss]
25+
Html::new(html) // $ Alert[rust/xss]
2626
}
2727

2828
fn html_escape(s: &str) -> String {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,27 @@
11
#select
2+
| main.rs:12:13:12:29 | ...::html | main.rs:9:10:9:12 | map | main.rs:12:13:12:29 | ...::html | Cross-site scripting vulnerability due to a $@. | main.rs:9:10:9:12 | map | user-provided value |
23
edges
4+
| main.rs:9:10:9:12 | map | main.rs:9:15:9:26 | ...: String | provenance | Src:MaD:2 |
5+
| main.rs:9:15:9:26 | ...: String | main.rs:11:32:11:56 | MacroExpr | provenance | |
6+
| main.rs:11:17:11:20 | body | main.rs:12:31:12:34 | body | provenance | |
7+
| main.rs:11:32:11:56 | ...::format(...) | main.rs:11:32:11:56 | { ... } | provenance | |
8+
| main.rs:11:32:11:56 | ...::must_use(...) | main.rs:11:17:11:20 | body | provenance | |
9+
| main.rs:11:32:11:56 | MacroExpr | main.rs:11:32:11:56 | ...::format(...) | provenance | MaD:3 |
10+
| main.rs:11:32:11:56 | { ... } | main.rs:11:32:11:56 | ...::must_use(...) | provenance | MaD:4 |
11+
| main.rs:12:31:12:34 | body | main.rs:12:13:12:29 | ...::html | provenance | MaD:1 Sink:MaD:1 |
12+
models
13+
| 1 | Sink: warp::reply::html; Argument[0]; html-injection |
14+
| 2 | Source: <_ as warp::filter::Filter>::map; Argument[0].Parameter[0..7]; remote |
15+
| 3 | Summary: alloc::fmt::format; Argument[0]; ReturnValue; taint |
16+
| 4 | Summary: core::hint::must_use; Argument[0]; ReturnValue; value |
317
nodes
18+
| main.rs:9:10:9:12 | map | semmle.label | map |
19+
| main.rs:9:15:9:26 | ...: String | semmle.label | ...: String |
20+
| main.rs:11:17:11:20 | body | semmle.label | body |
21+
| main.rs:11:32:11:56 | ...::format(...) | semmle.label | ...::format(...) |
22+
| main.rs:11:32:11:56 | ...::must_use(...) | semmle.label | ...::must_use(...) |
23+
| main.rs:11:32:11:56 | MacroExpr | semmle.label | MacroExpr |
24+
| main.rs:11:32:11:56 | { ... } | semmle.label | { ... } |
25+
| main.rs:12:13:12:29 | ...::html | semmle.label | ...::html |
26+
| main.rs:12:31:12:34 | body | semmle.label | body |
427
subpaths

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ use warp::Filter;
66
pub async fn main() {
77
let hello = warp::path("greet")
88
.and(warp::path::param())
9-
.map(|name: String| {
9+
.map(|name: String| { // $ Source
1010
// Vulnerable to XSS because it directly includes user input in the response
1111
let body = format!("<h1>Hello, {name}!</h1>");
12-
warp::reply::html(body) // $ MISSING: Alert[rust/xss]
12+
warp::reply::html(body) // $ Alert[rust/xss]
1313
});
1414

1515
// Start the web server on port 3000

0 commit comments

Comments
 (0)