Skip to content

Commit 78c58aa

Browse files
committed
Rust: Allow implicit taint reads from tuple contents at sinks.
1 parent 6444494 commit 78c58aa

File tree

4 files changed

+56
-5
lines changed

4 files changed

+56
-5
lines changed

rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -773,7 +773,7 @@ final class ArrayElementContent extends Content, TArrayElement {
773773
* NOTE: Unlike `struct`s and `enum`s tuples are structural and not nominal,
774774
* hence we don't store a canonical path for them.
775775
*/
776-
private class TuplePositionContent extends Content, TTuplePositionContent {
776+
final class TuplePositionContent extends Content, TTuplePositionContent {
777777
private int pos;
778778

779779
TuplePositionContent() { this = TTuplePositionContent(pos) }

rust/ql/src/queries/security/CWE-312/CleartextLogging.ql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import rust
1717
import codeql.rust.security.CleartextLoggingExtensions
1818
import codeql.rust.dataflow.DataFlow
1919
import codeql.rust.dataflow.TaintTracking
20+
import codeql.rust.dataflow.internal.DataFlowImpl
2021

2122
/**
2223
* A taint-tracking configuration for cleartext logging vulnerabilities.
@@ -34,6 +35,12 @@ module CleartextLoggingConfig implements DataFlow::ConfigSig {
3435
// make sources barriers so that we only report the closest instance
3536
isSource(node)
3637
}
38+
39+
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
40+
// flow out from tuple content at sinks.
41+
isSink(node) and
42+
c.getAReadContent() instanceof TuplePositionContent
43+
}
3744
}
3845

3946
module CleartextLoggingFlow = TaintTracking::Global<CleartextLoggingConfig>;

rust/ql/test/query-tests/security/CWE-312/CleartextLogging.expected

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,17 @@
1111
| test_logging.rs:57:5:57:34 | ...::log | test_logging.rs:57:24:57:31 | password | test_logging.rs:57:5:57:34 | ...::log | This operation writes '...::log' to a log file. It may contain unencrypted sensitive data from $@. | test_logging.rs:57:24:57:31 | password | password |
1212
| test_logging.rs:58:5:58:36 | ...::log | test_logging.rs:58:24:58:31 | password | test_logging.rs:58:5:58:36 | ...::log | This operation writes '...::log' to a log file. It may contain unencrypted sensitive data from $@. | test_logging.rs:58:24:58:31 | password | password |
1313
| test_logging.rs:60:5:60:54 | ...::log | test_logging.rs:60:46:60:53 | password | test_logging.rs:60:5:60:54 | ...::log | This operation writes '...::log' to a log file. It may contain unencrypted sensitive data from $@. | test_logging.rs:60:46:60:53 | password | password |
14+
| test_logging.rs:61:5:61:55 | ...::log | test_logging.rs:61:21:61:28 | password | test_logging.rs:61:5:61:55 | ...::log | This operation writes '...::log' to a log file. It may contain unencrypted sensitive data from $@. | test_logging.rs:61:21:61:28 | password | password |
1415
| test_logging.rs:65:5:65:48 | ...::log | test_logging.rs:65:40:65:47 | password | test_logging.rs:65:5:65:48 | ...::log | This operation writes '...::log' to a log file. It may contain unencrypted sensitive data from $@. | test_logging.rs:65:40:65:47 | password | password |
1516
| test_logging.rs:67:5:67:66 | ...::log | test_logging.rs:67:58:67:65 | password | test_logging.rs:67:5:67:66 | ...::log | This operation writes '...::log' to a log file. It may contain unencrypted sensitive data from $@. | test_logging.rs:67:58:67:65 | password | password |
17+
| test_logging.rs:68:5:68:67 | ...::log | test_logging.rs:68:19:68:26 | password | test_logging.rs:68:5:68:67 | ...::log | This operation writes '...::log' to a log file. It may contain unencrypted sensitive data from $@. | test_logging.rs:68:19:68:26 | password | password |
1618
| test_logging.rs:72:5:72:47 | ...::log::<...> | test_logging.rs:72:39:72:46 | password | test_logging.rs:72:5:72:47 | ...::log::<...> | This operation writes '...::log::<...>' to a log file. It may contain unencrypted sensitive data from $@. | test_logging.rs:72:39:72:46 | password | password |
1719
| test_logging.rs:74:5:74:65 | ...::log::<...> | test_logging.rs:74:57:74:64 | password | test_logging.rs:74:5:74:65 | ...::log::<...> | This operation writes '...::log::<...>' to a log file. It may contain unencrypted sensitive data from $@. | test_logging.rs:74:57:74:64 | password | password |
20+
| test_logging.rs:75:5:75:51 | ...::log::<...> | test_logging.rs:75:21:75:28 | password | test_logging.rs:75:5:75:51 | ...::log::<...> | This operation writes '...::log::<...>' to a log file. It may contain unencrypted sensitive data from $@. | test_logging.rs:75:21:75:28 | password | password |
1821
| test_logging.rs:76:5:76:47 | ...::log::<...> | test_logging.rs:76:39:76:46 | password | test_logging.rs:76:5:76:47 | ...::log::<...> | This operation writes '...::log::<...>' to a log file. It may contain unencrypted sensitive data from $@. | test_logging.rs:76:39:76:46 | password | password |
1922
| test_logging.rs:82:5:82:44 | ...::log::<...> | test_logging.rs:82:36:82:43 | password | test_logging.rs:82:5:82:44 | ...::log::<...> | This operation writes '...::log::<...>' to a log file. It may contain unencrypted sensitive data from $@. | test_logging.rs:82:36:82:43 | password | password |
2023
| test_logging.rs:84:5:84:62 | ...::log::<...> | test_logging.rs:84:54:84:61 | password | test_logging.rs:84:5:84:62 | ...::log::<...> | This operation writes '...::log::<...>' to a log file. It may contain unencrypted sensitive data from $@. | test_logging.rs:84:54:84:61 | password | password |
24+
| test_logging.rs:85:5:85:48 | ...::log::<...> | test_logging.rs:85:21:85:28 | password | test_logging.rs:85:5:85:48 | ...::log::<...> | This operation writes '...::log::<...>' to a log file. It may contain unencrypted sensitive data from $@. | test_logging.rs:85:21:85:28 | password | password |
2125
| test_logging.rs:86:5:86:44 | ...::log::<...> | test_logging.rs:86:36:86:43 | password | test_logging.rs:86:5:86:44 | ...::log::<...> | This operation writes '...::log::<...>' to a log file. It may contain unencrypted sensitive data from $@. | test_logging.rs:86:36:86:43 | password | password |
2226
| test_logging.rs:100:5:100:19 | ...::log | test_logging.rs:99:38:99:45 | password | test_logging.rs:100:5:100:19 | ...::log | This operation writes '...::log' to a log file. It may contain unencrypted sensitive data from $@. | test_logging.rs:99:38:99:45 | password | password |
2327
| test_logging.rs:118:5:118:42 | ...::log | test_logging.rs:118:28:118:41 | get_password(...) | test_logging.rs:118:5:118:42 | ...::log | This operation writes '...::log' to a log file. It may contain unencrypted sensitive data from $@. | test_logging.rs:118:28:118:41 | get_password(...) | get_password(...) |
@@ -66,20 +70,40 @@ edges
6670
| test_logging.rs:58:24:58:31 | password | test_logging.rs:58:12:58:35 | MacroExpr | provenance | |
6771
| test_logging.rs:60:30:60:53 | MacroExpr | test_logging.rs:60:5:60:54 | ...::log | provenance | MaD:0 Sink:MaD:0 |
6872
| test_logging.rs:60:46:60:53 | password | test_logging.rs:60:30:60:53 | MacroExpr | provenance | |
73+
| test_logging.rs:61:20:61:28 | &... [&ref, tuple.0, &ref] | test_logging.rs:61:5:61:55 | ...::log | provenance | MaD:1 Sink:MaD:1 Sink:MaD:1 |
74+
| test_logging.rs:61:20:61:28 | &... [&ref, tuple.0, &ref] | test_logging.rs:61:5:61:55 | ...::log | provenance | MaD:1 Sink:MaD:1 Sink:MaD:1 Sink:MaD:1 |
75+
| test_logging.rs:61:20:61:28 | &password [&ref] | test_logging.rs:61:20:61:28 | TupleExpr [tuple.0, &ref] | provenance | |
76+
| test_logging.rs:61:20:61:28 | TupleExpr [tuple.0, &ref] | test_logging.rs:61:20:61:28 | &... [&ref, tuple.0, &ref] | provenance | |
77+
| test_logging.rs:61:21:61:28 | password | test_logging.rs:61:20:61:28 | &password [&ref] | provenance | |
6978
| test_logging.rs:65:24:65:47 | MacroExpr | test_logging.rs:65:5:65:48 | ...::log | provenance | MaD:0 Sink:MaD:0 |
7079
| test_logging.rs:65:40:65:47 | password | test_logging.rs:65:24:65:47 | MacroExpr | provenance | |
7180
| test_logging.rs:67:42:67:65 | MacroExpr | test_logging.rs:67:5:67:66 | ...::log | provenance | MaD:0 Sink:MaD:0 |
7281
| test_logging.rs:67:58:67:65 | password | test_logging.rs:67:42:67:65 | MacroExpr | provenance | |
82+
| test_logging.rs:68:18:68:26 | &... [&ref, tuple.0, &ref] | test_logging.rs:68:5:68:67 | ...::log | provenance | MaD:1 Sink:MaD:1 Sink:MaD:1 |
83+
| test_logging.rs:68:18:68:26 | &... [&ref, tuple.0, &ref] | test_logging.rs:68:5:68:67 | ...::log | provenance | MaD:1 Sink:MaD:1 Sink:MaD:1 Sink:MaD:1 |
84+
| test_logging.rs:68:18:68:26 | &password [&ref] | test_logging.rs:68:18:68:26 | TupleExpr [tuple.0, &ref] | provenance | |
85+
| test_logging.rs:68:18:68:26 | TupleExpr [tuple.0, &ref] | test_logging.rs:68:18:68:26 | &... [&ref, tuple.0, &ref] | provenance | |
86+
| test_logging.rs:68:19:68:26 | password | test_logging.rs:68:18:68:26 | &password [&ref] | provenance | |
7387
| test_logging.rs:72:23:72:46 | MacroExpr | test_logging.rs:72:5:72:47 | ...::log::<...> | provenance | MaD:0 Sink:MaD:0 |
7488
| test_logging.rs:72:39:72:46 | password | test_logging.rs:72:23:72:46 | MacroExpr | provenance | |
7589
| test_logging.rs:74:41:74:64 | MacroExpr | test_logging.rs:74:5:74:65 | ...::log::<...> | provenance | MaD:0 Sink:MaD:0 |
7690
| test_logging.rs:74:57:74:64 | password | test_logging.rs:74:41:74:64 | MacroExpr | provenance | |
91+
| test_logging.rs:75:20:75:28 | &... [&ref, tuple.0, &ref] | test_logging.rs:75:5:75:51 | ...::log::<...> | provenance | MaD:1 Sink:MaD:1 Sink:MaD:1 |
92+
| test_logging.rs:75:20:75:28 | &... [&ref, tuple.0, &ref] | test_logging.rs:75:5:75:51 | ...::log::<...> | provenance | MaD:1 Sink:MaD:1 Sink:MaD:1 Sink:MaD:1 |
93+
| test_logging.rs:75:20:75:28 | &password [&ref] | test_logging.rs:75:20:75:28 | TupleExpr [tuple.0, &ref] | provenance | |
94+
| test_logging.rs:75:20:75:28 | TupleExpr [tuple.0, &ref] | test_logging.rs:75:20:75:28 | &... [&ref, tuple.0, &ref] | provenance | |
95+
| test_logging.rs:75:21:75:28 | password | test_logging.rs:75:20:75:28 | &password [&ref] | provenance | |
7796
| test_logging.rs:76:23:76:46 | MacroExpr | test_logging.rs:76:5:76:47 | ...::log::<...> | provenance | MaD:0 Sink:MaD:0 |
7897
| test_logging.rs:76:39:76:46 | password | test_logging.rs:76:23:76:46 | MacroExpr | provenance | |
7998
| test_logging.rs:82:20:82:43 | MacroExpr | test_logging.rs:82:5:82:44 | ...::log::<...> | provenance | MaD:0 Sink:MaD:0 |
8099
| test_logging.rs:82:36:82:43 | password | test_logging.rs:82:20:82:43 | MacroExpr | provenance | |
81100
| test_logging.rs:84:38:84:61 | MacroExpr | test_logging.rs:84:5:84:62 | ...::log::<...> | provenance | MaD:0 Sink:MaD:0 |
82101
| test_logging.rs:84:54:84:61 | password | test_logging.rs:84:38:84:61 | MacroExpr | provenance | |
102+
| test_logging.rs:85:20:85:28 | &... [&ref, tuple.0, &ref] | test_logging.rs:85:5:85:48 | ...::log::<...> | provenance | MaD:1 Sink:MaD:1 Sink:MaD:1 |
103+
| test_logging.rs:85:20:85:28 | &... [&ref, tuple.0, &ref] | test_logging.rs:85:5:85:48 | ...::log::<...> | provenance | MaD:1 Sink:MaD:1 Sink:MaD:1 Sink:MaD:1 |
104+
| test_logging.rs:85:20:85:28 | &password [&ref] | test_logging.rs:85:20:85:28 | TupleExpr [tuple.0, &ref] | provenance | |
105+
| test_logging.rs:85:20:85:28 | TupleExpr [tuple.0, &ref] | test_logging.rs:85:20:85:28 | &... [&ref, tuple.0, &ref] | provenance | |
106+
| test_logging.rs:85:21:85:28 | password | test_logging.rs:85:20:85:28 | &password [&ref] | provenance | |
83107
| test_logging.rs:86:20:86:43 | MacroExpr | test_logging.rs:86:5:86:44 | ...::log::<...> | provenance | MaD:0 Sink:MaD:0 |
84108
| test_logging.rs:86:36:86:43 | password | test_logging.rs:86:20:86:43 | MacroExpr | provenance | |
85109
| test_logging.rs:99:9:99:10 | m3 | test_logging.rs:100:11:100:18 | MacroExpr | provenance | |
@@ -207,18 +231,33 @@ nodes
207231
| test_logging.rs:60:5:60:54 | ...::log | semmle.label | ...::log |
208232
| test_logging.rs:60:30:60:53 | MacroExpr | semmle.label | MacroExpr |
209233
| test_logging.rs:60:46:60:53 | password | semmle.label | password |
234+
| test_logging.rs:61:5:61:55 | ...::log | semmle.label | ...::log |
235+
| test_logging.rs:61:20:61:28 | &... [&ref, tuple.0, &ref] | semmle.label | &... [&ref, tuple.0, &ref] |
236+
| test_logging.rs:61:20:61:28 | &password [&ref] | semmle.label | &password [&ref] |
237+
| test_logging.rs:61:20:61:28 | TupleExpr [tuple.0, &ref] | semmle.label | TupleExpr [tuple.0, &ref] |
238+
| test_logging.rs:61:21:61:28 | password | semmle.label | password |
210239
| test_logging.rs:65:5:65:48 | ...::log | semmle.label | ...::log |
211240
| test_logging.rs:65:24:65:47 | MacroExpr | semmle.label | MacroExpr |
212241
| test_logging.rs:65:40:65:47 | password | semmle.label | password |
213242
| test_logging.rs:67:5:67:66 | ...::log | semmle.label | ...::log |
214243
| test_logging.rs:67:42:67:65 | MacroExpr | semmle.label | MacroExpr |
215244
| test_logging.rs:67:58:67:65 | password | semmle.label | password |
245+
| test_logging.rs:68:5:68:67 | ...::log | semmle.label | ...::log |
246+
| test_logging.rs:68:18:68:26 | &... [&ref, tuple.0, &ref] | semmle.label | &... [&ref, tuple.0, &ref] |
247+
| test_logging.rs:68:18:68:26 | &password [&ref] | semmle.label | &password [&ref] |
248+
| test_logging.rs:68:18:68:26 | TupleExpr [tuple.0, &ref] | semmle.label | TupleExpr [tuple.0, &ref] |
249+
| test_logging.rs:68:19:68:26 | password | semmle.label | password |
216250
| test_logging.rs:72:5:72:47 | ...::log::<...> | semmle.label | ...::log::<...> |
217251
| test_logging.rs:72:23:72:46 | MacroExpr | semmle.label | MacroExpr |
218252
| test_logging.rs:72:39:72:46 | password | semmle.label | password |
219253
| test_logging.rs:74:5:74:65 | ...::log::<...> | semmle.label | ...::log::<...> |
220254
| test_logging.rs:74:41:74:64 | MacroExpr | semmle.label | MacroExpr |
221255
| test_logging.rs:74:57:74:64 | password | semmle.label | password |
256+
| test_logging.rs:75:5:75:51 | ...::log::<...> | semmle.label | ...::log::<...> |
257+
| test_logging.rs:75:20:75:28 | &... [&ref, tuple.0, &ref] | semmle.label | &... [&ref, tuple.0, &ref] |
258+
| test_logging.rs:75:20:75:28 | &password [&ref] | semmle.label | &password [&ref] |
259+
| test_logging.rs:75:20:75:28 | TupleExpr [tuple.0, &ref] | semmle.label | TupleExpr [tuple.0, &ref] |
260+
| test_logging.rs:75:21:75:28 | password | semmle.label | password |
222261
| test_logging.rs:76:5:76:47 | ...::log::<...> | semmle.label | ...::log::<...> |
223262
| test_logging.rs:76:23:76:46 | MacroExpr | semmle.label | MacroExpr |
224263
| test_logging.rs:76:39:76:46 | password | semmle.label | password |
@@ -228,6 +267,11 @@ nodes
228267
| test_logging.rs:84:5:84:62 | ...::log::<...> | semmle.label | ...::log::<...> |
229268
| test_logging.rs:84:38:84:61 | MacroExpr | semmle.label | MacroExpr |
230269
| test_logging.rs:84:54:84:61 | password | semmle.label | password |
270+
| test_logging.rs:85:5:85:48 | ...::log::<...> | semmle.label | ...::log::<...> |
271+
| test_logging.rs:85:20:85:28 | &... [&ref, tuple.0, &ref] | semmle.label | &... [&ref, tuple.0, &ref] |
272+
| test_logging.rs:85:20:85:28 | &password [&ref] | semmle.label | &password [&ref] |
273+
| test_logging.rs:85:20:85:28 | TupleExpr [tuple.0, &ref] | semmle.label | TupleExpr [tuple.0, &ref] |
274+
| test_logging.rs:85:21:85:28 | password | semmle.label | password |
231275
| test_logging.rs:86:5:86:44 | ...::log::<...> | semmle.label | ...::log::<...> |
232276
| test_logging.rs:86:20:86:43 | MacroExpr | semmle.label | MacroExpr |
233277
| test_logging.rs:86:36:86:43 | password | semmle.label | password |

rust/ql/test/query-tests/security/CWE-312/test_logging.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,21 +58,21 @@ fn test_log(harmless: String, password: String, encrypted_password: String) {
5858
debug!("message = {password:?}"); // $ Source Alert[rust/cleartext-logging]
5959
debug!(target: "target", "message = {}", harmless);
6060
debug!(target: "target", "message = {}", password); // $ Source Alert[rust/cleartext-logging]
61-
debug!(target: &password, "message = {}", harmless); // $ MISSING: Alert[rust/cleartext-logging]
61+
debug!(target: &password, "message = {}", harmless); // $ Source Alert[rust/cleartext-logging]
6262

6363
// log! macro, various formatting
6464
log!(Level::Error, "message = {}", harmless);
6565
log!(Level::Error, "message = {}", password); // $ Source Alert[rust/cleartext-logging]
6666
log!(target: "target", Level::Error, "message = {}", harmless);
6767
log!(target: "target", Level::Error, "message = {}", password); // $ Source Alert[rust/cleartext-logging]
68-
log!(target: &password, Level::Error, "message = {}", harmless); // $ MISSING: Alert[rust/cleartext-logging]
68+
log!(target: &password, Level::Error, "message = {}", harmless); // $ Source Alert[rust/cleartext-logging]
6969

7070
// structured logging
7171
error!(value = 1; "message = {}", harmless);
7272
error!(value = 1; "message = {}", password); // $ Source Alert[rust/cleartext-logging]
7373
error!(target: "target", value = 1; "message");
7474
error!(target: "target", value = 1; "message = {}", password); // $ Source Alert[rust/cleartext-logging]
75-
error!(target: &password, value = 1; "message"); // $ MISSING: Alert[rust/cleartext-logging]
75+
error!(target: &password, value = 1; "message"); // $ Source Alert[rust/cleartext-logging]
7676
error!(value = 1; "message = {}", password); // $ Source Alert[rust/cleartext-logging]
7777
error!(value = password.as_str(); "message"); // $ MISSING: Alert[rust/cleartext-logging]
7878
error!(value:? = password.as_str(); "message"); // $ MISSING: Alert[rust/cleartext-logging]
@@ -82,7 +82,7 @@ fn test_log(harmless: String, password: String, encrypted_password: String) {
8282
error!(value1; "message = {}", password); // $ Source Alert[rust/cleartext-logging]
8383
error!(target: "target", value1; "message");
8484
error!(target: "target", value1; "message = {}", password); // $ Source Alert[rust/cleartext-logging]
85-
error!(target: &password, value1; "message"); // $ MISSING: Alert[rust/cleartext-logging]
85+
error!(target: &password, value1; "message"); // $ Source Alert[rust/cleartext-logging]
8686
error!(value1; "message = {}", password); // $ Source Alert[rust/cleartext-logging]
8787

8888
let value2 = password.as_str();

0 commit comments

Comments
 (0)