Skip to content

Rust: Update legacy MaD models 2 #19942

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Jul 10, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion rust/ql/test/library-tests/dataflow/sources/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ fn test_io_stdin() -> std::io::Result<()> {
{
let mut buffer = Vec::<u8>::new();
let _bytes = std::io::stdin().read_to_end(&mut buffer)?; // $ Alert[rust/summary/taint-sources]
sink(&buffer); // $ MISSING: hasTaintFlow
sink(&buffer); // $ hasTaintFlow
}

{
Expand Down
10 changes: 5 additions & 5 deletions rust/ql/test/library-tests/frameworks/postgres/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
)",
&[],
)?;

let query = format!("INSERT INTO person (name, age) VALUES ('{}', '{}')", name, age);

conn.execute(query.as_str(), &[])?; // $ sql-sink
Expand All @@ -33,11 +33,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// conn.query_typed_raw(query.as_str(), &[])?;

for row in &conn.query("SELECT id, name, age FROM person", &[])? { // $ sql-sink
let id: i32 = row.get("id"); // $ database-read
let name: &str = row.try_get("name")?; // $ database-read
let age: i32 = row.try_get("age").unwrap(); // $ database-read
let id: i32 = row.get("id"); // $ MISSING: database-read
let name: &str = row.try_get("name")?; // $ MISSING: database-read
let age: i32 = row.try_get("age").unwrap(); // $ MISSING: database-read
println!("found person: {} {} {}", id, name, age);
}

