Rust: Add numeric type barrier for log injection.

This commit is contained in:
Geoffrey White
2025-10-31 15:46:37 +00:00
parent 52397f0ce0
commit 2d4369ac6c
3 changed files with 10 additions and 16 deletions

View File

@@ -8,6 +8,7 @@ private import codeql.rust.dataflow.DataFlow
private import codeql.rust.dataflow.FlowSink
private import codeql.rust.Concepts
private import codeql.util.Unit
private import codeql.rust.security.Barriers as Barriers
/**
* Provides default sources, sinks and barriers for detecting log injection
@@ -42,4 +43,10 @@ module LogInjection {
private class ModelsAsDataSink extends Sink {
ModelsAsDataSink() { sinkNode(this, "log-injection") }
}
/**
* A barrier for log injection vulnerabilities for nodes whose type is a
* numeric or boolean type, which is unlikely to expose any vulnerability.
*/
private class NumericTypeBarrier extends Barrier instanceof Barriers::NumericTypeBarrier { }
}

View File

@@ -3,7 +3,6 @@
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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
| main.rs:10:22:10:81 | ... .unwrap_or(...) | main.rs:10:9:10:18 | user_input | provenance | |
| main.rs:11:9:11:19 | remote_data | main.rs:17:12:17:46 | MacroExpr | provenance | |
| main.rs:11:9:11:19 | remote_data | main.rs:30:11:30:66 | MacroExpr | provenance | |
| main.rs:11:9:11:19 | remote_data | main.rs:48:18:48:43 | remote_data.parse() [Ok] | provenance | MaD:12 |
| main.rs:11:9:11:19 | remote_data | main.rs:48:18:48:43 | remote_data.parse() [Ok] | provenance | MaD:12 |
| main.rs:11:23:11:44 | ...::get | main.rs:11:23:11:71 | ...::get(...) [Ok] | provenance | Src:MaD:4 |
| main.rs:11:23:11:71 | ...::get(...) [Ok] | main.rs:11:23:12:17 | ... .unwrap() | provenance | MaD:9 |
| main.rs:11:23:12:17 | ... .unwrap() | main.rs:11:23:12:24 | ... .text() [Ok] | provenance | MaD:13 |
| main.rs:11:23:12:17 | ... .unwrap() | main.rs:11:23:12:24 | ... .text() [Ok] | provenance | MaD:12 |
| main.rs:11:23:12:24 | ... .text() [Ok] | main.rs:11:23:12:61 | ... .unwrap_or(...) | provenance | MaD:10 |
| main.rs:11:23:12:61 | ... .unwrap_or(...) | main.rs:11:9:11:19 | remote_data | provenance | |
| main.rs:16:11:16:44 | MacroExpr | main.rs:16:5:16:9 | ...::log | provenance | MaD:1 Sink:MaD:1 |
| main.rs:17:12:17:46 | MacroExpr | main.rs:17:5:17:10 | ...::log | provenance | MaD:1 Sink:MaD:1 |
| main.rs:19:12:19:39 | MacroExpr | main.rs:19:5:19:10 | ...::log | provenance | MaD:1 Sink:MaD:1 |
| main.rs:30:11:30:66 | MacroExpr | main.rs:30:5:30:9 | ...::log | provenance | MaD:1 Sink:MaD:1 |
| main.rs:48:9:48:14 | number | main.rs:49:11:49:30 | MacroExpr | provenance | |
| main.rs:48:18:48:43 | remote_data.parse() [Ok] | main.rs:48:18:48:56 | ... .unwrap_or(...) | provenance | MaD:10 |
| main.rs:48:18:48:56 | ... .unwrap_or(...) | main.rs:48:9:48:14 | number | provenance | |
| main.rs:49:11:49:30 | MacroExpr | main.rs:49:5:49:9 | ...::log | provenance | MaD:1 Sink:MaD:1 |
| main.rs:109:13:109:21 | user_data | main.rs:112:15:112:35 | MacroExpr | provenance | |
| main.rs:109:13:109:21 | user_data | main.rs:113:15:113:38 | MacroExpr | provenance | |
| main.rs:109:13:109:21 | user_data | main.rs:114:16:114:37 | MacroExpr | provenance | |
@@ -70,8 +63,7 @@ models
| 9 | Summary: <core::result::Result>::unwrap; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue; value |
| 10 | Summary: <core::result::Result>::unwrap_or; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue; value |
| 11 | Summary: <core::result::Result>::unwrap_or_default; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue; value |
| 12 | Summary: <core::str>::parse; Argument[self]; ReturnValue.Field[core::result::Result::Ok(0)]; taint |
| 13 | Summary: <reqwest::blocking::response::Response>::text; Argument[self]; ReturnValue.Field[core::result::Result::Ok(0)]; taint |
| 12 | Summary: <reqwest::blocking::response::Response>::text; Argument[self]; ReturnValue.Field[core::result::Result::Ok(0)]; taint |
nodes
| main.rs:10:9:10:18 | user_input | semmle.label | user_input |
| main.rs:10:22:10:34 | ...::var | semmle.label | ...::var |
@@ -91,11 +83,6 @@ nodes
| main.rs:19:12:19:39 | MacroExpr | semmle.label | MacroExpr |
| main.rs:30:5:30:9 | ...::log | semmle.label | ...::log |
| main.rs:30:11:30:66 | MacroExpr | semmle.label | MacroExpr |
| main.rs:48:9:48:14 | number | semmle.label | number |
| main.rs:48:18:48:43 | remote_data.parse() [Ok] | semmle.label | remote_data.parse() [Ok] |
| main.rs:48:18:48:56 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) |
| main.rs:49:5:49:9 | ...::log | semmle.label | ...::log |
| main.rs:49:11:49:30 | MacroExpr | semmle.label | MacroExpr |
| main.rs:109:13:109:21 | user_data | semmle.label | user_data |
| main.rs:109:25:109:38 | ...::args | semmle.label | ...::args |
| main.rs:109:25:109:40 | ...::args(...) [element] | semmle.label | ...::args(...) [element] |

View File

@@ -46,7 +46,7 @@ fn main() {
// GOOD: Numeric data derived from user input (directly)
let number = remote_data.parse::<u64>().unwrap_or(0);
info!("Number: {}", number); // $ SPURIOUS: Alert[rust/log-injection]=remote
info!("Number: {}", number);
// More complex test cases
test_complex_scenarios(&username, &user_input);