Skip to content

Commit 2d4369a

Browse files
committed
Rust: Add numeric type barrier for log injection.
1 parent 52397f0 commit 2d4369a

File tree

3 files changed

+10
-16
lines changed

3 files changed

+10
-16
lines changed

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ private import codeql.rust.dataflow.DataFlow
88
private import codeql.rust.dataflow.FlowSink
99
private import codeql.rust.Concepts
1010
private import codeql.util.Unit
11+
private import codeql.rust.security.Barriers as Barriers
1112

1213
/**
1314
* Provides default sources, sinks and barriers for detecting log injection
@@ -42,4 +43,10 @@ module LogInjection {
4243
private class ModelsAsDataSink extends Sink {
4344
ModelsAsDataSink() { sinkNode(this, "log-injection") }
4445
}
46+
47+
/**
48+
* A barrier for log injection vulnerabilities for nodes whose type is a
49+
* numeric or boolean type, which is unlikely to expose any vulnerability.
50+
*/
51+
private class NumericTypeBarrier extends Barrier instanceof Barriers::NumericTypeBarrier { }
4552
}

rust/ql/test/query-tests/security/CWE-117/LogInjection.expected

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
| main.rs:17:5:17:10 | ...::log | main.rs:11:23:11:44 | ...::get | main.rs:17:5:17:10 | ...::log | Log entry depends on a $@. | main.rs:11:23:11:44 | ...::get | user-provided value |
44
| main.rs:19:5:19:10 | ...::log | main.rs:10:22:10:34 | ...::var | main.rs:19:5:19:10 | ...::log | Log entry depends on a $@. | main.rs:10:22:10:34 | ...::var | user-provided value |
55
| main.rs:30:5:30:9 | ...::log | main.rs:11:23:11:44 | ...::get | main.rs:30:5:30:9 | ...::log | Log entry depends on a $@. | main.rs:11:23:11:44 | ...::get | user-provided value |
6-
| main.rs:49:5:49:9 | ...::log | main.rs:11:23:11:44 | ...::get | main.rs:49:5:49:9 | ...::log | Log entry depends on a $@. | main.rs:11:23:11:44 | ...::get | user-provided value |
76
| main.rs:112:9:112:13 | ...::log | main.rs:109:25:109:38 | ...::args | main.rs:112:9:112:13 | ...::log | Log entry depends on a $@. | main.rs:109:25:109:38 | ...::args | user-provided value |
87
| main.rs:113:9:113:13 | ...::log | main.rs:109:25:109:38 | ...::args | main.rs:113:9:113:13 | ...::log | Log entry depends on a $@. | main.rs:109:25:109:38 | ...::args | user-provided value |
98
| main.rs:114:9:114:14 | ...::log | main.rs:109:25:109:38 | ...::args | main.rs:114:9:114:14 | ...::log | Log entry depends on a $@. | main.rs:109:25:109:38 | ...::args | user-provided value |
@@ -20,21 +19,15 @@ edges
2019
| main.rs:10:22:10:81 | ... .unwrap_or(...) | main.rs:10:9:10:18 | user_input | provenance | |
2120
| main.rs:11:9:11:19 | remote_data | main.rs:17:12:17:46 | MacroExpr | provenance | |
2221
| main.rs:11:9:11:19 | remote_data | main.rs:30:11:30:66 | MacroExpr | provenance | |
23-
| main.rs:11:9:11:19 | remote_data | main.rs:48:18:48:43 | remote_data.parse() [Ok] | provenance | MaD:12 |
24-
| main.rs:11:9:11:19 | remote_data | main.rs:48:18:48:43 | remote_data.parse() [Ok] | provenance | MaD:12 |
2522
| main.rs:11:23:11:44 | ...::get | main.rs:11:23:11:71 | ...::get(...) [Ok] | provenance | Src:MaD:4 |
2623
| main.rs:11:23:11:71 | ...::get(...) [Ok] | main.rs:11:23:12:17 | ... .unwrap() | provenance | MaD:9 |
27-
| main.rs:11:23:12:17 | ... .unwrap() | main.rs:11:23:12:24 | ... .text() [Ok] | provenance | MaD:13 |
24+
| main.rs:11:23:12:17 | ... .unwrap() | main.rs:11:23:12:24 | ... .text() [Ok] | provenance | MaD:12 |
2825
| main.rs:11:23:12:24 | ... .text() [Ok] | main.rs:11:23:12:61 | ... .unwrap_or(...) | provenance | MaD:10 |
2926
| main.rs:11:23:12:61 | ... .unwrap_or(...) | main.rs:11:9:11:19 | remote_data | provenance | |
3027
| main.rs:16:11:16:44 | MacroExpr | main.rs:16:5:16:9 | ...::log | provenance | MaD:1 Sink:MaD:1 |
3128
| main.rs:17:12:17:46 | MacroExpr | main.rs:17:5:17:10 | ...::log | provenance | MaD:1 Sink:MaD:1 |
3229
| main.rs:19:12:19:39 | MacroExpr | main.rs:19:5:19:10 | ...::log | provenance | MaD:1 Sink:MaD:1 |
3330
| main.rs:30:11:30:66 | MacroExpr | main.rs:30:5:30:9 | ...::log | provenance | MaD:1 Sink:MaD:1 |
34-
| main.rs:48:9:48:14 | number | main.rs:49:11:49:30 | MacroExpr | provenance | |
35-
| main.rs:48:18:48:43 | remote_data.parse() [Ok] | main.rs:48:18:48:56 | ... .unwrap_or(...) | provenance | MaD:10 |
36-
| main.rs:48:18:48:56 | ... .unwrap_or(...) | main.rs:48:9:48:14 | number | provenance | |
37-
| main.rs:49:11:49:30 | MacroExpr | main.rs:49:5:49:9 | ...::log | provenance | MaD:1 Sink:MaD:1 |
3831
| main.rs:109:13:109:21 | user_data | main.rs:112:15:112:35 | MacroExpr | provenance | |
3932
| main.rs:109:13:109:21 | user_data | main.rs:113:15:113:38 | MacroExpr | provenance | |
4033
| main.rs:109:13:109:21 | user_data | main.rs:114:16:114:37 | MacroExpr | provenance | |
@@ -70,8 +63,7 @@ models
7063
| 9 | Summary: <core::result::Result>::unwrap; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue; value |
7164
| 10 | Summary: <core::result::Result>::unwrap_or; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue; value |
7265
| 11 | Summary: <core::result::Result>::unwrap_or_default; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue; value |
73-
| 12 | Summary: <core::str>::parse; Argument[self]; ReturnValue.Field[core::result::Result::Ok(0)]; taint |
74-
| 13 | Summary: <reqwest::blocking::response::Response>::text; Argument[self]; ReturnValue.Field[core::result::Result::Ok(0)]; taint |
66+
| 12 | Summary: <reqwest::blocking::response::Response>::text; Argument[self]; ReturnValue.Field[core::result::Result::Ok(0)]; taint |
7567
nodes
7668
| main.rs:10:9:10:18 | user_input | semmle.label | user_input |
7769
| main.rs:10:22:10:34 | ...::var | semmle.label | ...::var |
@@ -91,11 +83,6 @@ nodes
9183
| main.rs:19:12:19:39 | MacroExpr | semmle.label | MacroExpr |
9284
| main.rs:30:5:30:9 | ...::log | semmle.label | ...::log |
9385
| main.rs:30:11:30:66 | MacroExpr | semmle.label | MacroExpr |
94-
| main.rs:48:9:48:14 | number | semmle.label | number |
95-
| main.rs:48:18:48:43 | remote_data.parse() [Ok] | semmle.label | remote_data.parse() [Ok] |
96-
| main.rs:48:18:48:56 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) |
97-
| main.rs:49:5:49:9 | ...::log | semmle.label | ...::log |
98-
| main.rs:49:11:49:30 | MacroExpr | semmle.label | MacroExpr |
9986
| main.rs:109:13:109:21 | user_data | semmle.label | user_data |
10087
| main.rs:109:25:109:38 | ...::args | semmle.label | ...::args |
10188
| main.rs:109:25:109:40 | ...::args(...) [element] | semmle.label | ...::args(...) [element] |

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ fn main() {
4646

4747
// GOOD: Numeric data derived from user input (directly)
4848
let number = remote_data.parse::<u64>().unwrap_or(0);
49-
info!("Number: {}", number); // $ SPURIOUS: Alert[rust/log-injection]=remote
49+
info!("Number: {}", number);
5050

5151
// More complex test cases
5252
test_complex_scenarios(&username, &user_input);

0 commit comments

Comments
 (0)