Ok(())
}
}
Original file line number Diff line number Diff line change
@@ -1,74 +1,14 @@
#select
| test.rs:14:9:14:24 | ...::digest | test.rs:14:26:14:39 | credit_card_no | test.rs:14:9:14:24 | ...::digest | $@ is used in a hashing algorithm (MD5) that is insecure. | test.rs:14:26:14:39 | credit_card_no | Sensitive data (private) |
| test.rs:15:9:15:24 | ...::digest | test.rs:15:26:15:33 | password | test.rs:15:9:15:24 | ...::digest | $@ is used in a hashing algorithm (MD5) that is insecure for password hashing, since it is not a computationally expensive hash function. | test.rs:15:26:15:33 | password | Sensitive data (password) |
| test.rs:20:9:20:24 | ...::compute | test.rs:20:26:20:39 | credit_card_no | test.rs:20:9:20:24 | ...::compute | $@ is used in a hashing algorithm (MD5) that is insecure. | test.rs:20:26:20:39 | credit_card_no | Sensitive data (private) |
| test.rs:21:9:21:24 | ...::compute | test.rs:21:26:21:33 | password | test.rs:21:9:21:24 | ...::compute | $@ is used in a hashing algorithm (MD5) that is insecure for password hashing, since it is not a computationally expensive hash function. | test.rs:21:26:21:33 | password | Sensitive data (password) |
| test.rs:26:9:26:26 | ...::digest | test.rs:26:28:26:41 | credit_card_no | test.rs:26:9:26:26 | ...::digest | $@ is used in a hashing algorithm (SHA1) that is insecure. | test.rs:26:28:26:41 | credit_card_no | Sensitive data (private) |
| test.rs:27:9:27:26 | ...::digest | test.rs:27:28:27:35 | password | test.rs:27:9:27:26 | ...::digest | $@ is used in a hashing algorithm (SHA1) that is insecure for password hashing, since it is not a computationally expensive hash function. | test.rs:27:28:27:35 | password | Sensitive data (password) |
| test.rs:32:9:32:34 | ...::digest | test.rs:32:36:32:49 | credit_card_no | test.rs:32:9:32:34 | ...::digest | $@ is used in a hashing algorithm (SHA1) that is insecure. | test.rs:32:36:32:49 | credit_card_no | Sensitive data (private) |
| test.rs:33:9:33:34 | ...::digest | test.rs:33:36:33:43 | password | test.rs:33:9:33:34 | ...::digest | $@ is used in a hashing algorithm (SHA1) that is insecure for password hashing, since it is not a computationally expensive hash function. | test.rs:33:36:33:43 | password | Sensitive data (password) |
| test.rs:39:9:39:30 | ...::digest | test.rs:39:32:39:39 | password | test.rs:39:9:39:30 | ...::digest | $@ is used in a hashing algorithm (SHA3256) that is insecure for password hashing, since it is not a computationally expensive hash function. | test.rs:39:32:39:39 | password | Sensitive data (password) |
| test.rs:60:9:60:24 | ...::digest | test.rs:60:26:60:37 | password_str | test.rs:60:9:60:24 | ...::digest | $@ is used in a hashing algorithm (MD5) that is insecure for password hashing, since it is not a computationally expensive hash function. | test.rs:60:26:60:37 | password_str | Sensitive data (password) |
| test.rs:62:9:62:24 | ...::digest | test.rs:62:26:62:37 | password_arr | test.rs:62:9:62:24 | ...::digest | $@ is used in a hashing algorithm (MD5) that is insecure for password hashing, since it is not a computationally expensive hash function. | test.rs:62:26:62:37 | password_arr | Sensitive data (password) |
| test.rs:64:9:64:24 | ...::digest | test.rs:64:26:64:37 | password_vec | test.rs:64:9:64:24 | ...::digest | $@ is used in a hashing algorithm (MD5) that is insecure for password hashing, since it is not a computationally expensive hash function. | test.rs:64:26:64:37 | password_vec | Sensitive data (password) |
| test.rs:77:9:77:33 | ...::new_with_prefix | test.rs:77:35:77:42 | password | test.rs:77:9:77:33 | ...::new_with_prefix | $@ is used in a hashing algorithm (MD5) that is insecure for password hashing, since it is not a computationally expensive hash function. | test.rs:77:35:77:42 | password | Sensitive data (password) |
| test.rs:81:9:81:24 | ...::digest | test.rs:81:26:81:33 | password | test.rs:81:9:81:24 | ...::digest | $@ is used in a hashing algorithm (MD5) that is insecure for password hashing, since it is not a computationally expensive hash function. | test.rs:81:26:81:33 | password | Sensitive data (password) |
| test.rs:83:9:83:24 | ...::digest | test.rs:83:26:83:33 | password | test.rs:83:9:83:24 | ...::digest | $@ is used in a hashing algorithm (MD5) that is insecure for password hashing, since it is not a computationally expensive hash function. | test.rs:83:26:83:33 | password | Sensitive data (password) |
edges
| test.rs:14:26:14:39 | credit_card_no | test.rs:14:9:14:24 | ...::digest | provenance | MaD:1 Sink:MaD:1 |
| test.rs:15:26:15:33 | password | test.rs:15:9:15:24 | ...::digest | provenance | MaD:1 Sink:MaD:1 |
| test.rs:20:26:20:39 | credit_card_no | test.rs:20:9:20:24 | ...::compute | provenance | MaD:3 Sink:MaD:3 |
| test.rs:21:26:21:33 | password | test.rs:21:9:21:24 | ...::compute | provenance | MaD:3 Sink:MaD:3 |
| test.rs:26:28:26:41 | credit_card_no | test.rs:26:9:26:26 | ...::digest | provenance | MaD:1 Sink:MaD:1 |
| test.rs:27:28:27:35 | password | test.rs:27:9:27:26 | ...::digest | provenance | MaD:1 Sink:MaD:1 |
| test.rs:32:36:32:49 | credit_card_no | test.rs:32:9:32:34 | ...::digest | provenance | MaD:1 Sink:MaD:1 |
| test.rs:33:36:33:43 | password | test.rs:33:9:33:34 | ...::digest | provenance | MaD:1 Sink:MaD:1 |
| test.rs:39:32:39:39 | password | test.rs:39:9:39:30 | ...::digest | provenance | MaD:1 Sink:MaD:1 |
| test.rs:60:26:60:37 | password_str | test.rs:60:9:60:24 | ...::digest | provenance | MaD:1 Sink:MaD:1 |
| test.rs:62:26:62:37 | password_arr | test.rs:62:9:62:24 | ...::digest | provenance | MaD:1 Sink:MaD:1 |
| test.rs:64:26:64:37 | password_vec | test.rs:64:9:64:24 | ...::digest | provenance | MaD:1 Sink:MaD:1 |
| test.rs:77:35:77:42 | password | test.rs:77:9:77:33 | ...::new_with_prefix | provenance | MaD:2 Sink:MaD:2 |
| test.rs:81:26:81:33 | password | test.rs:81:26:81:40 | password.trim() [&ref] | provenance | MaD:5 |
| test.rs:81:26:81:40 | password.trim() [&ref] | test.rs:81:9:81:24 | ...::digest | provenance | MaD:1 Sink:MaD:1 |
| test.rs:83:26:83:33 | password | test.rs:83:26:83:44 | password.as_bytes() | provenance | MaD:4 |
| test.rs:83:26:83:44 | password.as_bytes() | test.rs:83:9:83:24 | ...::digest | provenance | MaD:1 Sink:MaD:1 |
| test.rs:20:26:20:39 | credit_card_no | test.rs:20:9:20:24 | ...::compute | provenance | MaD:1 Sink:MaD:1 |
| test.rs:21:26:21:33 | password | test.rs:21:9:21:24 | ...::compute | provenance | MaD:1 Sink:MaD:1 |
models
| 1 | Sink: repo:https://github.com/RustCrypto/traits:digest; <_ as crate::digest::Digest>::digest; Argument[0]; hasher-input |
| 2 | Sink: repo:https://github.com/RustCrypto/traits:digest; <_ as crate::digest::Digest>::new_with_prefix; Argument[0]; hasher-input |
| 3 | Sink: repo:https://github.com/stainless-steel/md5:md5; crate::compute; Argument[0]; hasher-input |
| 4 | Summary: lang:core; <str>::as_bytes; Argument[self]; ReturnValue; taint |
| 5 | Summary: lang:core; <str>::trim; Argument[self]; ReturnValue.Reference; taint |
| 1 | Sink: md5::compute; Argument[0]; hasher-input |
nodes
| test.rs:14:9:14:24 | ...::digest | semmle.label | ...::digest |
| test.rs:14:26:14:39 | credit_card_no | semmle.label | credit_card_no |
| test.rs:15:9:15:24 | ...::digest | semmle.label | ...::digest |
| test.rs:15:26:15:33 | password | semmle.label | password |
| test.rs:20:9:20:24 | ...::compute | semmle.label | ...::compute |
| test.rs:20:26:20:39 | credit_card_no | semmle.label | credit_card_no |
| test.rs:21:9:21:24 | ...::compute | semmle.label | ...::compute |
| test.rs:21:26:21:33 | password | semmle.label | password |
| test.rs:26:9:26:26 | ...::digest | semmle.label | ...::digest |
| test.rs:26:28:26:41 | credit_card_no | semmle.label | credit_card_no |
| test.rs:27:9:27:26 | ...::digest | semmle.label | ...::digest |
| test.rs:27:28:27:35 | password | semmle.label | password |
| test.rs:32:9:32:34 | ...::digest | semmle.label | ...::digest |
| test.rs:32:36:32:49 | credit_card_no | semmle.label | credit_card_no |
| test.rs:33:9:33:34 | ...::digest | semmle.label | ...::digest |
| test.rs:33:36:33:43 | password | semmle.label | password |
| test.rs:39:9:39:30 | ...::digest | semmle.label | ...::digest |
| test.rs:39:32:39:39 | password | semmle.label | password |
| test.rs:60:9:60:24 | ...::digest | semmle.label | ...::digest |
| test.rs:60:26:60:37 | password_str | semmle.label | password_str |
| test.rs:62:9:62:24 | ...::digest | semmle.label | ...::digest |
| test.rs:62:26:62:37 | password_arr | semmle.label | password_arr |
| test.rs:64:9:64:24 | ...::digest | semmle.label | ...::digest |
| test.rs:64:26:64:37 | password_vec | semmle.label | password_vec |
| test.rs:77:9:77:33 | ...::new_with_prefix | semmle.label | ...::new_with_prefix |
| test.rs:77:35:77:42 | password | semmle.label | password |
| test.rs:81:9:81:24 | ...::digest | semmle.label | ...::digest |
| test.rs:81:26:81:33 | password | semmle.label | password |
| test.rs:81:26:81:40 | password.trim() [&ref] | semmle.label | password.trim() [&ref] |
| test.rs:83:9:83:24 | ...::digest | semmle.label | ...::digest |
| test.rs:83:26:83:33 | password | semmle.label | password |
| test.rs:83:26:83:44 | password.as_bytes() | semmle.label | password.as_bytes() |
subpaths
26 changes: 13 additions & 13 deletions rust/ql/test/query-tests/security/CWE-328/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ fn test_hash_algorithms(

// MD5
_ = md5::Md5::digest(harmless);
_ = md5::Md5::digest(credit_card_no); // $ Alert[rust/weak-sensitive-data-hashing]
_ = md5::Md5::digest(password); // $ Alert[rust/weak-sensitive-data-hashing]
_ = md5::Md5::digest(credit_card_no); // $ MISSING: Alert[rust/weak-sensitive-data-hashing]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently getStaticTarget() fails on md5::Md5::digest. This are the relevant lines:

pub type Md5 = CoreWrapper<Md5Core>;

impl<D: FixedOutput + Default + Update + HashMarker> Digest for D {
    fn digest(data: impl AsRef<[u8]>) -> Output<Self> { ... }
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hvitved I guess the type variable in for D is the cause of the trouble, isn't it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we don't currently handle impl<T> Foo for T; I have added this instance to our internal issue tracking this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I've just created an issue to track test results we are losing but expect to get back with type inference improvements - the idea being we can merge this before we get it back if we want to.

_ = md5::Md5::digest(password); // $ MISSING: Alert[rust/weak-sensitive-data-hashing]
_ = md5::Md5::digest(encrypted_password);

// MD5 (alternative / older library)
Expand All @@ -23,20 +23,20 @@ fn test_hash_algorithms(

// SHA-1
_ = sha1::Sha1::digest(harmless);
_ = sha1::Sha1::digest(credit_card_no); // $ Alert[rust/weak-sensitive-data-hashing]
_ = sha1::Sha1::digest(password); // $ Alert[rust/weak-sensitive-data-hashing]
_ = sha1::Sha1::digest(credit_card_no); // $ MISSING: Alert[rust/weak-sensitive-data-hashing]
_ = sha1::Sha1::digest(password); // $ MISSING: Alert[rust/weak-sensitive-data-hashing]
_ = sha1::Sha1::digest(encrypted_password);

// SHA-1 checked
_ = sha1_checked::Sha1::digest(harmless);
_ = sha1_checked::Sha1::digest(credit_card_no); // $ Alert[rust/weak-sensitive-data-hashing]
_ = sha1_checked::Sha1::digest(password); // $ Alert[rust/weak-sensitive-data-hashing]
_ = sha1_checked::Sha1::digest(credit_card_no); // $ MISSING: Alert[rust/weak-sensitive-data-hashing]
_ = sha1_checked::Sha1::digest(password); // $ MISSING: Alert[rust/weak-sensitive-data-hashing]
_ = sha1_checked::Sha1::digest(encrypted_password);

// SHA-256 (appropriate for sensitive data hashing)
_ = sha3::Sha3_256::digest(harmless);
_ = sha3::Sha3_256::digest(credit_card_no);
_ = sha3::Sha3_256::digest(password); // $ Alert[rust/weak-sensitive-data-hashing]
_ = sha3::Sha3_256::digest(password); // $ MISSING: Alert[rust/weak-sensitive-data-hashing]
_ = sha3::Sha3_256::digest(encrypted_password);

// Argon2 (appropriate for password hashing)
Expand All @@ -57,11 +57,11 @@ fn test_hash_code_patterns(

// hash different types of data
_ = md5::Md5::digest(harmless_str);
_ = md5::Md5::digest(password_str); // $ Alert[rust/weak-sensitive-data-hashing]
_ = md5::Md5::digest(password_str); // $ MISSING: Alert[rust/weak-sensitive-data-hashing]
_ = md5::Md5::digest(harmless_arr);
_ = md5::Md5::digest(password_arr); // $ Alert[rust/weak-sensitive-data-hashing]
_ = md5::Md5::digest(password_arr); // $ MISSING: Alert[rust/weak-sensitive-data-hashing]
_ = md5::Md5::digest(harmless_vec);
_ = md5::Md5::digest(password_vec); // $ Alert[rust/weak-sensitive-data-hashing]
_ = md5::Md5::digest(password_vec); // $ MISSING: Alert[rust/weak-sensitive-data-hashing]

// hash through a hasher object
let mut md5_hasher = md5::Md5::new();
Expand All @@ -74,13 +74,13 @@ fn test_hash_code_patterns(
_ = md5::Md5::new().chain_update(harmless).chain_update(password).chain_update(harmless).finalize(); // $ MISSING: Alert[rust/weak-sensitive-data-hashing]

_ = md5::Md5::new_with_prefix(harmless).finalize();
_ = md5::Md5::new_with_prefix(password).finalize(); // $ Alert[rust/weak-sensitive-data-hashing]
_ = md5::Md5::new_with_prefix(password).finalize(); // $ MISSING: Alert[rust/weak-sensitive-data-hashing]

// hash transformed data
_ = md5::Md5::digest(harmless.trim());
_ = md5::Md5::digest(password.trim()); // $ Alert[rust/weak-sensitive-data-hashing]
_ = md5::Md5::digest(password.trim()); // $ MISSING: Alert[rust/weak-sensitive-data-hashing]
_ = md5::Md5::digest(harmless.as_bytes());
_ = md5::Md5::digest(password.as_bytes()); // $ Alert[rust/weak-sensitive-data-hashing]
_ = md5::Md5::digest(password.as_bytes()); // $ MISSING: Alert[rust/weak-sensitive-data-hashing]
_ = md5::Md5::digest(std::str::from_utf8(harmless_arr).unwrap());
_ = md5::Md5::digest(std::str::from_utf8(password_arr).unwrap()); // $ MISSING: Alert[rust/weak-sensitive-data-hashing]
}
Expand Down