From 0ea06aca0622c988b8ec1bfcd3f17cba35bd2bc1 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Tue, 16 Dec 2025 12:32:40 +0100 Subject: [PATCH 1/5] Rust: Introduce more functions in Axum test --- .../web_frameworks/InlineFlow.expected | 156 +++++++++--------- .../web_frameworks/TaintSources.expected | 128 +++++++------- .../dataflow/sources/web_frameworks/test.rs | 80 ++++----- 3 files changed, 172 insertions(+), 192 deletions(-) diff --git a/rust/ql/test/library-tests/dataflow/sources/web_frameworks/InlineFlow.expected b/rust/ql/test/library-tests/dataflow/sources/web_frameworks/InlineFlow.expected index 8777ff626eb3..dce59fc29b70 100644 --- a/rust/ql/test/library-tests/dataflow/sources/web_frameworks/InlineFlow.expected +++ b/rust/ql/test/library-tests/dataflow/sources/web_frameworks/InlineFlow.expected @@ -20,36 +20,36 @@ edges | test.rs:58:14:58:15 | ms | test.rs:60:14:60:17 | ms.a | provenance | | | test.rs:58:14:58:15 | ms | test.rs:61:14:61:17 | ms.b | provenance | | | test.rs:68:15:68:15 | a | test.rs:70:14:70:14 | a | provenance | | -| test.rs:98:9:98:31 | ...: ...::Path::<...> | test.rs:100:17:100:20 | path | provenance | | -| test.rs:100:13:100:13 | a | test.rs:101:14:101:14 | a | provenance | | -| test.rs:100:13:100:13 | a | test.rs:102:14:102:14 | a | provenance | | -| test.rs:100:13:100:13 | a | test.rs:103:14:103:14 | a | provenance | | -| test.rs:100:17:100:20 | path | test.rs:100:17:100:33 | path.into_inner() | provenance | MaD:6 | -| test.rs:100:17:100:33 | path.into_inner() | test.rs:100:13:100:13 | a | provenance | | -| test.rs:101:14:101:14 | a | test.rs:101:14:101:23 | a.as_str() | provenance | MaD:8 | -| test.rs:102:14:102:14 | a | test.rs:102:14:102:25 | a.as_bytes() | provenance | MaD:7 | -| test.rs:109:9:109:41 | ...: ...::Path::<...> | test.rs:111:22:111:25 | path | provenance | | -| test.rs:111:13:111:18 | TuplePat | test.rs:113:14:113:14 | a | provenance | | -| test.rs:111:13:111:18 | TuplePat | test.rs:114:14:114:14 | b | provenance | | -| test.rs:111:22:111:25 | path | test.rs:111:22:111:38 | path.into_inner() | provenance | MaD:6 | -| test.rs:111:22:111:38 | path.into_inner() | test.rs:111:13:111:18 | TuplePat | provenance | | -| test.rs:120:9:120:41 | ...: ...::Query::<...> | test.rs:122:14:122:14 | a | provenance | | -| test.rs:127:5:127:20 | to | test.rs:129:9:129:31 | ...: ...::Path::<...> | provenance | Src:MaD:4 | -| test.rs:129:9:129:31 | ...: ...::Path::<...> | test.rs:131:17:131:20 | path | provenance | | -| test.rs:131:13:131:13 | a | test.rs:132:14:132:14 | a | provenance | | -| test.rs:131:17:131:20 | path | test.rs:131:17:131:33 | path.into_inner() | provenance | MaD:6 | -| test.rs:131:17:131:33 | path.into_inner() | test.rs:131:13:131:13 | a | provenance | | -| test.rs:139:41:139:42 | to | test.rs:98:9:98:31 | ...: ...::Path::<...> | provenance | Src:MaD:5 | -| test.rs:140:45:140:46 | to | test.rs:109:9:109:41 | ...: ...::Path::<...> | provenance | Src:MaD:5 | -| test.rs:141:41:141:42 | to | test.rs:120:9:120:41 | ...: ...::Query::<...> | provenance | Src:MaD:5 | -| test.rs:242:33:242:35 | map | test.rs:242:38:242:46 | ...: String | provenance | Src:MaD:2 | -| test.rs:242:38:242:46 | ...: String | test.rs:244:18:244:18 | a | provenance | | -| test.rs:250:46:250:49 | then | test.rs:251:25:251:33 | ...: String | provenance | Src:MaD:3 | -| test.rs:251:25:251:33 | ...: String | test.rs:252:22:252:22 | a | provenance | | -| test.rs:259:50:259:57 | and_then | test.rs:260:26:260:32 | ...: u64 | provenance | Src:MaD:1 | -| test.rs:260:26:260:32 | ...: u64 | test.rs:263:22:263:23 | id | provenance | | -| test.rs:272:75:272:77 | map | test.rs:273:15:273:23 | ...: String | provenance | Src:MaD:2 | -| test.rs:273:15:273:23 | ...: String | test.rs:275:22:275:22 | a | provenance | | +| test.rs:97:33:97:55 | ...: ...::Path::<...> | test.rs:98:17:98:20 | path | provenance | | +| test.rs:98:13:98:13 | a | test.rs:99:14:99:14 | a | provenance | | +| test.rs:98:13:98:13 | a | test.rs:100:14:100:14 | a | provenance | | +| test.rs:98:13:98:13 | a | test.rs:101:14:101:14 | a | provenance | | +| test.rs:98:17:98:20 | path | test.rs:98:17:98:33 | path.into_inner() | provenance | MaD:6 | +| test.rs:98:17:98:33 | path.into_inner() | test.rs:98:13:98:13 | a | provenance | | +| test.rs:99:14:99:14 | a | test.rs:99:14:99:23 | a.as_str() | provenance | MaD:8 | +| test.rs:100:14:100:14 | a | test.rs:100:14:100:25 | a.as_bytes() | provenance | MaD:7 | +| test.rs:106:33:106:65 | ...: ...::Path::<...> | test.rs:107:22:107:25 | path | provenance | | +| test.rs:107:13:107:18 | TuplePat | test.rs:109:14:109:14 | a | provenance | | +| test.rs:107:13:107:18 | TuplePat | test.rs:110:14:110:14 | b | provenance | | +| test.rs:107:22:107:25 | path | test.rs:107:22:107:38 | path.into_inner() | provenance | MaD:6 | +| test.rs:107:22:107:38 | path.into_inner() | test.rs:107:13:107:18 | TuplePat | provenance | | +| test.rs:115:33:115:65 | ...: ...::Query::<...> | test.rs:116:14:116:14 | a | provenance | | +| test.rs:121:5:121:20 | to | test.rs:122:33:122:55 | ...: ...::Path::<...> | provenance | Src:MaD:4 | +| test.rs:122:33:122:55 | ...: ...::Path::<...> | test.rs:123:17:123:20 | path | provenance | | +| test.rs:123:13:123:13 | a | test.rs:124:14:124:14 | a | provenance | | +| test.rs:123:17:123:20 | path | test.rs:123:17:123:33 | path.into_inner() | provenance | MaD:6 | +| test.rs:123:17:123:33 | path.into_inner() | test.rs:123:13:123:13 | a | provenance | | +| test.rs:131:41:131:42 | to | test.rs:97:33:97:55 | ...: ...::Path::<...> | provenance | Src:MaD:5 | +| test.rs:132:45:132:46 | to | test.rs:106:33:106:65 | ...: ...::Path::<...> | provenance | Src:MaD:5 | +| test.rs:133:41:133:42 | to | test.rs:115:33:115:65 | ...: ...::Query::<...> | provenance | Src:MaD:5 | +| test.rs:222:33:222:35 | map | test.rs:222:38:222:46 | ...: String | provenance | Src:MaD:2 | +| test.rs:222:38:222:46 | ...: String | test.rs:224:18:224:18 | a | provenance | | +| test.rs:230:46:230:49 | then | test.rs:231:25:231:33 | ...: String | provenance | Src:MaD:3 | +| test.rs:231:25:231:33 | ...: String | test.rs:232:22:232:22 | a | provenance | | +| test.rs:239:50:239:57 | and_then | test.rs:240:26:240:32 | ...: u64 | provenance | Src:MaD:1 | +| test.rs:240:26:240:32 | ...: u64 | test.rs:243:22:243:23 | id | provenance | | +| test.rs:252:75:252:77 | map | test.rs:253:15:253:23 | ...: String | provenance | Src:MaD:2 | +| test.rs:253:15:253:23 | ...: String | test.rs:255:22:255:22 | a | provenance | | nodes | test.rs:11:31:11:31 | a | semmle.label | a | | test.rs:13:14:13:14 | a | semmle.label | a | @@ -68,44 +68,44 @@ nodes | test.rs:61:14:61:17 | ms.b | semmle.label | ms.b | | test.rs:68:15:68:15 | a | semmle.label | a | | test.rs:70:14:70:14 | a | semmle.label | a | -| test.rs:98:9:98:31 | ...: ...::Path::<...> | semmle.label | ...: ...::Path::<...> | -| test.rs:100:13:100:13 | a | semmle.label | a | -| test.rs:100:17:100:20 | path | semmle.label | path | -| test.rs:100:17:100:33 | path.into_inner() | semmle.label | path.into_inner() | +| test.rs:97:33:97:55 | ...: ...::Path::<...> | semmle.label | ...: ...::Path::<...> | +| test.rs:98:13:98:13 | a | semmle.label | a | +| test.rs:98:17:98:20 | path | semmle.label | path | +| test.rs:98:17:98:33 | path.into_inner() | semmle.label | path.into_inner() | +| test.rs:99:14:99:14 | a | semmle.label | a | +| test.rs:99:14:99:23 | a.as_str() | semmle.label | a.as_str() | +| test.rs:100:14:100:14 | a | semmle.label | a | +| test.rs:100:14:100:25 | a.as_bytes() | semmle.label | a.as_bytes() | | test.rs:101:14:101:14 | a | semmle.label | a | -| test.rs:101:14:101:23 | a.as_str() | semmle.label | a.as_str() | -| test.rs:102:14:102:14 | a | semmle.label | a | -| test.rs:102:14:102:25 | a.as_bytes() | semmle.label | a.as_bytes() | -| test.rs:103:14:103:14 | a | semmle.label | a | -| test.rs:109:9:109:41 | ...: ...::Path::<...> | semmle.label | ...: ...::Path::<...> | -| test.rs:111:13:111:18 | TuplePat | semmle.label | TuplePat | -| test.rs:111:22:111:25 | path | semmle.label | path | -| test.rs:111:22:111:38 | path.into_inner() | semmle.label | path.into_inner() | -| test.rs:113:14:113:14 | a | semmle.label | a | -| test.rs:114:14:114:14 | b | semmle.label | b | -| test.rs:120:9:120:41 | ...: ...::Query::<...> | semmle.label | ...: ...::Query::<...> | -| test.rs:122:14:122:14 | a | semmle.label | a | -| test.rs:127:5:127:20 | to | semmle.label | to | -| test.rs:129:9:129:31 | ...: ...::Path::<...> | semmle.label | ...: ...::Path::<...> | -| test.rs:131:13:131:13 | a | semmle.label | a | -| test.rs:131:17:131:20 | path | semmle.label | path | -| test.rs:131:17:131:33 | path.into_inner() | semmle.label | path.into_inner() | -| test.rs:132:14:132:14 | a | semmle.label | a | -| test.rs:139:41:139:42 | to | semmle.label | to | -| test.rs:140:45:140:46 | to | semmle.label | to | -| test.rs:141:41:141:42 | to | semmle.label | to | -| test.rs:242:33:242:35 | map | semmle.label | map | -| test.rs:242:38:242:46 | ...: String | semmle.label | ...: String | -| test.rs:244:18:244:18 | a | semmle.label | a | -| test.rs:250:46:250:49 | then | semmle.label | then | -| test.rs:251:25:251:33 | ...: String | semmle.label | ...: String | -| test.rs:252:22:252:22 | a | semmle.label | a | -| test.rs:259:50:259:57 | and_then | semmle.label | and_then | -| test.rs:260:26:260:32 | ...: u64 | semmle.label | ...: u64 | -| test.rs:263:22:263:23 | id | semmle.label | id | -| test.rs:272:75:272:77 | map | semmle.label | map | -| test.rs:273:15:273:23 | ...: String | semmle.label | ...: String | -| test.rs:275:22:275:22 | a | semmle.label | a | +| test.rs:106:33:106:65 | ...: ...::Path::<...> | semmle.label | ...: ...::Path::<...> | +| test.rs:107:13:107:18 | TuplePat | semmle.label | TuplePat | +| test.rs:107:22:107:25 | path | semmle.label | path | +| test.rs:107:22:107:38 | path.into_inner() | semmle.label | path.into_inner() | +| test.rs:109:14:109:14 | a | semmle.label | a | +| test.rs:110:14:110:14 | b | semmle.label | b | +| test.rs:115:33:115:65 | ...: ...::Query::<...> | semmle.label | ...: ...::Query::<...> | +| test.rs:116:14:116:14 | a | semmle.label | a | +| test.rs:121:5:121:20 | to | semmle.label | to | +| test.rs:122:33:122:55 | ...: ...::Path::<...> | semmle.label | ...: ...::Path::<...> | +| test.rs:123:13:123:13 | a | semmle.label | a | +| test.rs:123:17:123:20 | path | semmle.label | path | +| test.rs:123:17:123:33 | path.into_inner() | semmle.label | path.into_inner() | +| test.rs:124:14:124:14 | a | semmle.label | a | +| test.rs:131:41:131:42 | to | semmle.label | to | +| test.rs:132:45:132:46 | to | semmle.label | to | +| test.rs:133:41:133:42 | to | semmle.label | to | +| test.rs:222:33:222:35 | map | semmle.label | map | +| test.rs:222:38:222:46 | ...: String | semmle.label | ...: String | +| test.rs:224:18:224:18 | a | semmle.label | a | +| test.rs:230:46:230:49 | then | semmle.label | then | +| test.rs:231:25:231:33 | ...: String | semmle.label | ...: String | +| test.rs:232:22:232:22 | a | semmle.label | a | +| test.rs:239:50:239:57 | and_then | semmle.label | and_then | +| test.rs:240:26:240:32 | ...: u64 | semmle.label | ...: u64 | +| test.rs:243:22:243:23 | id | semmle.label | id | +| test.rs:252:75:252:77 | map | semmle.label | map | +| test.rs:253:15:253:23 | ...: String | semmle.label | ...: String | +| test.rs:255:22:255:22 | a | semmle.label | a | subpaths testFailures #select @@ -119,14 +119,14 @@ testFailures | test.rs:60:14:60:17 | ms.a | test.rs:58:14:58:15 | ms | test.rs:60:14:60:17 | ms.a | $@ | test.rs:58:14:58:15 | ms | ms | | test.rs:61:14:61:17 | ms.b | test.rs:58:14:58:15 | ms | test.rs:61:14:61:17 | ms.b | $@ | test.rs:58:14:58:15 | ms | ms | | test.rs:70:14:70:14 | a | test.rs:68:15:68:15 | a | test.rs:70:14:70:14 | a | $@ | test.rs:68:15:68:15 | a | a | -| test.rs:101:14:101:23 | a.as_str() | test.rs:139:41:139:42 | to | test.rs:101:14:101:23 | a.as_str() | $@ | test.rs:139:41:139:42 | to | to | -| test.rs:102:14:102:25 | a.as_bytes() | test.rs:139:41:139:42 | to | test.rs:102:14:102:25 | a.as_bytes() | $@ | test.rs:139:41:139:42 | to | to | -| test.rs:103:14:103:14 | a | test.rs:139:41:139:42 | to | test.rs:103:14:103:14 | a | $@ | test.rs:139:41:139:42 | to | to | -| test.rs:113:14:113:14 | a | test.rs:140:45:140:46 | to | test.rs:113:14:113:14 | a | $@ | test.rs:140:45:140:46 | to | to | -| test.rs:114:14:114:14 | b | test.rs:140:45:140:46 | to | test.rs:114:14:114:14 | b | $@ | test.rs:140:45:140:46 | to | to | -| test.rs:122:14:122:14 | a | test.rs:141:41:141:42 | to | test.rs:122:14:122:14 | a | $@ | test.rs:141:41:141:42 | to | to | -| test.rs:132:14:132:14 | a | test.rs:127:5:127:20 | to | test.rs:132:14:132:14 | a | $@ | test.rs:127:5:127:20 | to | to | -| test.rs:244:18:244:18 | a | test.rs:242:33:242:35 | map | test.rs:244:18:244:18 | a | $@ | test.rs:242:33:242:35 | map | map | -| test.rs:252:22:252:22 | a | test.rs:250:46:250:49 | then | test.rs:252:22:252:22 | a | $@ | test.rs:250:46:250:49 | then | then | -| test.rs:263:22:263:23 | id | test.rs:259:50:259:57 | and_then | test.rs:263:22:263:23 | id | $@ | test.rs:259:50:259:57 | and_then | and_then | -| test.rs:275:22:275:22 | a | test.rs:272:75:272:77 | map | test.rs:275:22:275:22 | a | $@ | test.rs:272:75:272:77 | map | map | +| test.rs:99:14:99:23 | a.as_str() | test.rs:131:41:131:42 | to | test.rs:99:14:99:23 | a.as_str() | $@ | test.rs:131:41:131:42 | to | to | +| test.rs:100:14:100:25 | a.as_bytes() | test.rs:131:41:131:42 | to | test.rs:100:14:100:25 | a.as_bytes() | $@ | test.rs:131:41:131:42 | to | to | +| test.rs:101:14:101:14 | a | test.rs:131:41:131:42 | to | test.rs:101:14:101:14 | a | $@ | test.rs:131:41:131:42 | to | to | +| test.rs:109:14:109:14 | a | test.rs:132:45:132:46 | to | test.rs:109:14:109:14 | a | $@ | test.rs:132:45:132:46 | to | to | +| test.rs:110:14:110:14 | b | test.rs:132:45:132:46 | to | test.rs:110:14:110:14 | b | $@ | test.rs:132:45:132:46 | to | to | +| test.rs:116:14:116:14 | a | test.rs:133:41:133:42 | to | test.rs:116:14:116:14 | a | $@ | test.rs:133:41:133:42 | to | to | +| test.rs:124:14:124:14 | a | test.rs:121:5:121:20 | to | test.rs:124:14:124:14 | a | $@ | test.rs:121:5:121:20 | to | to | +| test.rs:224:18:224:18 | a | test.rs:222:33:222:35 | map | test.rs:224:18:224:18 | a | $@ | test.rs:222:33:222:35 | map | map | +| test.rs:232:22:232:22 | a | test.rs:230:46:230:49 | then | test.rs:232:22:232:22 | a | $@ | test.rs:230:46:230:49 | then | then | +| test.rs:243:22:243:23 | id | test.rs:239:50:239:57 | and_then | test.rs:243:22:243:23 | id | $@ | test.rs:239:50:239:57 | and_then | and_then | +| test.rs:255:22:255:22 | a | test.rs:252:75:252:77 | map | test.rs:255:22:255:22 | a | $@ | test.rs:252:75:252:77 | map | map | diff --git a/rust/ql/test/library-tests/dataflow/sources/web_frameworks/TaintSources.expected b/rust/ql/test/library-tests/dataflow/sources/web_frameworks/TaintSources.expected index 20a20ce3f9b1..660eb7d12fa9 100644 --- a/rust/ql/test/library-tests/dataflow/sources/web_frameworks/TaintSources.expected +++ b/rust/ql/test/library-tests/dataflow/sources/web_frameworks/TaintSources.expected @@ -3,67 +3,67 @@ | test.rs:48:14:48:30 | MyStruct {...} | Flow source 'RemoteSource' of type remote (DEFAULT). | | test.rs:58:14:58:15 | ms | Flow source 'RemoteSource' of type remote (DEFAULT). | | test.rs:68:15:68:15 | a | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:127:5:127:20 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:127:5:127:20 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:127:5:127:20 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:127:5:127:20 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:127:5:127:20 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:127:5:127:20 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:127:5:127:20 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:127:5:127:20 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:139:41:139:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:139:41:139:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:139:41:139:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:139:41:139:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:139:41:139:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:139:41:139:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:139:41:139:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:139:41:139:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:140:45:140:46 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:140:45:140:46 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:140:45:140:46 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:140:45:140:46 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:140:45:140:46 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:140:45:140:46 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:140:45:140:46 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:140:45:140:46 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:141:41:141:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:141:41:141:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:141:41:141:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:141:41:141:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:141:41:141:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:141:41:141:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:141:41:141:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:141:41:141:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:242:33:242:35 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:242:33:242:35 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:242:33:242:35 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:242:33:242:35 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:242:33:242:35 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:242:33:242:35 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:242:33:242:35 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:242:33:242:35 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:250:46:250:49 | then | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:250:46:250:49 | then | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:250:46:250:49 | then | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:250:46:250:49 | then | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:250:46:250:49 | then | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:250:46:250:49 | then | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:250:46:250:49 | then | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:250:46:250:49 | then | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:259:50:259:57 | and_then | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:259:50:259:57 | and_then | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:259:50:259:57 | and_then | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:259:50:259:57 | and_then | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:259:50:259:57 | and_then | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:259:50:259:57 | and_then | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:259:50:259:57 | and_then | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:259:50:259:57 | and_then | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:272:75:272:77 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:272:75:272:77 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:272:75:272:77 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:272:75:272:77 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:272:75:272:77 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:272:75:272:77 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:272:75:272:77 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:272:75:272:77 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:121:5:121:20 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:121:5:121:20 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:121:5:121:20 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:121:5:121:20 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:121:5:121:20 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:121:5:121:20 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:121:5:121:20 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:121:5:121:20 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:131:41:131:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:131:41:131:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:131:41:131:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:131:41:131:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:131:41:131:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:131:41:131:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:131:41:131:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:131:41:131:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:132:45:132:46 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:132:45:132:46 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:132:45:132:46 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:132:45:132:46 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:132:45:132:46 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:132:45:132:46 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:132:45:132:46 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:132:45:132:46 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:133:41:133:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:133:41:133:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:133:41:133:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:133:41:133:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:133:41:133:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:133:41:133:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:133:41:133:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:133:41:133:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:222:33:222:35 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:222:33:222:35 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:222:33:222:35 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:222:33:222:35 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:222:33:222:35 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:222:33:222:35 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:222:33:222:35 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:222:33:222:35 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:230:46:230:49 | then | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:230:46:230:49 | then | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:230:46:230:49 | then | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:230:46:230:49 | then | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:230:46:230:49 | then | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:230:46:230:49 | then | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:230:46:230:49 | then | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:230:46:230:49 | then | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:239:50:239:57 | and_then | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:239:50:239:57 | and_then | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:239:50:239:57 | and_then | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:239:50:239:57 | and_then | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:239:50:239:57 | and_then | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:239:50:239:57 | and_then | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:239:50:239:57 | and_then | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:239:50:239:57 | and_then | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:252:75:252:77 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:252:75:252:77 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:252:75:252:77 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:252:75:252:77 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:252:75:252:77 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:252:75:252:77 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:252:75:252:77 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:252:75:252:77 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | diff --git a/rust/ql/test/library-tests/dataflow/sources/web_frameworks/test.rs b/rust/ql/test/library-tests/dataflow/sources/web_frameworks/test.rs index 124f7615ef1d..8033560bef5b 100644 --- a/rust/ql/test/library-tests/dataflow/sources/web_frameworks/test.rs +++ b/rust/ql/test/library-tests/dataflow/sources/web_frameworks/test.rs @@ -94,9 +94,7 @@ mod actix_test { use super::sink; use actix_web::{get, web, App}; - async fn my_actix_handler_1( - path: web::Path, - ) -> String { + async fn my_actix_handler_1(path: web::Path) -> String { let a = path.into_inner(); sink(a.as_str()); // $ hasTaintFlow=my_actix_handler_1 sink(a.as_bytes()); // $ hasTaintFlow=my_actix_handler_1 @@ -105,9 +103,7 @@ mod actix_test { "".to_string() } - async fn my_actix_handler_2( - path: web::Path<(String, String)>, - ) -> String { + async fn my_actix_handler_2(path: web::Path<(String, String)>) -> String { let (a, b) = path.into_inner(); sink(a); // $ hasTaintFlow=my_actix_handler_2 @@ -116,18 +112,14 @@ mod actix_test { "".to_string() } - async fn my_actix_handler_3( - web::Query(a): web::Query, - ) -> String { + async fn my_actix_handler_3(web::Query(a): web::Query) -> String { sink(a); // $ hasTaintFlow=my_actix_handler_3 "".to_string() } #[get("/4/{a}")] // $ Alert[rust/summary/taint-sources] - async fn my_actix_handler_4( - path: web::Path, - ) -> String { + async fn my_actix_handler_4(path: web::Path) -> String { let a = path.into_inner(); sink(a); // $ hasTaintFlow=my_actix_handler_4 @@ -148,43 +140,35 @@ mod actix_test { mod axum_test { use super::sink; use axum::extract::{Json, Path, Query, Request}; - use axum::routing::get; + use axum::routing::{get, post, put, MethodFilter}; use axum::Router; use std::collections::HashMap; - async fn my_axum_handler_1( - Path(a): Path, // $ MISSING: Alert[rust/summary/taint-sources] - ) -> &'static str { - sink(a.as_str()); // $ MISSING: hasTaintFlow - sink(a.as_bytes()); // $ MISSING: hasTaintFlow - sink(a); // $ MISSING: hasTaintFlow + async fn my_axum_handler_1(Path(a): Path) -> &'static str { + sink(a.as_str()); // $ MISSING: hasTaintFlow=my_axum_handler_1 + sink(a.as_bytes()); // $ MISSING: hasTaintFlow=my_axum_handler_1 + sink(a); // $ MISSING: hasTaintFlow=my_axum_handler_1 "" } - async fn my_axum_handler_2( - Path((a, b)): Path<(String, String)>, // $ MISSING: Alert[rust/summary/taint-sources] - ) -> &'static str { - sink(a); // $ MISSING: hasTaintFlow - sink(b); // $ MISSING: hasTaintFlow + async fn my_axum_handler_2(Path((a, b)): Path<(String, String)>) -> &'static str { + sink(a); // $ MISSING: hasTaintFlow=my_axum_handler_2 + sink(b); // $ MISSING: hasTaintFlow=my_axum_handler_2 "" } - async fn my_axum_handler_3( - Query(params): Query>, // $ MISSING: Alert[rust/summary/taint-sources] - ) -> &'static str { + async fn my_axum_handler_3(Query(params): Query>) -> &'static str { for (key, value) in params { - sink(key); // $ MISSING: hasTaintFlow - sink(value); // $ MISSING: hasTaintFlow + sink(key); // $ MISSING: hasTaintFlow=my_axum_handler_3 + sink(value); // $ MISSING: hasTaintFlow=my_axum_handler_3 } "" } - async fn my_axum_handler_4( - request: Request, // $ MISSING: Alert[rust/summary/taint-sources] - ) -> &'static str { + async fn my_axum_handler_4(request: Request) -> &'static str { sink(request.body()); // $ MISSING: hasTaintFlow request.headers().get("header").unwrap(); // $ MISSING: hasTaintFlow sink(request.into_body()); // $ MISSING: hasTaintFlow @@ -192,39 +176,35 @@ mod axum_test { "" } - async fn my_axum_handler_5( - Json(payload): Json, // $ MISSING: Alert[rust/summary/taint-sources] - ) -> &'static str { + async fn my_axum_handler_5(Json(payload): Json) -> &'static str { sink(payload.as_str()); // $ MISSING: hasTaintFlow - sink(payload); // $ MISSING: hasTaintFlow + sink(payload); // $ MISSING: hasTaintFlow=...::DELETE "" } - async fn my_axum_handler_6( - body: String, // $ MISSING: Alert[rust/summary/taint-sources] - ) -> &'static str { - sink(body); // $ MISSING: hasTaintFlow + async fn my_axum_handler_6(body: String) -> &'static str { + sink(body); // $ MISSING: hasTaintFlow=my_axum_handler_6 "" } - async fn my_axum_handler_7( - body: String, // $ MISSING: Alert[rust/summary/taint-sources] - ) -> &'static str { - sink(body); // $ MISSING: hasTaintFlow + async fn my_axum_handler_7(body: String) -> &'static str { + sink(body); // $ MISSING: hasTaintFlow=my_axum_handler_7 "" } async fn test_axum() { let app = Router::<()>::new() - .route("/1/{a}", get(my_axum_handler_1)) - .route("/2/{a}/{b}", get(my_axum_handler_2)) - .route("/3/:a", get(my_axum_handler_3)) - .route("/4/:a", get(my_axum_handler_4)) - .route("/5/:a", get(my_axum_handler_5)) - .route("/67/:a", get(my_axum_handler_6).get(my_axum_handler_7)); + .route("/1/{a}", get(my_axum_handler_1)) // $ MISSING: Alert[rust/summary/taint-sources]) + .route("/2/{a}/{b}", post(my_axum_handler_2)) // $ MISSING: Alert[rust/summary/taint-sources]) + .route("/3/:a", put(my_axum_handler_3)) // $ MISSING: Alert[rust/summary/taint-sources]) + .route( + "/4/:a", + get(my_axum_handler_4).on(MethodFilter::DELETE, my_axum_handler_5), // $ MISSING: Alert[rust/summary/taint-sources]) + ) + .route("/5/:a", get(my_axum_handler_6).get(my_axum_handler_7)); // $ MISSING: Alert[rust/summary/taint-sources]) // ... } From fbf9f7eda732dc7f1eb7990a85084dfc15c6e2e9 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Tue, 16 Dec 2025 12:41:32 +0100 Subject: [PATCH 2/5] Rust: Add models for Axum --- .../lib/codeql/rust/frameworks/axum.model.yml | 23 ++++++ .../web_frameworks/InlineFlow.expected | 77 ++++++++++++++++--- .../web_frameworks/TaintSources.expected | 56 ++++++++++++++ .../dataflow/sources/web_frameworks/test.rs | 30 ++++---- 4 files changed, 161 insertions(+), 25 deletions(-) create mode 100644 rust/ql/lib/codeql/rust/frameworks/axum.model.yml diff --git a/rust/ql/lib/codeql/rust/frameworks/axum.model.yml b/rust/ql/lib/codeql/rust/frameworks/axum.model.yml new file mode 100644 index 000000000000..7ae7dec36359 --- /dev/null +++ b/rust/ql/lib/codeql/rust/frameworks/axum.model.yml @@ -0,0 +1,23 @@ +extensions: + - addsTo: + pack: codeql/rust-all + extensible: sourceModel + data: + # Get + - ["axum::routing::method_routing::get", "Argument[0].Parameter[0..7]", "remote", "manual"] + - ["::get", "Argument[0].Parameter[0..7]", "remote", "manual"] + # Post + - ["axum::routing::method_routing::post", "Argument[0].Parameter[0..7]", "remote", "manual"] + - ["::post", "Argument[0].Parameter[0..7]", "remote", "manual"] + # Put + - ["axum::routing::method_routing::put", "Argument[0].Parameter[0..7]", "remote", "manual"] + - ["::put", "Argument[0].Parameter[0..7]", "remote", "manual"] + # Delete + - ["axum::routing::method_routing::delete", "Argument[0].Parameter[0..7]", "remote", "manual"] + - ["::delete", "Argument[0].Parameter[0..7]", "remote", "manual"] + # Patch + - ["axum::routing::method_routing::patch", "Argument[0].Parameter[0..7]", "remote", "manual"] + - ["::patch", "Argument[0].Parameter[0..7]", "remote", "manual"] + # on + - ["axum::routing::method_routing::on", "Argument[1].Parameter[0..7]", "remote", "manual"] + - ["::on", "Argument[1].Parameter[0..7]", "remote", "manual"] \ No newline at end of file diff --git a/rust/ql/test/library-tests/dataflow/sources/web_frameworks/InlineFlow.expected b/rust/ql/test/library-tests/dataflow/sources/web_frameworks/InlineFlow.expected index dce59fc29b70..4c85f166699a 100644 --- a/rust/ql/test/library-tests/dataflow/sources/web_frameworks/InlineFlow.expected +++ b/rust/ql/test/library-tests/dataflow/sources/web_frameworks/InlineFlow.expected @@ -4,15 +4,20 @@ models | 3 | Source: <_ as warp::filter::Filter>::then; Argument[0].Parameter[0..7]; remote | | 4 | Source: ::to; Argument[0].Parameter[0..7]; remote | | 5 | Source: ::to; Argument[0].Parameter[0..7]; remote | -| 6 | Summary: ::into_inner; Argument[self]; ReturnValue; taint | -| 7 | Summary: ::as_bytes; Argument[self]; ReturnValue; value | -| 8 | Summary: ::as_str; Argument[self]; ReturnValue; value | +| 6 | Source: ::get; Argument[0].Parameter[0..7]; remote | +| 7 | Source: ::on; Argument[1].Parameter[0..7]; remote | +| 8 | Source: axum::routing::method_routing::get; Argument[0].Parameter[0..7]; remote | +| 9 | Source: axum::routing::method_routing::post; Argument[0].Parameter[0..7]; remote | +| 10 | Source: axum::routing::method_routing::put; Argument[0].Parameter[0..7]; remote | +| 11 | Summary: ::into_inner; Argument[self]; ReturnValue; taint | +| 12 | Summary: ::as_bytes; Argument[self]; ReturnValue; value | +| 13 | Summary: ::as_str; Argument[self]; ReturnValue; value | edges | test.rs:11:31:11:31 | a | test.rs:13:14:13:14 | a | provenance | | | test.rs:11:31:11:31 | a | test.rs:14:14:14:14 | a | provenance | | | test.rs:11:31:11:31 | a | test.rs:15:14:15:14 | a | provenance | | -| test.rs:13:14:13:14 | a | test.rs:13:14:13:23 | a.as_str() | provenance | MaD:8 | -| test.rs:14:14:14:14 | a | test.rs:14:14:14:25 | a.as_bytes() | provenance | MaD:7 | +| test.rs:13:14:13:14 | a | test.rs:13:14:13:23 | a.as_str() | provenance | MaD:13 | +| test.rs:14:14:14:14 | a | test.rs:14:14:14:25 | a.as_bytes() | provenance | MaD:12 | | test.rs:22:14:22:19 | TuplePat | test.rs:24:14:24:14 | a | provenance | | | test.rs:22:14:22:19 | TuplePat | test.rs:25:14:25:14 | b | provenance | | | test.rs:48:14:48:30 | MyStruct {...} | test.rs:50:14:50:14 | a | provenance | | @@ -24,24 +29,42 @@ edges | test.rs:98:13:98:13 | a | test.rs:99:14:99:14 | a | provenance | | | test.rs:98:13:98:13 | a | test.rs:100:14:100:14 | a | provenance | | | test.rs:98:13:98:13 | a | test.rs:101:14:101:14 | a | provenance | | -| test.rs:98:17:98:20 | path | test.rs:98:17:98:33 | path.into_inner() | provenance | MaD:6 | +| test.rs:98:17:98:20 | path | test.rs:98:17:98:33 | path.into_inner() | provenance | MaD:11 | | test.rs:98:17:98:33 | path.into_inner() | test.rs:98:13:98:13 | a | provenance | | -| test.rs:99:14:99:14 | a | test.rs:99:14:99:23 | a.as_str() | provenance | MaD:8 | -| test.rs:100:14:100:14 | a | test.rs:100:14:100:25 | a.as_bytes() | provenance | MaD:7 | +| test.rs:99:14:99:14 | a | test.rs:99:14:99:23 | a.as_str() | provenance | MaD:13 | +| test.rs:100:14:100:14 | a | test.rs:100:14:100:25 | a.as_bytes() | provenance | MaD:12 | | test.rs:106:33:106:65 | ...: ...::Path::<...> | test.rs:107:22:107:25 | path | provenance | | | test.rs:107:13:107:18 | TuplePat | test.rs:109:14:109:14 | a | provenance | | | test.rs:107:13:107:18 | TuplePat | test.rs:110:14:110:14 | b | provenance | | -| test.rs:107:22:107:25 | path | test.rs:107:22:107:38 | path.into_inner() | provenance | MaD:6 | +| test.rs:107:22:107:25 | path | test.rs:107:22:107:38 | path.into_inner() | provenance | MaD:11 | | test.rs:107:22:107:38 | path.into_inner() | test.rs:107:13:107:18 | TuplePat | provenance | | | test.rs:115:33:115:65 | ...: ...::Query::<...> | test.rs:116:14:116:14 | a | provenance | | | test.rs:121:5:121:20 | to | test.rs:122:33:122:55 | ...: ...::Path::<...> | provenance | Src:MaD:4 | | test.rs:122:33:122:55 | ...: ...::Path::<...> | test.rs:123:17:123:20 | path | provenance | | | test.rs:123:13:123:13 | a | test.rs:124:14:124:14 | a | provenance | | -| test.rs:123:17:123:20 | path | test.rs:123:17:123:33 | path.into_inner() | provenance | MaD:6 | +| test.rs:123:17:123:20 | path | test.rs:123:17:123:33 | path.into_inner() | provenance | MaD:11 | | test.rs:123:17:123:33 | path.into_inner() | test.rs:123:13:123:13 | a | provenance | | | test.rs:131:41:131:42 | to | test.rs:97:33:97:55 | ...: ...::Path::<...> | provenance | Src:MaD:5 | | test.rs:132:45:132:46 | to | test.rs:106:33:106:65 | ...: ...::Path::<...> | provenance | Src:MaD:5 | | test.rs:133:41:133:42 | to | test.rs:115:33:115:65 | ...: ...::Query::<...> | provenance | Src:MaD:5 | +| test.rs:147:32:147:52 | ...: Path::<...> | test.rs:148:14:148:14 | a | provenance | | +| test.rs:147:32:147:52 | ...: Path::<...> | test.rs:149:14:149:14 | a | provenance | | +| test.rs:147:32:147:52 | ...: Path::<...> | test.rs:150:14:150:14 | a | provenance | | +| test.rs:148:14:148:14 | a | test.rs:148:14:148:23 | a.as_str() | provenance | MaD:13 | +| test.rs:149:14:149:14 | a | test.rs:149:14:149:25 | a.as_bytes() | provenance | MaD:12 | +| test.rs:155:32:155:67 | ...: Path::<...> | test.rs:156:14:156:14 | a | provenance | | +| test.rs:155:32:155:67 | ...: Path::<...> | test.rs:157:14:157:14 | b | provenance | | +| test.rs:162:32:162:76 | ...: Query::<...> | test.rs:164:18:164:20 | key | provenance | | +| test.rs:162:32:162:76 | ...: Query::<...> | test.rs:165:18:165:22 | value | provenance | | +| test.rs:179:32:179:69 | ...: Json::<...> | test.rs:181:14:181:20 | payload | provenance | | +| test.rs:186:32:186:43 | ...: String | test.rs:187:14:187:17 | body | provenance | | +| test.rs:192:32:192:43 | ...: String | test.rs:193:14:193:17 | body | provenance | | +| test.rs:200:30:200:32 | get | test.rs:147:32:147:52 | ...: Path::<...> | provenance | Src:MaD:8 | +| test.rs:201:34:201:37 | post | test.rs:155:32:155:67 | ...: Path::<...> | provenance | Src:MaD:9 | +| test.rs:202:29:202:31 | put | test.rs:162:32:162:76 | ...: Query::<...> | provenance | Src:MaD:10 | +| test.rs:205:40:205:41 | on | test.rs:179:32:179:69 | ...: Json::<...> | provenance | Src:MaD:7 | +| test.rs:207:29:207:31 | get | test.rs:186:32:186:43 | ...: String | provenance | Src:MaD:8 | +| test.rs:207:52:207:54 | get | test.rs:192:32:192:43 | ...: String | provenance | Src:MaD:6 | | test.rs:222:33:222:35 | map | test.rs:222:38:222:46 | ...: String | provenance | Src:MaD:2 | | test.rs:222:38:222:46 | ...: String | test.rs:224:18:224:18 | a | provenance | | | test.rs:230:46:230:49 | then | test.rs:231:25:231:33 | ...: String | provenance | Src:MaD:3 | @@ -94,6 +117,30 @@ nodes | test.rs:131:41:131:42 | to | semmle.label | to | | test.rs:132:45:132:46 | to | semmle.label | to | | test.rs:133:41:133:42 | to | semmle.label | to | +| test.rs:147:32:147:52 | ...: Path::<...> | semmle.label | ...: Path::<...> | +| test.rs:148:14:148:14 | a | semmle.label | a | +| test.rs:148:14:148:23 | a.as_str() | semmle.label | a.as_str() | +| test.rs:149:14:149:14 | a | semmle.label | a | +| test.rs:149:14:149:25 | a.as_bytes() | semmle.label | a.as_bytes() | +| test.rs:150:14:150:14 | a | semmle.label | a | +| test.rs:155:32:155:67 | ...: Path::<...> | semmle.label | ...: Path::<...> | +| test.rs:156:14:156:14 | a | semmle.label | a | +| test.rs:157:14:157:14 | b | semmle.label | b | +| test.rs:162:32:162:76 | ...: Query::<...> | semmle.label | ...: Query::<...> | +| test.rs:164:18:164:20 | key | semmle.label | key | +| test.rs:165:18:165:22 | value | semmle.label | value | +| test.rs:179:32:179:69 | ...: Json::<...> | semmle.label | ...: Json::<...> | +| test.rs:181:14:181:20 | payload | semmle.label | payload | +| test.rs:186:32:186:43 | ...: String | semmle.label | ...: String | +| test.rs:187:14:187:17 | body | semmle.label | body | +| test.rs:192:32:192:43 | ...: String | semmle.label | ...: String | +| test.rs:193:14:193:17 | body | semmle.label | body | +| test.rs:200:30:200:32 | get | semmle.label | get | +| test.rs:201:34:201:37 | post | semmle.label | post | +| test.rs:202:29:202:31 | put | semmle.label | put | +| test.rs:205:40:205:41 | on | semmle.label | on | +| test.rs:207:29:207:31 | get | semmle.label | get | +| test.rs:207:52:207:54 | get | semmle.label | get | | test.rs:222:33:222:35 | map | semmle.label | map | | test.rs:222:38:222:46 | ...: String | semmle.label | ...: String | | test.rs:224:18:224:18 | a | semmle.label | a | @@ -126,6 +173,16 @@ testFailures | test.rs:110:14:110:14 | b | test.rs:132:45:132:46 | to | test.rs:110:14:110:14 | b | $@ | test.rs:132:45:132:46 | to | to | | test.rs:116:14:116:14 | a | test.rs:133:41:133:42 | to | test.rs:116:14:116:14 | a | $@ | test.rs:133:41:133:42 | to | to | | test.rs:124:14:124:14 | a | test.rs:121:5:121:20 | to | test.rs:124:14:124:14 | a | $@ | test.rs:121:5:121:20 | to | to | +| test.rs:148:14:148:23 | a.as_str() | test.rs:200:30:200:32 | get | test.rs:148:14:148:23 | a.as_str() | $@ | test.rs:200:30:200:32 | get | get | +| test.rs:149:14:149:25 | a.as_bytes() | test.rs:200:30:200:32 | get | test.rs:149:14:149:25 | a.as_bytes() | $@ | test.rs:200:30:200:32 | get | get | +| test.rs:150:14:150:14 | a | test.rs:200:30:200:32 | get | test.rs:150:14:150:14 | a | $@ | test.rs:200:30:200:32 | get | get | +| test.rs:156:14:156:14 | a | test.rs:201:34:201:37 | post | test.rs:156:14:156:14 | a | $@ | test.rs:201:34:201:37 | post | post | +| test.rs:157:14:157:14 | b | test.rs:201:34:201:37 | post | test.rs:157:14:157:14 | b | $@ | test.rs:201:34:201:37 | post | post | +| test.rs:164:18:164:20 | key | test.rs:202:29:202:31 | put | test.rs:164:18:164:20 | key | $@ | test.rs:202:29:202:31 | put | put | +| test.rs:165:18:165:22 | value | test.rs:202:29:202:31 | put | test.rs:165:18:165:22 | value | $@ | test.rs:202:29:202:31 | put | put | +| test.rs:181:14:181:20 | payload | test.rs:205:40:205:41 | on | test.rs:181:14:181:20 | payload | $@ | test.rs:205:40:205:41 | on | on | +| test.rs:187:14:187:17 | body | test.rs:207:29:207:31 | get | test.rs:187:14:187:17 | body | $@ | test.rs:207:29:207:31 | get | get | +| test.rs:193:14:193:17 | body | test.rs:207:52:207:54 | get | test.rs:193:14:193:17 | body | $@ | test.rs:207:52:207:54 | get | get | | test.rs:224:18:224:18 | a | test.rs:222:33:222:35 | map | test.rs:224:18:224:18 | a | $@ | test.rs:222:33:222:35 | map | map | | test.rs:232:22:232:22 | a | test.rs:230:46:230:49 | then | test.rs:232:22:232:22 | a | $@ | test.rs:230:46:230:49 | then | then | | test.rs:243:22:243:23 | id | test.rs:239:50:239:57 | and_then | test.rs:243:22:243:23 | id | $@ | test.rs:239:50:239:57 | and_then | and_then | diff --git a/rust/ql/test/library-tests/dataflow/sources/web_frameworks/TaintSources.expected b/rust/ql/test/library-tests/dataflow/sources/web_frameworks/TaintSources.expected index 660eb7d12fa9..146406e7192c 100644 --- a/rust/ql/test/library-tests/dataflow/sources/web_frameworks/TaintSources.expected +++ b/rust/ql/test/library-tests/dataflow/sources/web_frameworks/TaintSources.expected @@ -35,6 +35,62 @@ | test.rs:133:41:133:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | | test.rs:133:41:133:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | | test.rs:133:41:133:42 | to | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:200:30:200:32 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:200:30:200:32 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:200:30:200:32 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:200:30:200:32 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:200:30:200:32 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:200:30:200:32 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:200:30:200:32 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:200:30:200:32 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:201:34:201:37 | post | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:201:34:201:37 | post | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:201:34:201:37 | post | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:201:34:201:37 | post | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:201:34:201:37 | post | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:201:34:201:37 | post | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:201:34:201:37 | post | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:201:34:201:37 | post | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:202:29:202:31 | put | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:202:29:202:31 | put | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:202:29:202:31 | put | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:202:29:202:31 | put | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:202:29:202:31 | put | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:202:29:202:31 | put | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:202:29:202:31 | put | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:202:29:202:31 | put | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:205:17:205:19 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:205:17:205:19 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:205:17:205:19 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:205:17:205:19 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:205:17:205:19 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:205:17:205:19 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:205:17:205:19 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:205:17:205:19 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:205:40:205:41 | on | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:205:40:205:41 | on | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:205:40:205:41 | on | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:205:40:205:41 | on | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:205:40:205:41 | on | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:205:40:205:41 | on | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:205:40:205:41 | on | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:205:40:205:41 | on | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:207:29:207:31 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:207:29:207:31 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:207:29:207:31 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:207:29:207:31 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:207:29:207:31 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:207:29:207:31 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:207:29:207:31 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:207:29:207:31 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:207:52:207:54 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:207:52:207:54 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:207:52:207:54 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:207:52:207:54 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:207:52:207:54 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:207:52:207:54 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:207:52:207:54 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:207:52:207:54 | get | Flow source 'RemoteSource' of type remote (DEFAULT). | | test.rs:222:33:222:35 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | | test.rs:222:33:222:35 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | | test.rs:222:33:222:35 | map | Flow source 'RemoteSource' of type remote (DEFAULT). | diff --git a/rust/ql/test/library-tests/dataflow/sources/web_frameworks/test.rs b/rust/ql/test/library-tests/dataflow/sources/web_frameworks/test.rs index 8033560bef5b..c6c487fed28d 100644 --- a/rust/ql/test/library-tests/dataflow/sources/web_frameworks/test.rs +++ b/rust/ql/test/library-tests/dataflow/sources/web_frameworks/test.rs @@ -145,24 +145,24 @@ mod axum_test { use std::collections::HashMap; async fn my_axum_handler_1(Path(a): Path) -> &'static str { - sink(a.as_str()); // $ MISSING: hasTaintFlow=my_axum_handler_1 - sink(a.as_bytes()); // $ MISSING: hasTaintFlow=my_axum_handler_1 - sink(a); // $ MISSING: hasTaintFlow=my_axum_handler_1 + sink(a.as_str()); // $ hasTaintFlow=my_axum_handler_1 + sink(a.as_bytes()); // $ hasTaintFlow=my_axum_handler_1 + sink(a); // $ hasTaintFlow=my_axum_handler_1 "" } async fn my_axum_handler_2(Path((a, b)): Path<(String, String)>) -> &'static str { - sink(a); // $ MISSING: hasTaintFlow=my_axum_handler_2 - sink(b); // $ MISSING: hasTaintFlow=my_axum_handler_2 + sink(a); // $ hasTaintFlow=my_axum_handler_2 + sink(b); // $ hasTaintFlow=my_axum_handler_2 "" } async fn my_axum_handler_3(Query(params): Query>) -> &'static str { for (key, value) in params { - sink(key); // $ MISSING: hasTaintFlow=my_axum_handler_3 - sink(value); // $ MISSING: hasTaintFlow=my_axum_handler_3 + sink(key); // $ hasTaintFlow=my_axum_handler_3 + sink(value); // $ hasTaintFlow=my_axum_handler_3 } "" @@ -178,33 +178,33 @@ mod axum_test { async fn my_axum_handler_5(Json(payload): Json) -> &'static str { sink(payload.as_str()); // $ MISSING: hasTaintFlow - sink(payload); // $ MISSING: hasTaintFlow=...::DELETE + sink(payload); // $ hasTaintFlow=...::DELETE "" } async fn my_axum_handler_6(body: String) -> &'static str { - sink(body); // $ MISSING: hasTaintFlow=my_axum_handler_6 + sink(body); // $ hasTaintFlow=my_axum_handler_6 "" } async fn my_axum_handler_7(body: String) -> &'static str { - sink(body); // $ MISSING: hasTaintFlow=my_axum_handler_7 + sink(body); // $ hasTaintFlow=my_axum_handler_7 "" } async fn test_axum() { let app = Router::<()>::new() - .route("/1/{a}", get(my_axum_handler_1)) // $ MISSING: Alert[rust/summary/taint-sources]) - .route("/2/{a}/{b}", post(my_axum_handler_2)) // $ MISSING: Alert[rust/summary/taint-sources]) - .route("/3/:a", put(my_axum_handler_3)) // $ MISSING: Alert[rust/summary/taint-sources]) + .route("/1/{a}", get(my_axum_handler_1)) // $ Alert[rust/summary/taint-sources]) + .route("/2/{a}/{b}", post(my_axum_handler_2)) // $ Alert[rust/summary/taint-sources]) + .route("/3/:a", put(my_axum_handler_3)) // $ Alert[rust/summary/taint-sources]) .route( "/4/:a", - get(my_axum_handler_4).on(MethodFilter::DELETE, my_axum_handler_5), // $ MISSING: Alert[rust/summary/taint-sources]) + get(my_axum_handler_4).on(MethodFilter::DELETE, my_axum_handler_5), // $ Alert[rust/summary/taint-sources]) ) - .route("/5/:a", get(my_axum_handler_6).get(my_axum_handler_7)); // $ MISSING: Alert[rust/summary/taint-sources]) + .route("/5/:a", get(my_axum_handler_6).get(my_axum_handler_7)); // $ Alert[rust/summary/taint-sources]) // ... } From cbdab994979a79d556aee6b04944a3a8aef81be0 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Tue, 16 Dec 2025 10:39:37 +0100 Subject: [PATCH 3/5] Rust: Add XSS sink for Axum HTML response creation --- .../codeql/rust/security/XssExtensions.qll | 10 ++++++++++ .../security/CWE-079/axum/XSS.expected | 20 +++++++++++++++++++ .../query-tests/security/CWE-079/axum/main.rs | 4 ++-- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/rust/ql/lib/codeql/rust/security/XssExtensions.qll b/rust/ql/lib/codeql/rust/security/XssExtensions.qll index cb0510cd7045..97318ff81737 100644 --- a/rust/ql/lib/codeql/rust/security/XssExtensions.qll +++ b/rust/ql/lib/codeql/rust/security/XssExtensions.qll @@ -59,4 +59,14 @@ module Xss { ) } } + + // TODO: Convert this to MaD once MaD supports sink for tuple struct expressions. + private class AxumHtmlSink extends Sink { + AxumHtmlSink() { + exists(TupleStructExpr call | + call.getResolvedTarget().getCanonicalPath() = "axum::response::Html" and + this.asExpr() = call.getSyntacticPositionalArgument(0) + ) + } + } } diff --git a/rust/ql/test/query-tests/security/CWE-079/axum/XSS.expected b/rust/ql/test/query-tests/security/CWE-079/axum/XSS.expected index 58f42bec0c84..385ce0f58c48 100644 --- a/rust/ql/test/query-tests/security/CWE-079/axum/XSS.expected +++ b/rust/ql/test/query-tests/security/CWE-079/axum/XSS.expected @@ -1,4 +1,24 @@ #select +| 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 | edges +| main.rs:8:24:8:59 | ...: Query::<...> | main.rs:9:32:9:63 | MacroExpr | provenance | | +| main.rs:9:9:9:20 | html_content | main.rs:10:10:10:21 | html_content | provenance | | +| main.rs:9:32:9:63 | ...::format(...) | main.rs:9:32:9:63 | { ... } | provenance | | +| main.rs:9:32:9:63 | ...::must_use(...) | main.rs:9:9:9:20 | html_content | provenance | | +| main.rs:9:32:9:63 | MacroExpr | main.rs:9:32:9:63 | ...::format(...) | provenance | MaD:2 | +| main.rs:9:32:9:63 | { ... } | main.rs:9:32:9:63 | ...::must_use(...) | provenance | MaD:3 | +| main.rs:15:51:15:53 | get | main.rs:8:24:8:59 | ...: Query::<...> | provenance | Src:MaD:1 | +models +| 1 | Source: axum::routing::method_routing::get; Argument[0].Parameter[0..7]; remote | +| 2 | Summary: alloc::fmt::format; Argument[0]; ReturnValue; taint | +| 3 | Summary: core::hint::must_use; Argument[0]; ReturnValue; value | nodes +| main.rs:8:24:8:59 | ...: Query::<...> | semmle.label | ...: Query::<...> | +| main.rs:9:9:9:20 | html_content | semmle.label | html_content | +| main.rs:9:32:9:63 | ...::format(...) | semmle.label | ...::format(...) | +| main.rs:9:32:9:63 | ...::must_use(...) | semmle.label | ...::must_use(...) | +| main.rs:9:32:9:63 | MacroExpr | semmle.label | MacroExpr | +| main.rs:9:32:9:63 | { ... } | semmle.label | { ... } | +| main.rs:10:10:10:21 | html_content | semmle.label | html_content | +| main.rs:15:51:15:53 | get | semmle.label | get | subpaths diff --git a/rust/ql/test/query-tests/security/CWE-079/axum/main.rs b/rust/ql/test/query-tests/security/CWE-079/axum/main.rs index 9379302a318a..27807c5883d9 100644 --- a/rust/ql/test/query-tests/security/CWE-079/axum/main.rs +++ b/rust/ql/test/query-tests/security/CWE-079/axum/main.rs @@ -7,12 +7,12 @@ struct GreetingParams { async fn greet_handler(Query(params): Query) -> Html { let html_content = format!("

