Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit bb3be2f

Browse files
committed
Rust: Add a test for the log crate + placeholder query.
1 parent f845ac1 commit bb3be2f

5 files changed

Lines changed: 158 additions & 0 deletions

File tree

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* @name Cleartext logging of sensitive information
3+
* @description Logging sensitive information in plaintext can
4+
* expose it to an attacker.
5+
* @kind path-problem
6+
* @problem.severity error
7+
* @security-severity 7.5
8+
* @precision high
9+
* @id rust/cleartext-logging
10+
* @tags security
11+
* external/cwe/cwe-312
12+
* external/cwe/cwe-359
13+
* external/cwe/cwe-532
14+
*/
15+
16+
import rust
17+
18+
from Element e
19+
where none()
20+
select e, ""

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

Whitespace-only changes.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
query: queries/security/CWE-312/CleartextLogging.ql
2+
postprocess:
3+
- utils/test/InlineExpectationsTestQuery.ql
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
qltest_cargo_check: true
2+
qltest_dependencies:
3+
- log = { version = "0.4.25", features = ["kv"] }
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
2+
use log::{debug, error, info, trace, warn, log, Level};
3+
4+
// --- tests ---
5+
6+
fn get_password() -> String {
7+
return "123456".to_string();
8+
}
9+
10+
fn use_password(password: &String) {
11+
// ...
12+
}
13+
14+
#[derive(Debug)]
15+
struct MyStruct1 {
16+
harmless: String,
17+
password: String,
18+
}
19+
20+
impl std::fmt::Display for MyStruct1 {
21+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
22+
write!(f, "{} {}", self.harmless, self.password)
23+
}
24+
}
25+
26+
#[derive(Debug)]
27+
struct MyStruct2 {
28+
harmless: String,
29+
password: String,
30+
}
31+
32+
impl std::fmt::Display for MyStruct2 {
33+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
34+
write!(f, "{} [REDACTED]", self.harmless) // doesn't output password
35+
}
36+
}
37+
38+
fn test_log(harmless: String, password: String, encrypted_password: String) {
39+
// logging macros
40+
debug!("message = {}", password); // $ MISSING: Alert[rust/cleartext-logging]
41+
error!("message = {}", password); // $ MISSING: Alert[rust/cleartext-logging]
42+
info!("message = {}", password); // $ MISSING: Alert[rust/cleartext-logging]
43+
trace!("message = {}", password); // $ MISSING: Alert[rust/cleartext-logging]
44+
warn!("message = {}", password); // $ MISSING: Alert[rust/cleartext-logging]
45+
log!(Level::Error, "message = {}", password); // $ MISSING: Alert[rust/cleartext-logging]
46+
47+
// debug! macro, various formatting
48+
debug!("message");
49+
debug!("message = {}", harmless);
50+
debug!("message = {}", password); // $ MISSING: Alert[rust/cleartext-logging]
51+
debug!("message = {}", encrypted_password);
52+
debug!("message = {} {}", harmless, password); // $ MISSING: Alert[rust/cleartext-logging]
53+
debug!("message = {harmless}");
54+
debug!("message = {harmless} {}", password); // $ MISSING: Alert[rust/cleartext-logging]
55+
debug!("message = {password}"); // $ MISSING: Alert[rust/cleartext-logging]
56+
debug!("message = {password:?}"); // $ MISSING: Alert[rust/cleartext-logging]
57+
debug!(target: "target", "message = {}", harmless);
58+
debug!(target: "target", "message = {}", password); // $ MISSING: Alert[rust/cleartext-logging]
59+
debug!(target: &password, "message = {}", harmless); // $ MISSING: Alert[rust/cleartext-logging]
60+
61+
// log! macro, various formatting
62+
log!(Level::Error, "message = {}", harmless);
63+
log!(Level::Error, "message = {}", password); // $ MISSING: Alert[rust/cleartext-logging]
64+
log!(target: "target", Level::Error, "message = {}", harmless);
65+
log!(target: "target", Level::Error, "message = {}", password); // $ MISSING: Alert[rust/cleartext-logging]
66+
log!(target: &password, Level::Error, "message = {}", harmless); // $ MISSING: Alert[rust/cleartext-logging]
67+
68+
// structured logging
69+
error!(value = 1; "message = {}", harmless);
70+
error!(value = 1; "message = {}", password); // $ MISSING: Alert[rust/cleartext-logging]
71+
error!(target: "target", value = 1; "message");
72+
error!(target: "target", value = 1; "message = {}", password); // $ MISSING: Alert[rust/cleartext-logging]
73+
error!(target: &password, value = 1; "message"); // $ MISSING: Alert[rust/cleartext-logging]
74+
error!(value = 1; "message = {}", password); // $ MISSING: Alert[rust/cleartext-logging]
75+
error!(value = password.as_str(); "message"); // $ MISSING: Alert[rust/cleartext-logging]
76+
error!(value:? = password.as_str(); "message"); // $ MISSING: Alert[rust/cleartext-logging]
77+
78+
let value1 = 1;
79+
error!(value1; "message = {}", harmless);
80+
error!(value1; "message = {}", password); // $ MISSING: Alert[rust/cleartext-logging]
81+
error!(target: "target", value1; "message");
82+
error!(target: "target", value1; "message = {}", password); // $ MISSING: Alert[rust/cleartext-logging]
83+
error!(target: &password, value1; "message"); // $ MISSING: Alert[rust/cleartext-logging]
84+
error!(value1; "message = {}", password); // $ MISSING: Alert[rust/cleartext-logging]
85+
86+
let value2 = password.as_str();
87+
error!(value2; "message"); // $ MISSING: Alert[rust/cleartext-logging]
88+
error!(value2:?; "message"); // $ MISSING: Alert[rust/cleartext-logging]
89+
90+
// pre-formatted
91+
let m1 = &password; // $ MISSING: Source=m1
92+
info!("message = {}", m1); // $ MISSING: Alert[rust/cleartext-logging]=m1
93+
94+
let m2 = "message = ".to_string() + &password; // $ MISSING: Source=m2
95+
info!("{}", m2); // $ MISSING: Alert[rust/cleartext-logging]=m2
96+
97+
let m3 = format!("message = {}", password); // $ MISSING:=m3
98+
info!("{}", m3); // $ MISSING: Alert[rust/cleartext-logging]=m3
99+
100+
// logging with a call
101+
trace!("message = {}", get_password()); // $ MISSING: Alert[rust/cleartext-logging]
102+
103+
let str1 = "123456".to_string();
104+
trace!("message = {}", &str1); // $ MISSING: Alert[rust/cleartext-logging]
105+
use_password(&str1); // (proves that `str1` is a password)
106+
trace!("message = {}", &str1); // $ MISSING: Alert[rust/cleartext-logging]
107+
108+
let str2 = "123456".to_string();
109+
trace!("message = {}", &str2);
110+
111+
// logging from a tuple
112+
let t1 = (harmless, password); // $ MISSING:=t1
113+
trace!("message = {}", t1.0);
114+
trace!("message = {}", t1.1); // $ MISSING: Alert[rust/cleartext-logging]=t1
115+
trace!("message = {:?}", t1); // $ MISSING: Alert[rust/cleartext-logging]=t1
116+
trace!("message = {:#?}", t1); // $ MISSING: Alert[rust/cleartext-logging]=t1
117+
118+
// logging from a struct
119+
let s1 = MyStruct1 { harmless: "foo".to_string(), password: "123456".to_string() }; // $ MISSING: Source=s1
120+
warn!("message = {}", s1.harmless);
121+
warn!("message = {}", s1.password); // $ MISSING: Alert[rust/cleartext-logging]
122+
warn!("message = {}", s1); // $ MISSING: Alert[rust/cleartext-logging]=s1
123+
warn!("message = {:?}", s1); // $ MISSING: Alert[rust/cleartext-logging]=s1
124+
warn!("message = {:#?}", s1); // $ MISSING: Alert[rust/cleartext-logging]=s1
125+
126+
let s2 = MyStruct2 { harmless: "foo".to_string(), password: "123456".to_string() }; // $ MISSING: Source=s2
127+
warn!("message = {}", s2.harmless);
128+
warn!("message = {}", s2.password); // $ MISSING: Alert[rust/cleartext-logging]
129+
warn!("message = {}", s2); // (this implementation does not output the password field)
130+
warn!("message = {:?}", s2); // $ MISSING: Alert[rust/cleartext-logging]=s2
131+
warn!("message = {:#?}", s2); // $ MISSING: Alert[rust/cleartext-logging]=s2
132+
}

0 commit comments

Comments
 (0)