diff --git a/rust/ql/lib/codeql/rust/security/CleartextLoggingExtensions.qll b/rust/ql/lib/codeql/rust/security/CleartextLoggingExtensions.qll index c728d29f0155..4d69c5c61777 100644 --- a/rust/ql/lib/codeql/rust/security/CleartextLoggingExtensions.qll +++ b/rust/ql/lib/codeql/rust/security/CleartextLoggingExtensions.qll @@ -36,7 +36,11 @@ module CleartextLogging { /** * Sensitive data, considered as a flow source. */ - private class SensitiveDataAsSource extends Source instanceof SensitiveData { } + private class SensitiveDataAsSource extends Source instanceof SensitiveData { + SensitiveDataAsSource() { + SensitiveData.super.getClassification() != SensitiveDataClassification::id() + } + } /** * A sink for logging from model data. diff --git a/rust/ql/lib/codeql/rust/security/CleartextStorageDatabaseExtensions.qll b/rust/ql/lib/codeql/rust/security/CleartextStorageDatabaseExtensions.qll index afbf27e5bc9e..757447bc38a4 100644 --- a/rust/ql/lib/codeql/rust/security/CleartextStorageDatabaseExtensions.qll +++ b/rust/ql/lib/codeql/rust/security/CleartextStorageDatabaseExtensions.qll @@ -35,7 +35,11 @@ module CleartextStorageDatabase { /** * Sensitive data, considered as a flow source. */ - private class SensitiveDataAsSource extends Source instanceof SensitiveData { } + private class SensitiveDataAsSource extends Source instanceof SensitiveData { + SensitiveDataAsSource() { + SensitiveData.super.getClassification() != SensitiveDataClassification::id() + } + } /** * A sink for cleartext storage vulnerabilities from model data. diff --git a/rust/ql/lib/codeql/rust/security/CleartextTransmissionExtensions.qll b/rust/ql/lib/codeql/rust/security/CleartextTransmissionExtensions.qll index 14ee95186c3a..7bad60249a3c 100644 --- a/rust/ql/lib/codeql/rust/security/CleartextTransmissionExtensions.qll +++ b/rust/ql/lib/codeql/rust/security/CleartextTransmissionExtensions.qll @@ -48,7 +48,11 @@ module CleartextTransmission { /** * Sensitive data, considered as a flow source. */ - private class SensitiveDataAsSource extends Source instanceof SensitiveData { } + private class SensitiveDataAsSource extends Source instanceof SensitiveData { + SensitiveDataAsSource() { + SensitiveData.super.getClassification() != SensitiveDataClassification::id() + } + } /** * A sink defined through MaD. diff --git a/rust/ql/src/change-notes/2026-11-02-cleartext-account-identifiers.md b/rust/ql/src/change-notes/2026-11-02-cleartext-account-identifiers.md new file mode 100644 index 000000000000..fbfc8cabce98 --- /dev/null +++ b/rust/ql/src/change-notes/2026-11-02-cleartext-account-identifiers.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The `rust/cleartext-logging`, `rust/cleartext-storage-database` and `rust/cleartext-transmission` queries no longer treat account identifiers, such as user IDs and UUIDs, as sensitive data. diff --git a/rust/ql/test/library-tests/sensitivedata/test.rs b/rust/ql/test/library-tests/sensitivedata/test.rs index e2bb5a5f595c..3d0c20b95862 100644 --- a/rust/ql/test/library-tests/sensitivedata/test.rs +++ b/rust/ql/test/library-tests/sensitivedata/test.rs @@ -105,8 +105,8 @@ fn test_credentials( ) { // credentials - sink(account_key); // $ sensitive=id - sink(accnt_key); // $ sensitive=id + sink(account_key); // $ sensitive=secret + sink(accnt_key); // $ sensitive=secret sink(license_key); // $ MISSING: sensitive=secret sink(secret_key); // $ sensitive=secret @@ -116,8 +116,8 @@ fn test_credentials( sink(user_id); // $ sensitive=id sink(my_user_id_64); // $ sensitive=id - sink(sessionkey); // $ sensitive=id - sink(session_key); // $ sensitive=id + sink(sessionkey); // $ sensitive=secret + sink(session_key); // $ sensitive=secret sink(ms.get_certificate()); // $ sensitive=certificate diff --git a/rust/ql/test/query-tests/security/CWE-311/CleartextTransmission.expected b/rust/ql/test/query-tests/security/CWE-311/CleartextTransmission.expected index 9a12c86d010f..d4e93bcfbcb6 100644 --- a/rust/ql/test/query-tests/security/CWE-311/CleartextTransmission.expected +++ b/rust/ql/test/query-tests/security/CWE-311/CleartextTransmission.expected @@ -4,6 +4,7 @@ | main.rs:21:17:21:19 | url | main.rs:19:50:19:57 | password | main.rs:21:17:21:19 | url | This 'url' operation transmits data which may contain unencrypted sensitive data from $@. | main.rs:19:50:19:57 | password | password | | main.rs:28:33:28:35 | url | main.rs:26:50:26:57 | password | main.rs:28:33:28:35 | url | This 'url' operation transmits data which may contain unencrypted sensitive data from $@. | main.rs:26:50:26:57 | password | password | | main.rs:35:33:35:35 | url | main.rs:33:50:33:57 | password | main.rs:35:33:35:35 | url | This 'url' operation transmits data which may contain unencrypted sensitive data from $@. | main.rs:33:50:33:57 | password | password | +| main.rs:45:28:45:30 | url | main.rs:44:50:44:65 | account_password | main.rs:45:28:45:30 | url | This 'url' operation transmits data which may contain unencrypted sensitive data from $@. | main.rs:44:50:44:65 | account_password | account_password | edges | main.rs:6:9:6:11 | url | main.rs:7:28:7:30 | url | provenance | Sink:MaD:4 | | main.rs:6:23:6:57 | ...::format(...) | main.rs:6:23:6:57 | { ... } | provenance | | @@ -40,6 +41,12 @@ edges | main.rs:33:23:33:57 | MacroExpr | main.rs:33:23:33:57 | ...::format(...) | provenance | MaD:7 | | main.rs:33:23:33:57 | { ... } | main.rs:33:23:33:57 | ...::must_use(...) | provenance | MaD:8 | | main.rs:33:50:33:57 | password | main.rs:33:23:33:57 | MacroExpr | provenance | | +| main.rs:44:9:44:11 | url | main.rs:45:28:45:30 | url | provenance | Sink:MaD:4 | +| main.rs:44:23:44:65 | ...::format(...) | main.rs:44:23:44:65 | { ... } | provenance | | +| main.rs:44:23:44:65 | ...::must_use(...) | main.rs:44:9:44:11 | url | provenance | | +| main.rs:44:23:44:65 | MacroExpr | main.rs:44:23:44:65 | ...::format(...) | provenance | MaD:7 | +| main.rs:44:23:44:65 | { ... } | main.rs:44:23:44:65 | ...::must_use(...) | provenance | MaD:8 | +| main.rs:44:50:44:65 | account_password | main.rs:44:23:44:65 | MacroExpr | provenance | | models | 1 | Sink: ::post; Argument[0]; request-url | | 2 | Sink: ::request; Argument[1]; request-url | @@ -90,4 +97,11 @@ nodes | main.rs:33:23:33:57 | { ... } | semmle.label | { ... } | | main.rs:33:50:33:57 | password | semmle.label | password | | main.rs:35:33:35:35 | url | semmle.label | url | +| main.rs:44:9:44:11 | url | semmle.label | url | +| main.rs:44:23:44:65 | ...::format(...) | semmle.label | ...::format(...) | +| main.rs:44:23:44:65 | ...::must_use(...) | semmle.label | ...::must_use(...) | +| main.rs:44:23:44:65 | MacroExpr | semmle.label | MacroExpr | +| main.rs:44:23:44:65 | { ... } | semmle.label | { ... } | +| main.rs:44:50:44:65 | account_password | semmle.label | account_password | +| main.rs:45:28:45:30 | url | semmle.label | url | subpaths diff --git a/rust/ql/test/query-tests/security/CWE-311/main.rs b/rust/ql/test/query-tests/security/CWE-311/main.rs index 63d16a46a369..f1a1a083b5c1 100644 --- a/rust/ql/test/query-tests/security/CWE-311/main.rs +++ b/rust/ql/test/query-tests/security/CWE-311/main.rs @@ -35,10 +35,21 @@ fn request_put_with_password_in_url() { client.request(Method::PUT, url).body("body").send(); // $ Alert[rust/cleartext-transmission] } +fn get_with_account_identifiers_in_url() { + let user_uuid = "uuid"; + let url = format!("example.com?user={}", user_uuid); + reqwest::blocking::get(url).unwrap().text().unwrap(); + + let account_password = "Hunter12"; + let url = format!("example.com?password={}", account_password); // $ Source + reqwest::blocking::get(url).unwrap().text().unwrap(); // $ Alert[rust/cleartext-transmission] +} + fn main() { get_with_password_in_url(); get_with_password_in_constructed_url(); post_with_password_in_url(); request_blocking_put_with_password_in_url(); request_put_with_password_in_url(); + get_with_account_identifiers_in_url(); } 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 b87bd75ca140..bbf86e51f7bc 100644 --- a/rust/ql/test/query-tests/security/CWE-312/CleartextLogging.expected +++ b/rust/ql/test/query-tests/security/CWE-312/CleartextLogging.expected @@ -55,7 +55,9 @@ | test_logging.rs:245:20:245:65 | ... .as_bytes() | test_logging.rs:245:46:245:53 | password | test_logging.rs:245:20:245:65 | ... .as_bytes() | This operation writes $@ to a log file. | test_logging.rs:245:46:245:53 | password | password | | test_logging.rs:248:15:248:60 | ... .as_bytes() | test_logging.rs:248:41:248:48 | password | test_logging.rs:248:15:248:60 | ... .as_bytes() | This operation writes $@ to a log file. | test_logging.rs:248:41:248:48 | password | password | | test_logging.rs:251:15:251:60 | ... .as_bytes() | test_logging.rs:251:41:251:48 | password | test_logging.rs:251:15:251:60 | ... .as_bytes() | This operation writes $@ to a log file. | test_logging.rs:251:41:251:48 | password | password | -| test_logging.rs:290:11:290:31 | MacroExpr | test_logging.rs:289:17:289:39 | get_password_or_error(...) | test_logging.rs:290:11:290:31 | MacroExpr | This operation writes $@ to a log file. | test_logging.rs:289:17:289:39 | get_password_or_error(...) | get_password_or_error(...) | +| test_logging.rs:276:11:276:42 | MacroExpr | test_logging.rs:276:27:276:42 | account_password | test_logging.rs:276:11:276:42 | MacroExpr | This operation writes $@ to a log file. | test_logging.rs:276:27:276:42 | account_password | account_password | +| test_logging.rs:277:11:277:37 | MacroExpr | test_logging.rs:277:27:277:37 | session_key | test_logging.rs:277:11:277:37 | MacroExpr | This operation writes $@ to a log file. | test_logging.rs:277:27:277:37 | session_key | session_key | +| test_logging.rs:296:11:296:31 | MacroExpr | test_logging.rs:295:17:295:39 | get_password_or_error(...) | test_logging.rs:296:11:296:31 | MacroExpr | This operation writes $@ to a log file. | test_logging.rs:295:17:295:39 | get_password_or_error(...) | get_password_or_error(...) | edges | test_logging.rs:42:28:42:35 | password | test_logging.rs:42:12:42:35 | MacroExpr | provenance | Sink:MaD:11 | | test_logging.rs:43:28:43:35 | password | test_logging.rs:43:12:43:35 | MacroExpr | provenance | Sink:MaD:11 | @@ -226,8 +228,10 @@ edges | test_logging.rs:251:23:251:48 | MacroExpr | test_logging.rs:251:23:251:48 | ...::format(...) | provenance | MaD:20 | | test_logging.rs:251:23:251:48 | { ... } | test_logging.rs:251:23:251:48 | ...::must_use(...) | provenance | MaD:21 | | test_logging.rs:251:41:251:48 | password | test_logging.rs:251:23:251:48 | MacroExpr | provenance | | -| test_logging.rs:289:9:289:13 | value | test_logging.rs:290:11:290:31 | MacroExpr | provenance | Sink:MaD:11 | -| test_logging.rs:289:17:289:39 | get_password_or_error(...) | test_logging.rs:289:9:289:13 | value | provenance | | +| test_logging.rs:276:27:276:42 | account_password | test_logging.rs:276:11:276:42 | MacroExpr | provenance | Sink:MaD:11 | +| test_logging.rs:277:27:277:37 | session_key | test_logging.rs:277:11:277:37 | MacroExpr | provenance | Sink:MaD:11 | +| test_logging.rs:295:9:295:13 | value | test_logging.rs:296:11:296:31 | MacroExpr | provenance | Sink:MaD:11 | +| test_logging.rs:295:17:295:39 | get_password_or_error(...) | test_logging.rs:295:9:295:13 | value | provenance | | models | 1 | Sink: ::log_expect; Argument[0]; log-injection | | 2 | Sink: ::expect; Argument[0]; log-injection | @@ -465,7 +469,11 @@ nodes | test_logging.rs:251:23:251:48 | MacroExpr | semmle.label | MacroExpr | | test_logging.rs:251:23:251:48 | { ... } | semmle.label | { ... } | | test_logging.rs:251:41:251:48 | password | semmle.label | password | -| test_logging.rs:289:9:289:13 | value | semmle.label | value | -| test_logging.rs:289:17:289:39 | get_password_or_error(...) | semmle.label | get_password_or_error(...) | -| test_logging.rs:290:11:290:31 | MacroExpr | semmle.label | MacroExpr | +| test_logging.rs:276:11:276:42 | MacroExpr | semmle.label | MacroExpr | +| test_logging.rs:276:27:276:42 | account_password | semmle.label | account_password | +| test_logging.rs:277:11:277:37 | MacroExpr | semmle.label | MacroExpr | +| test_logging.rs:277:27:277:37 | session_key | semmle.label | session_key | +| test_logging.rs:295:9:295:13 | value | semmle.label | value | +| test_logging.rs:295:17:295:39 | get_password_or_error(...) | semmle.label | get_password_or_error(...) | +| test_logging.rs:296:11:296:31 | MacroExpr | semmle.label | MacroExpr | subpaths diff --git a/rust/ql/test/query-tests/security/CWE-312/CleartextStorageDatabase.expected b/rust/ql/test/query-tests/security/CWE-312/CleartextStorageDatabase.expected index 920ce2e00c27..c6a5e2735b75 100644 --- a/rust/ql/test/query-tests/security/CWE-312/CleartextStorageDatabase.expected +++ b/rust/ql/test/query-tests/security/CWE-312/CleartextStorageDatabase.expected @@ -4,9 +4,10 @@ | test_storage.rs:119:25:119:46 | insert_query2.as_str() | test_storage.rs:71:97:71:114 | get_phone_number(...) | test_storage.rs:119:25:119:46 | insert_query2.as_str() | This database operation may read or write unencrypted sensitive data from $@. | test_storage.rs:71:97:71:114 | get_phone_number(...) | get_phone_number(...) | | test_storage.rs:125:25:125:46 | insert_query2.as_str() | test_storage.rs:71:97:71:114 | get_phone_number(...) | test_storage.rs:125:25:125:46 | insert_query2.as_str() | This database operation may read or write unencrypted sensitive data from $@. | test_storage.rs:71:97:71:114 | get_phone_number(...) | get_phone_number(...) | | test_storage.rs:139:25:139:46 | insert_query2.as_str() | test_storage.rs:71:97:71:114 | get_phone_number(...) | test_storage.rs:139:25:139:46 | insert_query2.as_str() | This database operation may read or write unencrypted sensitive data from $@. | test_storage.rs:71:97:71:114 | get_phone_number(...) | get_phone_number(...) | -| test_storage.rs:194:24:194:40 | &insert_query_bad | test_storage.rs:189:100:189:117 | get_phone_number(...) | test_storage.rs:194:24:194:40 | &insert_query_bad | This database operation may read or write unencrypted sensitive data from $@. | test_storage.rs:189:100:189:117 | get_phone_number(...) | get_phone_number(...) | -| test_storage.rs:196:34:196:50 | &select_query_bad | test_storage.rs:190:86:190:103 | get_phone_number(...) | test_storage.rs:196:34:196:50 | &select_query_bad | This database operation may read or write unencrypted sensitive data from $@. | test_storage.rs:190:86:190:103 | get_phone_number(...) | get_phone_number(...) | -| test_storage.rs:204:39:204:55 | &select_query_bad | test_storage.rs:190:86:190:103 | get_phone_number(...) | test_storage.rs:204:39:204:55 | &select_query_bad | This database operation may read or write unencrypted sensitive data from $@. | test_storage.rs:190:86:190:103 | get_phone_number(...) | get_phone_number(...) | +| test_storage.rs:199:24:199:40 | &insert_query_bad | test_storage.rs:189:100:189:117 | get_phone_number(...) | test_storage.rs:199:24:199:40 | &insert_query_bad | This database operation may read or write unencrypted sensitive data from $@. | test_storage.rs:189:100:189:117 | get_phone_number(...) | get_phone_number(...) | +| test_storage.rs:201:24:201:41 | &insert_query_bad2 | test_storage.rs:195:105:195:120 | account_password | test_storage.rs:201:24:201:41 | &insert_query_bad2 | This database operation may read or write unencrypted sensitive data from $@. | test_storage.rs:195:105:195:120 | account_password | account_password | +| test_storage.rs:203:34:203:50 | &select_query_bad | test_storage.rs:190:86:190:103 | get_phone_number(...) | test_storage.rs:203:34:203:50 | &select_query_bad | This database operation may read or write unencrypted sensitive data from $@. | test_storage.rs:190:86:190:103 | get_phone_number(...) | get_phone_number(...) | +| test_storage.rs:211:39:211:55 | &select_query_bad | test_storage.rs:190:86:190:103 | get_phone_number(...) | test_storage.rs:211:39:211:55 | &select_query_bad | This database operation may read or write unencrypted sensitive data from $@. | test_storage.rs:190:86:190:103 | get_phone_number(...) | get_phone_number(...) | edges | test_storage.rs:71:9:71:21 | insert_query2 | test_storage.rs:100:25:100:37 | insert_query2 | provenance | | | test_storage.rs:71:9:71:21 | insert_query2 | test_storage.rs:115:27:115:39 | insert_query2 | provenance | | @@ -29,33 +30,41 @@ edges | test_storage.rs:125:25:125:46 | insert_query2.as_str() [&ref] | test_storage.rs:125:25:125:46 | insert_query2.as_str() | provenance | Sink:MaD:4 | | test_storage.rs:139:25:139:37 | insert_query2 | test_storage.rs:139:25:139:46 | insert_query2.as_str() [&ref] | provenance | MaD:8 | | test_storage.rs:139:25:139:46 | insert_query2.as_str() [&ref] | test_storage.rs:139:25:139:46 | insert_query2.as_str() | provenance | Sink:MaD:4 | -| test_storage.rs:189:9:189:24 | insert_query_bad | test_storage.rs:194:25:194:40 | insert_query_bad | provenance | | +| test_storage.rs:189:9:189:24 | insert_query_bad | test_storage.rs:199:25:199:40 | insert_query_bad | provenance | | | test_storage.rs:189:28:189:117 | ... + ... | test_storage.rs:189:28:189:124 | ... + ... | provenance | MaD:7 | | test_storage.rs:189:28:189:124 | ... + ... | test_storage.rs:189:9:189:24 | insert_query_bad | provenance | | | test_storage.rs:189:99:189:117 | &... | test_storage.rs:189:28:189:117 | ... + ... | provenance | MaD:6 | | test_storage.rs:189:99:189:117 | &... [&ref] | test_storage.rs:189:28:189:117 | ... + ... | provenance | MaD:6 | | test_storage.rs:189:100:189:117 | get_phone_number(...) | test_storage.rs:189:99:189:117 | &... | provenance | Config | | test_storage.rs:189:100:189:117 | get_phone_number(...) | test_storage.rs:189:99:189:117 | &... [&ref] | provenance | | -| test_storage.rs:190:9:190:24 | select_query_bad | test_storage.rs:196:35:196:50 | select_query_bad | provenance | | +| test_storage.rs:190:9:190:24 | select_query_bad | test_storage.rs:203:35:203:50 | select_query_bad | provenance | | | test_storage.rs:190:28:190:103 | ... + ... | test_storage.rs:190:28:190:109 | ... + ... | provenance | MaD:7 | | test_storage.rs:190:28:190:109 | ... + ... | test_storage.rs:190:9:190:24 | select_query_bad | provenance | | | test_storage.rs:190:85:190:103 | &... | test_storage.rs:190:28:190:103 | ... + ... | provenance | MaD:6 | | test_storage.rs:190:85:190:103 | &... [&ref] | test_storage.rs:190:28:190:103 | ... + ... | provenance | MaD:6 | | test_storage.rs:190:86:190:103 | get_phone_number(...) | test_storage.rs:190:85:190:103 | &... | provenance | Config | | test_storage.rs:190:86:190:103 | get_phone_number(...) | test_storage.rs:190:85:190:103 | &... [&ref] | provenance | | -| test_storage.rs:194:24:194:40 | &insert_query_bad | test_storage.rs:194:24:194:40 | &insert_query_bad | provenance | Sink:MaD:1 | -| test_storage.rs:194:24:194:40 | &insert_query_bad [&ref] | test_storage.rs:194:24:194:40 | &insert_query_bad | provenance | Sink:MaD:1 | -| test_storage.rs:194:25:194:40 | insert_query_bad | test_storage.rs:194:24:194:40 | &insert_query_bad | provenance | Config | -| test_storage.rs:194:25:194:40 | insert_query_bad | test_storage.rs:194:24:194:40 | &insert_query_bad [&ref] | provenance | | -| test_storage.rs:196:34:196:50 | &select_query_bad | test_storage.rs:196:34:196:50 | &select_query_bad | provenance | Sink:MaD:3 | -| test_storage.rs:196:34:196:50 | &select_query_bad [&ref] | test_storage.rs:196:34:196:50 | &select_query_bad | provenance | Sink:MaD:3 | -| test_storage.rs:196:35:196:50 | select_query_bad | test_storage.rs:196:34:196:50 | &select_query_bad | provenance | Config | -| test_storage.rs:196:35:196:50 | select_query_bad | test_storage.rs:196:34:196:50 | &select_query_bad [&ref] | provenance | | -| test_storage.rs:196:35:196:50 | select_query_bad | test_storage.rs:204:40:204:55 | select_query_bad | provenance | | -| test_storage.rs:204:39:204:55 | &select_query_bad | test_storage.rs:204:39:204:55 | &select_query_bad | provenance | Sink:MaD:2 | -| test_storage.rs:204:39:204:55 | &select_query_bad [&ref] | test_storage.rs:204:39:204:55 | &select_query_bad | provenance | Sink:MaD:2 | -| test_storage.rs:204:40:204:55 | select_query_bad | test_storage.rs:204:39:204:55 | &select_query_bad | provenance | Config | -| test_storage.rs:204:40:204:55 | select_query_bad | test_storage.rs:204:39:204:55 | &select_query_bad [&ref] | provenance | | +| test_storage.rs:195:9:195:25 | insert_query_bad2 | test_storage.rs:201:25:201:41 | insert_query_bad2 | provenance | | +| test_storage.rs:195:29:195:120 | ... + ... | test_storage.rs:195:29:195:127 | ... + ... | provenance | MaD:7 | +| test_storage.rs:195:29:195:127 | ... + ... | test_storage.rs:195:9:195:25 | insert_query_bad2 | provenance | | +| test_storage.rs:195:105:195:120 | account_password | test_storage.rs:195:29:195:120 | ... + ... | provenance | MaD:6 | +| test_storage.rs:199:24:199:40 | &insert_query_bad | test_storage.rs:199:24:199:40 | &insert_query_bad | provenance | Sink:MaD:1 | +| test_storage.rs:199:24:199:40 | &insert_query_bad [&ref] | test_storage.rs:199:24:199:40 | &insert_query_bad | provenance | Sink:MaD:1 | +| test_storage.rs:199:25:199:40 | insert_query_bad | test_storage.rs:199:24:199:40 | &insert_query_bad | provenance | Config | +| test_storage.rs:199:25:199:40 | insert_query_bad | test_storage.rs:199:24:199:40 | &insert_query_bad [&ref] | provenance | | +| test_storage.rs:201:24:201:41 | &insert_query_bad2 | test_storage.rs:201:24:201:41 | &insert_query_bad2 | provenance | Sink:MaD:1 | +| test_storage.rs:201:24:201:41 | &insert_query_bad2 [&ref] | test_storage.rs:201:24:201:41 | &insert_query_bad2 | provenance | Sink:MaD:1 | +| test_storage.rs:201:25:201:41 | insert_query_bad2 | test_storage.rs:201:24:201:41 | &insert_query_bad2 | provenance | Config | +| test_storage.rs:201:25:201:41 | insert_query_bad2 | test_storage.rs:201:24:201:41 | &insert_query_bad2 [&ref] | provenance | | +| test_storage.rs:203:34:203:50 | &select_query_bad | test_storage.rs:203:34:203:50 | &select_query_bad | provenance | Sink:MaD:3 | +| test_storage.rs:203:34:203:50 | &select_query_bad [&ref] | test_storage.rs:203:34:203:50 | &select_query_bad | provenance | Sink:MaD:3 | +| test_storage.rs:203:35:203:50 | select_query_bad | test_storage.rs:203:34:203:50 | &select_query_bad | provenance | Config | +| test_storage.rs:203:35:203:50 | select_query_bad | test_storage.rs:203:34:203:50 | &select_query_bad [&ref] | provenance | | +| test_storage.rs:203:35:203:50 | select_query_bad | test_storage.rs:211:40:211:55 | select_query_bad | provenance | | +| test_storage.rs:211:39:211:55 | &select_query_bad | test_storage.rs:211:39:211:55 | &select_query_bad | provenance | Sink:MaD:2 | +| test_storage.rs:211:39:211:55 | &select_query_bad [&ref] | test_storage.rs:211:39:211:55 | &select_query_bad | provenance | Sink:MaD:2 | +| test_storage.rs:211:40:211:55 | select_query_bad | test_storage.rs:211:39:211:55 | &select_query_bad | provenance | Config | +| test_storage.rs:211:40:211:55 | select_query_bad | test_storage.rs:211:39:211:55 | &select_query_bad [&ref] | provenance | | models | 1 | Sink: ::execute; Argument[0]; sql-injection | | 2 | Sink: ::prepare; Argument[0]; sql-injection | @@ -99,16 +108,24 @@ nodes | test_storage.rs:190:85:190:103 | &... | semmle.label | &... | | test_storage.rs:190:85:190:103 | &... [&ref] | semmle.label | &... [&ref] | | test_storage.rs:190:86:190:103 | get_phone_number(...) | semmle.label | get_phone_number(...) | -| test_storage.rs:194:24:194:40 | &insert_query_bad | semmle.label | &insert_query_bad | -| test_storage.rs:194:24:194:40 | &insert_query_bad | semmle.label | &insert_query_bad | -| test_storage.rs:194:24:194:40 | &insert_query_bad [&ref] | semmle.label | &insert_query_bad [&ref] | -| test_storage.rs:194:25:194:40 | insert_query_bad | semmle.label | insert_query_bad | -| test_storage.rs:196:34:196:50 | &select_query_bad | semmle.label | &select_query_bad | -| test_storage.rs:196:34:196:50 | &select_query_bad | semmle.label | &select_query_bad | -| test_storage.rs:196:34:196:50 | &select_query_bad [&ref] | semmle.label | &select_query_bad [&ref] | -| test_storage.rs:196:35:196:50 | select_query_bad | semmle.label | select_query_bad | -| test_storage.rs:204:39:204:55 | &select_query_bad | semmle.label | &select_query_bad | -| test_storage.rs:204:39:204:55 | &select_query_bad | semmle.label | &select_query_bad | -| test_storage.rs:204:39:204:55 | &select_query_bad [&ref] | semmle.label | &select_query_bad [&ref] | -| test_storage.rs:204:40:204:55 | select_query_bad | semmle.label | select_query_bad | +| test_storage.rs:195:9:195:25 | insert_query_bad2 | semmle.label | insert_query_bad2 | +| test_storage.rs:195:29:195:120 | ... + ... | semmle.label | ... + ... | +| test_storage.rs:195:29:195:127 | ... + ... | semmle.label | ... + ... | +| test_storage.rs:195:105:195:120 | account_password | semmle.label | account_password | +| test_storage.rs:199:24:199:40 | &insert_query_bad | semmle.label | &insert_query_bad | +| test_storage.rs:199:24:199:40 | &insert_query_bad | semmle.label | &insert_query_bad | +| test_storage.rs:199:24:199:40 | &insert_query_bad [&ref] | semmle.label | &insert_query_bad [&ref] | +| test_storage.rs:199:25:199:40 | insert_query_bad | semmle.label | insert_query_bad | +| test_storage.rs:201:24:201:41 | &insert_query_bad2 | semmle.label | &insert_query_bad2 | +| test_storage.rs:201:24:201:41 | &insert_query_bad2 | semmle.label | &insert_query_bad2 | +| test_storage.rs:201:24:201:41 | &insert_query_bad2 [&ref] | semmle.label | &insert_query_bad2 [&ref] | +| test_storage.rs:201:25:201:41 | insert_query_bad2 | semmle.label | insert_query_bad2 | +| test_storage.rs:203:34:203:50 | &select_query_bad | semmle.label | &select_query_bad | +| test_storage.rs:203:34:203:50 | &select_query_bad | semmle.label | &select_query_bad | +| test_storage.rs:203:34:203:50 | &select_query_bad [&ref] | semmle.label | &select_query_bad [&ref] | +| test_storage.rs:203:35:203:50 | select_query_bad | semmle.label | select_query_bad | +| test_storage.rs:211:39:211:55 | &select_query_bad | semmle.label | &select_query_bad | +| test_storage.rs:211:39:211:55 | &select_query_bad | semmle.label | &select_query_bad | +| test_storage.rs:211:39:211:55 | &select_query_bad [&ref] | semmle.label | &select_query_bad [&ref] | +| test_storage.rs:211:40:211:55 | select_query_bad | semmle.label | select_query_bad | subpaths 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 50f0bd5ef7bb..f62aec8a1cc0 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 @@ -271,6 +271,12 @@ fn test_collections(harmless: String) { password_queue.make_contiguous(); } +fn test_account_identifiers(user_id: i32, user_uuid: String, account_password: String, session_key: String) { + info!("message = {} {}", user_id, user_uuid); + info!("message = {}", account_password); // $ Alert[rust/cleartext-logging] + info!("message = {}", session_key); // $ Alert[rust/cleartext-logging] +} + fn get_password_or_error() -> Result { Ok("123456".to_string()) } @@ -305,5 +311,6 @@ fn main() { ); test_std("123456".to_string(), 0, None); test_collections("harmless".to_string()); + test_account_identifiers(123, "uuid".to_string(), "123456".to_string(), "key".to_string()); _ = test_try_operator(); } diff --git a/rust/ql/test/query-tests/security/CWE-312/test_storage.rs b/rust/ql/test/query-tests/security/CWE-312/test_storage.rs index 1d23a22bd6ea..3aef715b7186 100644 --- a/rust/ql/test/query-tests/security/CWE-312/test_storage.rs +++ b/rust/ql/test/query-tests/security/CWE-312/test_storage.rs @@ -188,10 +188,17 @@ async fn test_storage_rusqlite_sql_command(url: &str) -> Result<(), Box = row; diff --git a/shared/concepts/change-notes/2026-11-02-session-key-secret.md b/shared/concepts/change-notes/2026-11-02-session-key-secret.md new file mode 100644 index 000000000000..a248a49ba3cd --- /dev/null +++ b/shared/concepts/change-notes/2026-11-02-session-key-secret.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The sensitive data heuristics now classify names like `session_key` and `account_key` as secrets rather than account identifiers. diff --git a/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll b/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll index b2bda909e3ba..a4f33f246554 100644 --- a/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll +++ b/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll @@ -57,7 +57,8 @@ module HeuristicNames { * or trusted data. */ string maybeSecret() { - result = "(?is).*((?