Hello, {}!

", params.name); - Html(html_content) // $ MISSING: Alert[rust/xss] + Html(html_content) // $ Alert[rust/xss]=greet } #[tokio::main] pub async fn main() { - let app = Router::<()>::new().route("/greet", get(greet_handler)); + let app = Router::<()>::new().route("/greet", get(greet_handler)); // $ Source=greet let listener = tokio::net::TcpListener::bind("127.0.0.1:3000") .await .unwrap(); From e53bdb11be4ccb39903f729375ea87f63912965d Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Tue, 16 Dec 2025 13:15:34 +0100 Subject: [PATCH 4/5] Rust: Accept changes to expected files for consistency check --- .../CONSISTENCY/TypeInferenceConsistency.expected | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/ql/test/library-tests/dataflow/sources/web_frameworks/CONSISTENCY/TypeInferenceConsistency.expected b/rust/ql/test/library-tests/dataflow/sources/web_frameworks/CONSISTENCY/TypeInferenceConsistency.expected index 08edbe8c6121..f1bdb2cddbd6 100644 --- a/rust/ql/test/library-tests/dataflow/sources/web_frameworks/CONSISTENCY/TypeInferenceConsistency.expected +++ b/rust/ql/test/library-tests/dataflow/sources/web_frameworks/CONSISTENCY/TypeInferenceConsistency.expected @@ -1,4 +1,4 @@ nonUniqueCertainType -| test.rs:139:30:139:39 | ...::get(...) | | -| test.rs:140:34:140:43 | ...::get(...) | | -| test.rs:141:30:141:39 | ...::get(...) | | +| test.rs:131:30:131:39 | ...::get(...) | | +| test.rs:132:34:132:43 | ...::get(...) | | +| test.rs:133:30:133:39 | ...::get(...) | | From 420dd9ab61ce75c6c617a66c590198490fc03717 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Tue, 16 Dec 2025 15:15:22 +0100 Subject: [PATCH 5/5] Rust: Add change note for Axum models --- rust/ql/lib/change-notes/2025-12-16-axum-models.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 rust/ql/lib/change-notes/2025-12-16-axum-models.md diff --git a/rust/ql/lib/change-notes/2025-12-16-axum-models.md b/rust/ql/lib/change-notes/2025-12-16-axum-models.md new file mode 100644 index 000000000000..baa5910d799c --- /dev/null +++ b/rust/ql/lib/change-notes/2025-12-16-axum-models.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added models for the Axum web application framework. \ No newline at end of file