From 87218cb6d70ef54d9639d2afaddb1abf1ae7cffe Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 8 May 2025 11:59:10 +0100 Subject: [PATCH 01/13] Rust: Test more examples of sensitive data. --- .../test/library-tests/sensitivedata/test.rs | 115 +++++++++++++++++- 1 file changed, 110 insertions(+), 5 deletions(-) diff --git a/rust/ql/test/library-tests/sensitivedata/test.rs b/rust/ql/test/library-tests/sensitivedata/test.rs index ff5496fb7361..f42c82edd8c7 100644 --- a/rust/ql/test/library-tests/sensitivedata/test.rs +++ b/rust/ql/test/library-tests/sensitivedata/test.rs @@ -10,6 +10,7 @@ struct MyStruct { password: String, password_file_path: String, password_enabled: String, + mfa: String, } impl MyStruct { @@ -22,8 +23,8 @@ fn get_password() -> String { get_string() } fn test_passwords( password: &str, pass_word: &str, passwd: &str, my_password: &str, password_str: &str, - pass_phrase: &str, passphrase: &str, passPhrase: &str, - auth_key: &str, authkey: &str, authKey: &str, authentication_key: &str, authenticationkey: &str, authenticationKey: &str, + pass_phrase: &str, passphrase: &str, passPhrase: &str, backup_code: &str, + auth_key: &str, authkey: &str, authKey: &str, authentication_key: &str, authenticationkey: &str, authenticationKey: &str, oauth: &str, harmless: &str, encrypted_password: &str, password_hash: &str, ms: &MyStruct ) { @@ -36,6 +37,7 @@ fn test_passwords( sink(pass_phrase); // $ sensitive=password sink(passphrase); // $ sensitive=password sink(passPhrase); // $ sensitive=password + sink(backup_code); // $ MISSING: sensitive=password sink(auth_key); // $ sensitive=password sink(authkey); // $ sensitive=password @@ -43,14 +45,19 @@ fn test_passwords( sink(authentication_key); // $ sensitive=password sink(authenticationkey); // $ sensitive=password sink(authenticationKey); // $ sensitive=password + sink(oauth); // $ MISSING: sensitive=password sink(ms); // $ MISSING: sensitive=password sink(ms.password.as_str()); // $ MISSING: sensitive=password + sink(ms.mfa.as_str()); // $ MISSING: sensitive=password sink(get_password()); // $ sensitive=password let password2 = get_string(); sink(password2); // $ sensitive=password + let qry = "password=abc"; + sink(qry); // $ MISSING: sensitive=password + // not passwords sink(harmless); sink(encrypted_password); @@ -115,32 +122,98 @@ fn test_credentials( sink(get_next_token()); } +struct MacAddr { + values: [u8;12], +} + +struct DeviceInfo { + api_key: String, + deviceApiToken: String, + finger_print: String, + ip_address: String, + macaddr12: [u8;12], + mac_addr: MacAddr, + networkMacAddress: String, +} + +impl DeviceInfo { + fn test_device_info(&self, other: &DeviceInfo) { + // private device info + sink(&self.api_key); // $ MISSING: sensitive=id + sink(&other.api_key); // $ MISSING: sensitive=id + sink(&self.deviceApiToken); // $ MISSING: sensitive=id + sink(&self.finger_print); // $ MISSING: sensitive=id + sink(&self.ip_address); // $ MISSING: sensitive=id + sink(self.macaddr12); // $ MISSING: sensitive=id + sink(&self.mac_addr); // $ MISSING: sensitive=id + sink(self.mac_addr.values); // $ MISSING: sensitive=id + sink(self.mac_addr.values[0]); // $ MISSING: sensitive=id + sink(&self.networkMacAddress); // $ MISSING: sensitive=id + } +} + struct Financials { harmless: String, my_bank_account_number: String, credit_card_no: String, credit_rating: i32, - user_ccn: String + user_ccn: String, + cvv: String, + beneficiary: String, + routing_number: u64, + routingNumberText: String, + iban: String, + iBAN: String, +} + +enum Gender { + Male, + Female, +} + +struct SSN { + data: u128, +} + +impl SSN { + fn get_data(&self) -> u128 { + return self.data; + } } struct MyPrivateInfo { mobile_phone_num: String, contact_email: String, contact_e_mail_2: String, + emergency_contact: String, my_ssn: String, + ssn: SSN, birthday: String, - emergency_contact: String, name_of_employer: String, + gender: Gender, + genderString: String, + + patient_id: u64, + linkedPatientId: u64, + patient_record: String, medical_notes: Vec, + confidentialMessage: String, + latitude: f64, longitude: Option, financials: Financials } +enum ContactDetails { + HomePhoneNumber(String), + MobileNumber(String), + Email(String), +} + fn test_private_info( - info: &MyPrivateInfo + info: &MyPrivateInfo, details: &ContactDetails, ) { // private info sink(info.mobile_phone_num.as_str()); // $ MISSING: sensitive=private @@ -148,15 +221,33 @@ fn test_private_info( sink(info.contact_email.as_str()); // $ MISSING: sensitive=private sink(info.contact_e_mail_2.as_str()); // $ MISSING: sensitive=private sink(info.my_ssn.as_str()); // $ MISSING: sensitive=private + sink(&info.ssn); // $ MISSING: sensitive=private + sink(info.ssn.data); // $ MISSING: sensitive=private + sink(info.ssn.get_data()); // $ MISSING: sensitive=private sink(info.birthday.as_str()); // $ MISSING: sensitive=private sink(info.emergency_contact.as_str()); // $ MISSING: sensitive=private sink(info.name_of_employer.as_str()); // $ MISSING: sensitive=private + sink(&info.gender); // $ MISSING: sensitive=private + sink(info.genderString.as_str()); // $ MISSING: sensitive=private + let sex = "Male"; + let gender = Gender::Female; + let a = Gender::Female; + sink(sex); // $ MISSING: sensitive=private + sink(gender); // $ MISSING: sensitive=private + sink(a); // $ MISSING: sensitive=private + + sink(info.patient_id); // $ MISSING: sensitive=private + sink(info.linkedPatientId); // $ MISSING: sensitive=private + sink(info.patient_record.as_str()); // $ MISSING: sensitive=private + sink(info.patient_record.trim()); // $ MISSING: sensitive=private sink(&info.medical_notes); // $ MISSING: sensitive=private sink(info.medical_notes[0].as_str()); // $ MISSING: sensitive=private for n in info.medical_notes.iter() { sink(n.as_str()); // $ MISSING: sensitive=private } + sink(info.confidentialMessage.as_str()); // $ MISSING: sensitive=private + sink(info.confidentialMessage.to_lowercase()); // $ MISSING: sensitive=private sink(info.latitude); // $ MISSING: sensitive=private let x = info.longitude.unwrap(); @@ -166,7 +257,21 @@ fn test_private_info( sink(info.financials.credit_card_no.as_str()); // $ MISSING: sensitive=private sink(info.financials.credit_rating); // $ MISSING: sensitive=private sink(info.financials.user_ccn.as_str()); // $ MISSING: sensitive=private + sink(info.financials.cvv.as_str()); // $ MISSING: sensitive=private + sink(info.financials.beneficiary.as_str()); // $ MISSING: sensitive=private + sink(info.financials.routing_number); // $ MISSING: sensitive=private + sink(info.financials.routingNumberText.as_str()); // $ MISSING: sensitive=private + sink(info.financials.iban.as_str()); // $ MISSING: sensitive=private + sink(info.financials.iBAN.as_str()); // $ MISSING: sensitive=private + + sink(ContactDetails::HomePhoneNumber("123".to_string())); // $ MISSING: sensitive=private + sink(ContactDetails::MobileNumber("123".to_string())); // $ MISSING: sensitive=private + sink(ContactDetails::Email("a@b".to_string())); // $ MISSING: sensitive=private + if let ContactDetails::MobileNumber(num) = details { + sink(num.as_str()); // $ MISSING: sensitive=private + } // not private info + sink(info.financials.harmless.as_str()); } From 8825eefea6afe25f046016cbda2751112eb8cef0 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 8 May 2025 16:00:46 +0100 Subject: [PATCH 02/13] Rust: More counterexamples for sensitive data as well. --- .../test/library-tests/sensitivedata/test.rs | 43 ++++++++++++++++++- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/rust/ql/test/library-tests/sensitivedata/test.rs b/rust/ql/test/library-tests/sensitivedata/test.rs index f42c82edd8c7..4718a2b451e3 100644 --- a/rust/ql/test/library-tests/sensitivedata/test.rs +++ b/rust/ql/test/library-tests/sensitivedata/test.rs @@ -11,6 +11,7 @@ struct MyStruct { password_file_path: String, password_enabled: String, mfa: String, + numfailed: String, } impl MyStruct { @@ -25,10 +26,11 @@ fn test_passwords( password: &str, pass_word: &str, passwd: &str, my_password: &str, password_str: &str, pass_phrase: &str, passphrase: &str, passPhrase: &str, backup_code: &str, auth_key: &str, authkey: &str, authKey: &str, authentication_key: &str, authenticationkey: &str, authenticationKey: &str, oauth: &str, - harmless: &str, encrypted_password: &str, password_hash: &str, + harmless: &str, encrypted_password: &str, password_hash: &str, passwordFile: &str, ms: &MyStruct ) { // passwords + sink(password); // $ sensitive=password sink(pass_word); // $ MISSING: sensitive=password sink(passwd); // $ sensitive=password @@ -59,13 +61,16 @@ fn test_passwords( sink(qry); // $ MISSING: sensitive=password // not passwords + sink(harmless); sink(encrypted_password); sink(password_hash); + sink(passwordFile); // $ SPURIOUS: sensitive=password sink(ms.harmless.as_str()); sink(ms.password_file_path.as_str()); sink(ms.password_enabled.as_str()); + sink(ms.numfailed.as_str()); sink(get_string()); let harmless2 = get_string(); @@ -82,10 +87,11 @@ fn get_next_token() -> String { get_string() } fn test_credentials( account_key: &str, accnt_key: &str, license_key: &str, secret_key: &str, is_secret: bool, num_accounts: i64, username: String, user_name: String, userid: i64, user_id: i64, my_user_id_64: i64, unique_id: i64, uid: i64, - sessionkey: &[u64; 4], session_key: &[u64; 4], hashkey: &[u64; 4], hash_key: &[u64; 4], + sessionkey: &[u64; 4], session_key: &[u64; 4], hashkey: &[u64; 4], hash_key: &[u64; 4], sessionkeypath: &[u64; 4], account_key_path: &[u64; 4], ms: &MyStruct ) { // credentials + sink(account_key); // $ sensitive=id sink(accnt_key); // $ sensitive=id sink(license_key); // $ MISSING: sensitive=secret @@ -108,12 +114,15 @@ fn test_credentials( sink(get_secret_token()); // $ sensitive=secret // not (necessarily) credentials + sink(is_secret); sink(num_accounts); // $ SPURIOUS: sensitive=id sink(unique_id); sink(uid); // $ SPURIOUS: sensitive=id sink(hashkey); sink(hash_key); + sink(sessionkeypath); // $ SPURIOUS: sensitive=id + sink(account_key_path); // $ SPURIOUS: sensitive=id sink(ms.get_certificate_url()); // $ SPURIOUS: sensitive=certificate sink(ms.get_certificate_file()); // $ SPURIOUS: sensitive=certificate @@ -134,11 +143,17 @@ struct DeviceInfo { macaddr12: [u8;12], mac_addr: MacAddr, networkMacAddress: String, + + // not private device info + macro_value: bool, + mac_command: u32, + skip_address: String, } impl DeviceInfo { fn test_device_info(&self, other: &DeviceInfo) { // private device info + sink(&self.api_key); // $ MISSING: sensitive=id sink(&other.api_key); // $ MISSING: sensitive=id sink(&self.deviceApiToken); // $ MISSING: sensitive=id @@ -149,6 +164,12 @@ impl DeviceInfo { sink(self.mac_addr.values); // $ MISSING: sensitive=id sink(self.mac_addr.values[0]); // $ MISSING: sensitive=id sink(&self.networkMacAddress); // $ MISSING: sensitive=id + + // not private device info + + sink(self.macro_value); + sink(self.mac_command); + sink(&self.skip_address); } } @@ -164,6 +185,12 @@ struct Financials { routingNumberText: String, iban: String, iBAN: String, + + num_accounts: i32, + total_accounts: i32, + accounting: i32, + unaccounted: bool, + multiband: bool, } enum Gender { @@ -210,12 +237,14 @@ enum ContactDetails { HomePhoneNumber(String), MobileNumber(String), Email(String), + FavouriteColor(String), } fn test_private_info( info: &MyPrivateInfo, details: &ContactDetails, ) { // private info + sink(info.mobile_phone_num.as_str()); // $ MISSING: sensitive=private sink(info.mobile_phone_num.to_string()); // $ MISSING: sensitive=private sink(info.contact_email.as_str()); // $ MISSING: sensitive=private @@ -273,5 +302,15 @@ fn test_private_info( // not private info + let modulesEx = 1; + sink(modulesEx); + sink(info.financials.harmless.as_str()); + sink(info.financials.num_accounts); + sink(info.financials.total_accounts); + sink(info.financials.accounting); + sink(info.financials.unaccounted); + sink(info.financials.multiband); + + sink(ContactDetails::FavouriteColor("blue".to_string())); } From a537197691fba15f07676187151f2d6bd63b1da7 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 9 May 2025 10:39:53 +0100 Subject: [PATCH 03/13] Rust: Understand sensitive field access expressions. --- .../codeql/rust/security/SensitiveData.qll | 19 ++++++++- .../test/library-tests/sensitivedata/test.rs | 42 +++++++++---------- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/rust/ql/lib/codeql/rust/security/SensitiveData.qll b/rust/ql/lib/codeql/rust/security/SensitiveData.qll index 5a5f5a6dec03..698fa83197d5 100644 --- a/rust/ql/lib/codeql/rust/security/SensitiveData.qll +++ b/rust/ql/lib/codeql/rust/security/SensitiveData.qll @@ -67,7 +67,7 @@ private class SensitiveDataVariable extends Variable { } /** - * A variable access data flow node that might produce sensitive data. + * A variable access data flow node that might be sensitive data. */ private class SensitiveVariableAccess extends SensitiveData { SensitiveDataClassification classification; @@ -84,3 +84,20 @@ private class SensitiveVariableAccess extends SensitiveData { override SensitiveDataClassification getClassification() { result = classification } } + +/** + * A field access data flow node that might be sensitive data. + */ +private class SensitiveFieldAccess extends SensitiveData { + SensitiveDataClassification classification; + + SensitiveFieldAccess() { + HeuristicNames::nameIndicatesSensitiveData(this.asExpr() + .getAstNode() + .(FieldExpr) + .getIdentifier() + .getText(), classification) + } + + override SensitiveDataClassification getClassification() { result = classification } +} diff --git a/rust/ql/test/library-tests/sensitivedata/test.rs b/rust/ql/test/library-tests/sensitivedata/test.rs index 4718a2b451e3..42fb2f0693ba 100644 --- a/rust/ql/test/library-tests/sensitivedata/test.rs +++ b/rust/ql/test/library-tests/sensitivedata/test.rs @@ -50,7 +50,7 @@ fn test_passwords( sink(oauth); // $ MISSING: sensitive=password sink(ms); // $ MISSING: sensitive=password - sink(ms.password.as_str()); // $ MISSING: sensitive=password + sink(ms.password.as_str()); // $ sensitive=password sink(ms.mfa.as_str()); // $ MISSING: sensitive=password sink(get_password()); // $ sensitive=password @@ -68,8 +68,8 @@ fn test_passwords( sink(passwordFile); // $ SPURIOUS: sensitive=password sink(ms.harmless.as_str()); - sink(ms.password_file_path.as_str()); - sink(ms.password_enabled.as_str()); + sink(ms.password_file_path.as_str()); // $ SPURIOUS: sensitive=password + sink(ms.password_enabled.as_str()); // $ SPURIOUS: sensitive=password sink(ms.numfailed.as_str()); sink(get_string()); @@ -245,17 +245,17 @@ fn test_private_info( ) { // private info - sink(info.mobile_phone_num.as_str()); // $ MISSING: sensitive=private - sink(info.mobile_phone_num.to_string()); // $ MISSING: sensitive=private + sink(info.mobile_phone_num.as_str()); // $ sensitive=private + sink(info.mobile_phone_num.to_string()); // $ sensitive=private sink(info.contact_email.as_str()); // $ MISSING: sensitive=private sink(info.contact_e_mail_2.as_str()); // $ MISSING: sensitive=private - sink(info.my_ssn.as_str()); // $ MISSING: sensitive=private - sink(&info.ssn); // $ MISSING: sensitive=private + sink(info.my_ssn.as_str()); // $ sensitive=private + sink(&info.ssn); // $ sensitive=private sink(info.ssn.data); // $ MISSING: sensitive=private sink(info.ssn.get_data()); // $ MISSING: sensitive=private - sink(info.birthday.as_str()); // $ MISSING: sensitive=private - sink(info.emergency_contact.as_str()); // $ MISSING: sensitive=private - sink(info.name_of_employer.as_str()); // $ MISSING: sensitive=private + sink(info.birthday.as_str()); // $ sensitive=private + sink(info.emergency_contact.as_str()); // $ sensitive=private + sink(info.name_of_employer.as_str()); // $ sensitive=private sink(&info.gender); // $ MISSING: sensitive=private sink(info.genderString.as_str()); // $ MISSING: sensitive=private @@ -270,22 +270,22 @@ fn test_private_info( sink(info.linkedPatientId); // $ MISSING: sensitive=private sink(info.patient_record.as_str()); // $ MISSING: sensitive=private sink(info.patient_record.trim()); // $ MISSING: sensitive=private - sink(&info.medical_notes); // $ MISSING: sensitive=private - sink(info.medical_notes[0].as_str()); // $ MISSING: sensitive=private + sink(&info.medical_notes); // $ sensitive=private + sink(info.medical_notes[0].as_str()); // $ sensitive=private for n in info.medical_notes.iter() { sink(n.as_str()); // $ MISSING: sensitive=private } sink(info.confidentialMessage.as_str()); // $ MISSING: sensitive=private sink(info.confidentialMessage.to_lowercase()); // $ MISSING: sensitive=private - sink(info.latitude); // $ MISSING: sensitive=private + sink(info.latitude); // $ sensitive=private let x = info.longitude.unwrap(); sink(x); // $ MISSING: sensitive=private - sink(info.financials.my_bank_account_number.as_str()); // $ MISSING: sensitive=private - sink(info.financials.credit_card_no.as_str()); // $ MISSING: sensitive=private - sink(info.financials.credit_rating); // $ MISSING: sensitive=private - sink(info.financials.user_ccn.as_str()); // $ MISSING: sensitive=private + sink(info.financials.my_bank_account_number.as_str()); // $ sensitive=private SPURIOUS: sensitive=id + sink(info.financials.credit_card_no.as_str()); // $ sensitive=private + sink(info.financials.credit_rating); // $ sensitive=private + sink(info.financials.user_ccn.as_str()); // $ sensitive=private sink(info.financials.cvv.as_str()); // $ MISSING: sensitive=private sink(info.financials.beneficiary.as_str()); // $ MISSING: sensitive=private sink(info.financials.routing_number); // $ MISSING: sensitive=private @@ -306,10 +306,10 @@ fn test_private_info( sink(modulesEx); sink(info.financials.harmless.as_str()); - sink(info.financials.num_accounts); - sink(info.financials.total_accounts); - sink(info.financials.accounting); - sink(info.financials.unaccounted); + sink(info.financials.num_accounts); // $ SPURIOUS: sensitive=id + sink(info.financials.total_accounts); // $ SPURIOUS: sensitive=id + sink(info.financials.accounting); // $ SPURIOUS: sensitive=id + sink(info.financials.unaccounted); // $ SPURIOUS: sensitive=id sink(info.financials.multiband); sink(ContactDetails::FavouriteColor("blue".to_string())); From 0f36e1d625cbd6e57f8c6060327ff76cc8331bff Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 9 May 2025 11:26:23 +0100 Subject: [PATCH 04/13] Rust: Understand sensitive qualifier expressions. --- rust/ql/lib/codeql/rust/security/SensitiveData.qll | 8 +++----- rust/ql/test/library-tests/sensitivedata/test.rs | 8 ++++---- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/rust/ql/lib/codeql/rust/security/SensitiveData.qll b/rust/ql/lib/codeql/rust/security/SensitiveData.qll index 698fa83197d5..5a384feabc24 100644 --- a/rust/ql/lib/codeql/rust/security/SensitiveData.qll +++ b/rust/ql/lib/codeql/rust/security/SensitiveData.qll @@ -92,11 +92,9 @@ private class SensitiveFieldAccess extends SensitiveData { SensitiveDataClassification classification; SensitiveFieldAccess() { - HeuristicNames::nameIndicatesSensitiveData(this.asExpr() - .getAstNode() - .(FieldExpr) - .getIdentifier() - .getText(), classification) + exists(FieldExpr fe | fe.getParentNode*() = this.asExpr().getAstNode() | + HeuristicNames::nameIndicatesSensitiveData(fe.getIdentifier().getText(), classification) + ) } override SensitiveDataClassification getClassification() { result = classification } diff --git a/rust/ql/test/library-tests/sensitivedata/test.rs b/rust/ql/test/library-tests/sensitivedata/test.rs index 42fb2f0693ba..e1d07f16d47e 100644 --- a/rust/ql/test/library-tests/sensitivedata/test.rs +++ b/rust/ql/test/library-tests/sensitivedata/test.rs @@ -251,8 +251,8 @@ fn test_private_info( sink(info.contact_e_mail_2.as_str()); // $ MISSING: sensitive=private sink(info.my_ssn.as_str()); // $ sensitive=private sink(&info.ssn); // $ sensitive=private - sink(info.ssn.data); // $ MISSING: sensitive=private - sink(info.ssn.get_data()); // $ MISSING: sensitive=private + sink(info.ssn.data); // $ sensitive=private + sink(info.ssn.get_data()); // $ sensitive=private sink(info.birthday.as_str()); // $ sensitive=private sink(info.emergency_contact.as_str()); // $ sensitive=private sink(info.name_of_employer.as_str()); // $ sensitive=private @@ -273,14 +273,14 @@ fn test_private_info( sink(&info.medical_notes); // $ sensitive=private sink(info.medical_notes[0].as_str()); // $ sensitive=private for n in info.medical_notes.iter() { - sink(n.as_str()); // $ MISSING: sensitive=private + sink(n.as_str()); // $ sensitive=private } sink(info.confidentialMessage.as_str()); // $ MISSING: sensitive=private sink(info.confidentialMessage.to_lowercase()); // $ MISSING: sensitive=private sink(info.latitude); // $ sensitive=private let x = info.longitude.unwrap(); - sink(x); // $ MISSING: sensitive=private + sink(x); // $ sensitive=private sink(info.financials.my_bank_account_number.as_str()); // $ sensitive=private SPURIOUS: sensitive=id sink(info.financials.credit_card_no.as_str()); // $ sensitive=private From 5f5d6f679a71ce695059720d39c7af196fcf9482 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 9 May 2025 11:58:51 +0100 Subject: [PATCH 05/13] Rust: Understand sensitive enum variants calls. --- .../codeql/rust/security/SensitiveData.qll | 31 +++++++++++++++++-- .../test/library-tests/sensitivedata/test.rs | 4 +-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/rust/ql/lib/codeql/rust/security/SensitiveData.qll b/rust/ql/lib/codeql/rust/security/SensitiveData.qll index 5a384feabc24..1a7571a912ed 100644 --- a/rust/ql/lib/codeql/rust/security/SensitiveData.qll +++ b/rust/ql/lib/codeql/rust/security/SensitiveData.qll @@ -37,10 +37,10 @@ private class SensitiveDataFunction extends Function { /** * A function call data flow node that might produce sensitive data. */ -private class SensitiveDataCall extends SensitiveData { +private class SensitiveDataFunctionCall extends SensitiveData { SensitiveDataClassification classification; - SensitiveDataCall() { + SensitiveDataFunctionCall() { classification = this.asExpr() .getAstNode() @@ -53,6 +53,33 @@ private class SensitiveDataCall extends SensitiveData { override SensitiveDataClassification getClassification() { result = classification } } +/** + * An enum variant that might produce sensitive data. + */ +private class SensitiveDataVariant extends Variant { + SensitiveDataClassification classification; + + SensitiveDataVariant() { + HeuristicNames::nameIndicatesSensitiveData(this.getName().getText(), classification) + } + + SensitiveDataClassification getClassification() { result = classification } +} + +/** + * An enum variant call data flow node that might produce sensitive data. + */ +private class SensitiveDataVariantCall extends SensitiveData { + SensitiveDataClassification classification; + + SensitiveDataVariantCall() { + classification = + this.asExpr().getAstNode().(CallExpr).getVariant().(SensitiveDataVariant).getClassification() + } + + override SensitiveDataClassification getClassification() { result = classification } +} + /** * A variable that might contain sensitive data. */ diff --git a/rust/ql/test/library-tests/sensitivedata/test.rs b/rust/ql/test/library-tests/sensitivedata/test.rs index e1d07f16d47e..c4f4a57b8dee 100644 --- a/rust/ql/test/library-tests/sensitivedata/test.rs +++ b/rust/ql/test/library-tests/sensitivedata/test.rs @@ -293,8 +293,8 @@ fn test_private_info( sink(info.financials.iban.as_str()); // $ MISSING: sensitive=private sink(info.financials.iBAN.as_str()); // $ MISSING: sensitive=private - sink(ContactDetails::HomePhoneNumber("123".to_string())); // $ MISSING: sensitive=private - sink(ContactDetails::MobileNumber("123".to_string())); // $ MISSING: sensitive=private + sink(ContactDetails::HomePhoneNumber("123".to_string())); // $ sensitive=private + sink(ContactDetails::MobileNumber("123".to_string())); // $ sensitive=private sink(ContactDetails::Email("a@b".to_string())); // $ MISSING: sensitive=private if let ContactDetails::MobileNumber(num) = details { sink(num.as_str()); // $ MISSING: sensitive=private From d02d5c5baf435e73b9bc7fada768631831ec6cba Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 9 May 2025 14:33:26 +0100 Subject: [PATCH 06/13] Rust: Update cleartext logging test with new found results. --- .../security/CWE-312/CleartextLogging.expected | 8 ++++++++ rust/ql/test/query-tests/security/CWE-312/test_logging.rs | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/rust/ql/test/query-tests/security/CWE-312/CleartextLogging.expected b/rust/ql/test/query-tests/security/CWE-312/CleartextLogging.expected index 61218e9c9085..19efc0e19716 100644 --- a/rust/ql/test/query-tests/security/CWE-312/CleartextLogging.expected +++ b/rust/ql/test/query-tests/security/CWE-312/CleartextLogging.expected @@ -28,6 +28,8 @@ | 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 $@ to a log file. | test_logging.rs:99:38:99:45 | password | password | | 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 $@ to a log file. | test_logging.rs:118:28:118:41 | get_password(...) | get_password(...) | | test_logging.rs:131:5:131:32 | ...::log | test_logging.rs:129:25:129:32 | password | test_logging.rs:131:5:131:32 | ...::log | This operation writes $@ to a log file. | test_logging.rs:129:25:129:32 | password | password | +| test_logging.rs:138:5:138:38 | ...::log | test_logging.rs:138:11:138:37 | MacroExpr | test_logging.rs:138:5:138:38 | ...::log | This operation writes $@ to a log file. | test_logging.rs:138:11:138:37 | MacroExpr | MacroExpr | +| test_logging.rs:145:5:145:38 | ...::log | test_logging.rs:145:11:145:37 | MacroExpr | test_logging.rs:145:5:145:38 | ...::log | This operation writes $@ to a log file. | test_logging.rs:145:11:145:37 | MacroExpr | MacroExpr | | test_logging.rs:152:5:152:38 | ...::_print | test_logging.rs:152:30:152:37 | password | test_logging.rs:152:5:152:38 | ...::_print | This operation writes $@ to a log file. | test_logging.rs:152:30:152:37 | password | password | | test_logging.rs:153:5:153:38 | ...::_print | test_logging.rs:153:30:153:37 | password | test_logging.rs:153:5:153:38 | ...::_print | This operation writes $@ to a log file. | test_logging.rs:153:30:153:37 | password | password | | test_logging.rs:154:5:154:39 | ...::_eprint | test_logging.rs:154:31:154:38 | password | test_logging.rs:154:5:154:39 | ...::_eprint | This operation writes $@ to a log file. | test_logging.rs:154:31:154:38 | password | password | @@ -148,6 +150,8 @@ edges | test_logging.rs:131:12:131:31 | MacroExpr | test_logging.rs:131:5:131:32 | ...::log | provenance | MaD:9 Sink:MaD:9 | | test_logging.rs:131:28:131:29 | t1 [tuple.1] | test_logging.rs:131:28:131:31 | t1.1 | provenance | | | test_logging.rs:131:28:131:31 | t1.1 | test_logging.rs:131:12:131:31 | MacroExpr | provenance | | +| test_logging.rs:138:11:138:37 | MacroExpr | test_logging.rs:138:5:138:38 | ...::log | provenance | MaD:9 Sink:MaD:9 | +| test_logging.rs:145:11:145:37 | MacroExpr | test_logging.rs:145:5:145:38 | ...::log | provenance | MaD:9 Sink:MaD:9 | | test_logging.rs:152:12:152:37 | MacroExpr | test_logging.rs:152:5:152:38 | ...::_print | provenance | MaD:8 Sink:MaD:8 | | test_logging.rs:152:30:152:37 | password | test_logging.rs:152:12:152:37 | MacroExpr | provenance | | | test_logging.rs:153:14:153:37 | MacroExpr | test_logging.rs:153:5:153:38 | ...::_print | provenance | MaD:8 Sink:MaD:8 | @@ -352,6 +356,10 @@ nodes | test_logging.rs:131:12:131:31 | MacroExpr | semmle.label | MacroExpr | | test_logging.rs:131:28:131:29 | t1 [tuple.1] | semmle.label | t1 [tuple.1] | | test_logging.rs:131:28:131:31 | t1.1 | semmle.label | t1.1 | +| test_logging.rs:138:5:138:38 | ...::log | semmle.label | ...::log | +| test_logging.rs:138:11:138:37 | MacroExpr | semmle.label | MacroExpr | +| test_logging.rs:145:5:145:38 | ...::log | semmle.label | ...::log | +| test_logging.rs:145:11:145:37 | MacroExpr | semmle.label | MacroExpr | | test_logging.rs:152:5:152:38 | ...::_print | semmle.label | ...::_print | | test_logging.rs:152:12:152:37 | MacroExpr | semmle.label | MacroExpr | | test_logging.rs:152:30:152:37 | password | semmle.label | password | diff --git a/rust/ql/test/query-tests/security/CWE-312/test_logging.rs b/rust/ql/test/query-tests/security/CWE-312/test_logging.rs index 970a9caf0ee5..8606d2f9b22d 100644 --- a/rust/ql/test/query-tests/security/CWE-312/test_logging.rs +++ b/rust/ql/test/query-tests/security/CWE-312/test_logging.rs @@ -135,14 +135,14 @@ fn test_log(harmless: String, password: String, encrypted_password: String) { // logging from a struct let s1 = MyStruct1 { harmless: "foo".to_string(), password: "123456".to_string() }; // $ MISSING: Source=s1 warn!("message = {}", s1.harmless); - warn!("message = {}", s1.password); // $ MISSING: Alert[rust/cleartext-logging] + warn!("message = {}", s1.password); // $ Alert[rust/cleartext-logging] warn!("message = {}", s1); // $ MISSING: Alert[rust/cleartext-logging]=s1 warn!("message = {:?}", s1); // $ MISSING: Alert[rust/cleartext-logging]=s1 warn!("message = {:#?}", s1); // $ MISSING: Alert[rust/cleartext-logging]=s1 let s2 = MyStruct2 { harmless: "foo".to_string(), password: "123456".to_string() }; // $ MISSING: Source=s2 warn!("message = {}", s2.harmless); - warn!("message = {}", s2.password); // $ MISSING: Alert[rust/cleartext-logging] + warn!("message = {}", s2.password); // $ Alert[rust/cleartext-logging] warn!("message = {}", s2); // (this implementation does not output the password field) warn!("message = {:?}", s2); // $ MISSING: Alert[rust/cleartext-logging]=s2 warn!("message = {:#?}", s2); // $ MISSING: Alert[rust/cleartext-logging]=s2 From 0a3275e0b3fb80ac50cbb4b89934bd37387fdec1 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 12 May 2025 11:50:57 +0100 Subject: [PATCH 07/13] Rust: One more test case. --- rust/ql/test/library-tests/sensitivedata/test.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rust/ql/test/library-tests/sensitivedata/test.rs b/rust/ql/test/library-tests/sensitivedata/test.rs index c4f4a57b8dee..02ac0bdfff3a 100644 --- a/rust/ql/test/library-tests/sensitivedata/test.rs +++ b/rust/ql/test/library-tests/sensitivedata/test.rs @@ -26,6 +26,7 @@ fn test_passwords( password: &str, pass_word: &str, passwd: &str, my_password: &str, password_str: &str, pass_phrase: &str, passphrase: &str, passPhrase: &str, backup_code: &str, auth_key: &str, authkey: &str, authKey: &str, authentication_key: &str, authenticationkey: &str, authenticationKey: &str, oauth: &str, + one_time_code: &str, harmless: &str, encrypted_password: &str, password_hash: &str, passwordFile: &str, ms: &MyStruct ) { @@ -48,6 +49,7 @@ fn test_passwords( sink(authenticationkey); // $ sensitive=password sink(authenticationKey); // $ sensitive=password sink(oauth); // $ MISSING: sensitive=password + sink(one_time_code); // $ MISSING: sensitive=password sink(ms); // $ MISSING: sensitive=password sink(ms.password.as_str()); // $ sensitive=password From b907cfe468de58cd90c46d66c19e9f2fe8862bcb Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 12 May 2025 12:30:50 +0100 Subject: [PATCH 08/13] Rust: Add a few more test cases involving 'map'. --- .../test/library-tests/sensitivedata/test.rs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/rust/ql/test/library-tests/sensitivedata/test.rs b/rust/ql/test/library-tests/sensitivedata/test.rs index 02ac0bdfff3a..f74de9f5bf86 100644 --- a/rust/ql/test/library-tests/sensitivedata/test.rs +++ b/rust/ql/test/library-tests/sensitivedata/test.rs @@ -242,6 +242,10 @@ enum ContactDetails { FavouriteColor(String), } +struct ContactDetails2 { + home_phone_number: String, +} + fn test_private_info( info: &MyPrivateInfo, details: &ContactDetails, ) { @@ -298,9 +302,34 @@ fn test_private_info( sink(ContactDetails::HomePhoneNumber("123".to_string())); // $ sensitive=private sink(ContactDetails::MobileNumber("123".to_string())); // $ sensitive=private sink(ContactDetails::Email("a@b".to_string())); // $ MISSING: sensitive=private + + let numbers = [1, 2, 3]; + if let ContactDetails::MobileNumber(num) = details { sink(num.as_str()); // $ MISSING: sensitive=private } + let contacts = numbers.map(|number| + { + let contact = ContactDetails::MobileNumber(number.to_string()); + sink(&contact); // $ sensitive=private + contact + } + ); + sink(&contacts[0]); // $ MISSING: sensitive=private + if let ContactDetails::HomePhoneNumber(num) = &contacts[0] { + sink(num.as_str()); // $ MISSING: sensitive=private + } + + let contacts2 = numbers.map(|number| + { + let contact = ContactDetails2 { + home_phone_number: number.to_string(), + }; + sink(&contact.home_phone_number); // $ sensitive=private + contact + } + ); + sink(&contacts2[0].home_phone_number); // $ sensitive=private // not private info From ac5ec06736b002cca4fd1ad271188d2d1128d640 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 12 May 2025 12:47:31 +0100 Subject: [PATCH 09/13] Rust: Constrain SensitiveFieldAccess to avoid including unwanted parents. --- rust/ql/lib/codeql/rust/security/SensitiveData.qll | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rust/ql/lib/codeql/rust/security/SensitiveData.qll b/rust/ql/lib/codeql/rust/security/SensitiveData.qll index 1a7571a912ed..43282ed7d937 100644 --- a/rust/ql/lib/codeql/rust/security/SensitiveData.qll +++ b/rust/ql/lib/codeql/rust/security/SensitiveData.qll @@ -112,6 +112,10 @@ private class SensitiveVariableAccess extends SensitiveData { override SensitiveDataClassification getClassification() { result = classification } } +Expr fieldExprParentField(FieldExpr fe) { + result = fe.getParentNode() +} + /** * A field access data flow node that might be sensitive data. */ @@ -119,7 +123,7 @@ private class SensitiveFieldAccess extends SensitiveData { SensitiveDataClassification classification; SensitiveFieldAccess() { - exists(FieldExpr fe | fe.getParentNode*() = this.asExpr().getAstNode() | + exists(FieldExpr fe | fieldExprParentField*(fe) = this.asExpr().getAstNode() | HeuristicNames::nameIndicatesSensitiveData(fe.getIdentifier().getText(), classification) ) } From 682f59fc11a1374ca0fd5fc3b7c3e0c50a0f9324 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 12 May 2025 12:49:58 +0100 Subject: [PATCH 10/13] Rust: Make helper predicate private + autoformat. --- rust/ql/lib/codeql/rust/security/SensitiveData.qll | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/rust/ql/lib/codeql/rust/security/SensitiveData.qll b/rust/ql/lib/codeql/rust/security/SensitiveData.qll index 43282ed7d937..3dcc48a799ae 100644 --- a/rust/ql/lib/codeql/rust/security/SensitiveData.qll +++ b/rust/ql/lib/codeql/rust/security/SensitiveData.qll @@ -112,9 +112,7 @@ private class SensitiveVariableAccess extends SensitiveData { override SensitiveDataClassification getClassification() { result = classification } } -Expr fieldExprParentField(FieldExpr fe) { - result = fe.getParentNode() -} +private Expr fieldExprParentField(FieldExpr fe) { result = fe.getParentNode() } /** * A field access data flow node that might be sensitive data. From f04d6fd8c827d585dfc4e543193e86b6240bb635 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 12 May 2025 17:45:00 +0100 Subject: [PATCH 11/13] Rust: Accept minor test changes for the cleartext logging query. --- .../security/CWE-312/CleartextLogging.expected | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/rust/ql/test/query-tests/security/CWE-312/CleartextLogging.expected b/rust/ql/test/query-tests/security/CWE-312/CleartextLogging.expected index 19efc0e19716..dc304a699e5a 100644 --- a/rust/ql/test/query-tests/security/CWE-312/CleartextLogging.expected +++ b/rust/ql/test/query-tests/security/CWE-312/CleartextLogging.expected @@ -28,8 +28,8 @@ | 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 $@ to a log file. | test_logging.rs:99:38:99:45 | password | password | | 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 $@ to a log file. | test_logging.rs:118:28:118:41 | get_password(...) | get_password(...) | | test_logging.rs:131:5:131:32 | ...::log | test_logging.rs:129:25:129:32 | password | test_logging.rs:131:5:131:32 | ...::log | This operation writes $@ to a log file. | test_logging.rs:129:25:129:32 | password | password | -| test_logging.rs:138:5:138:38 | ...::log | test_logging.rs:138:11:138:37 | MacroExpr | test_logging.rs:138:5:138:38 | ...::log | This operation writes $@ to a log file. | test_logging.rs:138:11:138:37 | MacroExpr | MacroExpr | -| test_logging.rs:145:5:145:38 | ...::log | test_logging.rs:145:11:145:37 | MacroExpr | test_logging.rs:145:5:145:38 | ...::log | This operation writes $@ to a log file. | test_logging.rs:145:11:145:37 | MacroExpr | MacroExpr | +| test_logging.rs:138:5:138:38 | ...::log | test_logging.rs:138:27:138:37 | s1.password | test_logging.rs:138:5:138:38 | ...::log | This operation writes $@ to a log file. | test_logging.rs:138:27:138:37 | s1.password | s1.password | +| test_logging.rs:145:5:145:38 | ...::log | test_logging.rs:145:27:145:37 | s2.password | test_logging.rs:145:5:145:38 | ...::log | This operation writes $@ to a log file. | test_logging.rs:145:27:145:37 | s2.password | s2.password | | test_logging.rs:152:5:152:38 | ...::_print | test_logging.rs:152:30:152:37 | password | test_logging.rs:152:5:152:38 | ...::_print | This operation writes $@ to a log file. | test_logging.rs:152:30:152:37 | password | password | | test_logging.rs:153:5:153:38 | ...::_print | test_logging.rs:153:30:153:37 | password | test_logging.rs:153:5:153:38 | ...::_print | This operation writes $@ to a log file. | test_logging.rs:153:30:153:37 | password | password | | test_logging.rs:154:5:154:39 | ...::_eprint | test_logging.rs:154:31:154:38 | password | test_logging.rs:154:5:154:39 | ...::_eprint | This operation writes $@ to a log file. | test_logging.rs:154:31:154:38 | password | password | @@ -151,7 +151,9 @@ edges | test_logging.rs:131:28:131:29 | t1 [tuple.1] | test_logging.rs:131:28:131:31 | t1.1 | provenance | | | test_logging.rs:131:28:131:31 | t1.1 | test_logging.rs:131:12:131:31 | MacroExpr | provenance | | | test_logging.rs:138:11:138:37 | MacroExpr | test_logging.rs:138:5:138:38 | ...::log | provenance | MaD:9 Sink:MaD:9 | +| test_logging.rs:138:27:138:37 | s1.password | test_logging.rs:138:11:138:37 | MacroExpr | provenance | | | test_logging.rs:145:11:145:37 | MacroExpr | test_logging.rs:145:5:145:38 | ...::log | provenance | MaD:9 Sink:MaD:9 | +| test_logging.rs:145:27:145:37 | s2.password | test_logging.rs:145:11:145:37 | MacroExpr | provenance | | | test_logging.rs:152:12:152:37 | MacroExpr | test_logging.rs:152:5:152:38 | ...::_print | provenance | MaD:8 Sink:MaD:8 | | test_logging.rs:152:30:152:37 | password | test_logging.rs:152:12:152:37 | MacroExpr | provenance | | | test_logging.rs:153:14:153:37 | MacroExpr | test_logging.rs:153:5:153:38 | ...::_print | provenance | MaD:8 Sink:MaD:8 | @@ -358,8 +360,10 @@ nodes | test_logging.rs:131:28:131:31 | t1.1 | semmle.label | t1.1 | | test_logging.rs:138:5:138:38 | ...::log | semmle.label | ...::log | | test_logging.rs:138:11:138:37 | MacroExpr | semmle.label | MacroExpr | +| test_logging.rs:138:27:138:37 | s1.password | semmle.label | s1.password | | test_logging.rs:145:5:145:38 | ...::log | semmle.label | ...::log | | test_logging.rs:145:11:145:37 | MacroExpr | semmle.label | MacroExpr | +| test_logging.rs:145:27:145:37 | s2.password | semmle.label | s2.password | | test_logging.rs:152:5:152:38 | ...::_print | semmle.label | ...::_print | | test_logging.rs:152:12:152:37 | MacroExpr | semmle.label | MacroExpr | | test_logging.rs:152:30:152:37 | password | semmle.label | password | From 4bbdc9a1cddd9bbabb5013357a12714471184e27 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 19 May 2025 12:08:53 +0100 Subject: [PATCH 12/13] Rust: Simplify SensitiveData.qll. --- .../codeql/rust/security/SensitiveData.qll | 82 ++++--------------- 1 file changed, 15 insertions(+), 67 deletions(-) diff --git a/rust/ql/lib/codeql/rust/security/SensitiveData.qll b/rust/ql/lib/codeql/rust/security/SensitiveData.qll index 3dcc48a799ae..703a5099317a 100644 --- a/rust/ql/lib/codeql/rust/security/SensitiveData.qll +++ b/rust/ql/lib/codeql/rust/security/SensitiveData.qll @@ -22,77 +22,26 @@ abstract class SensitiveData extends DataFlow::Node { } /** - * A function that might produce sensitive data. + * A function call or enum variant data flow node that might produce sensitive data. */ -private class SensitiveDataFunction extends Function { +private class SensitiveDataCall extends SensitiveData { SensitiveDataClassification classification; - SensitiveDataFunction() { - HeuristicNames::nameIndicatesSensitiveData(this.getName().getText(), classification) - } - - SensitiveDataClassification getClassification() { result = classification } -} - -/** - * A function call data flow node that might produce sensitive data. - */ -private class SensitiveDataFunctionCall extends SensitiveData { - SensitiveDataClassification classification; - - SensitiveDataFunctionCall() { - classification = - this.asExpr() - .getAstNode() - .(CallExprBase) - .getStaticTarget() - .(SensitiveDataFunction) - .getClassification() - } - - override SensitiveDataClassification getClassification() { result = classification } -} - -/** - * An enum variant that might produce sensitive data. - */ -private class SensitiveDataVariant extends Variant { - SensitiveDataClassification classification; - - SensitiveDataVariant() { - HeuristicNames::nameIndicatesSensitiveData(this.getName().getText(), classification) - } - - SensitiveDataClassification getClassification() { result = classification } -} - -/** - * An enum variant call data flow node that might produce sensitive data. - */ -private class SensitiveDataVariantCall extends SensitiveData { - SensitiveDataClassification classification; - - SensitiveDataVariantCall() { - classification = - this.asExpr().getAstNode().(CallExpr).getVariant().(SensitiveDataVariant).getClassification() + SensitiveDataCall() { + exists(CallExprBase call, string name | + call = this.asExpr().getExpr() and + name = + [ + call.getStaticTarget().(Function).getName().getText(), + call.(CallExpr).getVariant().getName().getText(), + ] and + HeuristicNames::nameIndicatesSensitiveData(name, classification) + ) } override SensitiveDataClassification getClassification() { result = classification } } -/** - * A variable that might contain sensitive data. - */ -private class SensitiveDataVariable extends Variable { - SensitiveDataClassification classification; - - SensitiveDataVariable() { - HeuristicNames::nameIndicatesSensitiveData(this.getText(), classification) - } - - SensitiveDataClassification getClassification() { result = classification } -} - /** * A variable access data flow node that might be sensitive data. */ @@ -100,13 +49,12 @@ private class SensitiveVariableAccess extends SensitiveData { SensitiveDataClassification classification; SensitiveVariableAccess() { - classification = - this.asExpr() + HeuristicNames::nameIndicatesSensitiveData(this.asExpr() .getAstNode() .(VariableAccess) .getVariable() - .(SensitiveDataVariable) - .getClassification() + .(Variable) + .getText(), classification) } override SensitiveDataClassification getClassification() { result = classification } From b503b1ef6ccae745b728267da585dc0559333bb5 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 19 May 2025 12:09:27 +0100 Subject: [PATCH 13/13] Rust: Prefer getExpr() over getAstNode(). --- rust/ql/lib/codeql/rust/security/SensitiveData.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/ql/lib/codeql/rust/security/SensitiveData.qll b/rust/ql/lib/codeql/rust/security/SensitiveData.qll index 703a5099317a..bf3364abdb6b 100644 --- a/rust/ql/lib/codeql/rust/security/SensitiveData.qll +++ b/rust/ql/lib/codeql/rust/security/SensitiveData.qll @@ -50,7 +50,7 @@ private class SensitiveVariableAccess extends SensitiveData { SensitiveVariableAccess() { HeuristicNames::nameIndicatesSensitiveData(this.asExpr() - .getAstNode() + .getExpr() .(VariableAccess) .getVariable() .(Variable) @@ -69,7 +69,7 @@ private class SensitiveFieldAccess extends SensitiveData { SensitiveDataClassification classification; SensitiveFieldAccess() { - exists(FieldExpr fe | fieldExprParentField*(fe) = this.asExpr().getAstNode() | + exists(FieldExpr fe | fieldExprParentField*(fe) = this.asExpr().getExpr() | HeuristicNames::nameIndicatesSensitiveData(fe.getIdentifier().getText(), classification) ) }