From b6155ff44352a8d5c687c1fc63c8501041db20c0 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 1 May 2026 18:06:38 +0100 Subject: [PATCH 01/16] Swift: Test spacing. --- .../CWE-328/WeakPasswordHashing.expected | 68 +++++++++---------- .../CWE-328/WeakSensitiveDataHashing.expected | 60 ++++++++-------- .../Security/CWE-328/testCryptoKit.swift | 6 ++ 3 files changed, 70 insertions(+), 64 deletions(-) diff --git a/swift/ql/test/query-tests/Security/CWE-328/WeakPasswordHashing.expected b/swift/ql/test/query-tests/Security/CWE-328/WeakPasswordHashing.expected index 46f3d211ccd7..dfb0f794d96c 100644 --- a/swift/ql/test/query-tests/Security/CWE-328/WeakPasswordHashing.expected +++ b/swift/ql/test/query-tests/Security/CWE-328/WeakPasswordHashing.expected @@ -1,26 +1,26 @@ edges -| testCryptoKit.swift:193:38:193:38 | passwordString | testCryptoKit.swift:193:38:193:53 | .utf8 | provenance | | -| testCryptoKit.swift:193:38:193:53 | .utf8 | testCryptoKit.swift:193:33:193:57 | call to Data.init(_:) | provenance | | +| testCryptoKit.swift:199:38:199:38 | passwordString | testCryptoKit.swift:199:38:199:53 | .utf8 | provenance | | +| testCryptoKit.swift:199:38:199:53 | .utf8 | testCryptoKit.swift:199:33:199:57 | call to Data.init(_:) | provenance | | nodes | testCryptoKit.swift:65:47:65:47 | passwd | semmle.label | passwd | -| testCryptoKit.swift:71:44:71:44 | passwd | semmle.label | passwd | -| testCryptoKit.swift:77:37:77:37 | passwd | semmle.label | passwd | +| testCryptoKit.swift:77:44:77:44 | passwd | semmle.label | passwd | | testCryptoKit.swift:83:37:83:37 | passwd | semmle.label | passwd | | testCryptoKit.swift:89:37:89:37 | passwd | semmle.label | passwd | -| testCryptoKit.swift:98:23:98:23 | passwd | semmle.label | passwd | -| testCryptoKit.swift:107:23:107:23 | passwd | semmle.label | passwd | -| testCryptoKit.swift:116:23:116:23 | passwd | semmle.label | passwd | -| testCryptoKit.swift:125:23:125:23 | passwd | semmle.label | passwd | -| testCryptoKit.swift:134:23:134:23 | passwd | semmle.label | passwd | -| testCryptoKit.swift:143:32:143:32 | passwd | semmle.label | passwd | -| testCryptoKit.swift:152:32:152:32 | passwd | semmle.label | passwd | -| testCryptoKit.swift:161:32:161:32 | passwd | semmle.label | passwd | -| testCryptoKit.swift:170:32:170:32 | passwd | semmle.label | passwd | -| testCryptoKit.swift:179:32:179:32 | passwd | semmle.label | passwd | -| testCryptoKit.swift:189:49:189:49 | passwordData | semmle.label | passwordData | -| testCryptoKit.swift:193:33:193:57 | call to Data.init(_:) | semmle.label | call to Data.init(_:) | -| testCryptoKit.swift:193:38:193:38 | passwordString | semmle.label | passwordString | -| testCryptoKit.swift:193:38:193:53 | .utf8 | semmle.label | .utf8 | +| testCryptoKit.swift:95:37:95:37 | passwd | semmle.label | passwd | +| testCryptoKit.swift:104:23:104:23 | passwd | semmle.label | passwd | +| testCryptoKit.swift:113:23:113:23 | passwd | semmle.label | passwd | +| testCryptoKit.swift:122:23:122:23 | passwd | semmle.label | passwd | +| testCryptoKit.swift:131:23:131:23 | passwd | semmle.label | passwd | +| testCryptoKit.swift:140:23:140:23 | passwd | semmle.label | passwd | +| testCryptoKit.swift:149:32:149:32 | passwd | semmle.label | passwd | +| testCryptoKit.swift:158:32:158:32 | passwd | semmle.label | passwd | +| testCryptoKit.swift:167:32:167:32 | passwd | semmle.label | passwd | +| testCryptoKit.swift:176:32:176:32 | passwd | semmle.label | passwd | +| testCryptoKit.swift:185:32:185:32 | passwd | semmle.label | passwd | +| testCryptoKit.swift:195:49:195:49 | passwordData | semmle.label | passwordData | +| testCryptoKit.swift:199:33:199:57 | call to Data.init(_:) | semmle.label | call to Data.init(_:) | +| testCryptoKit.swift:199:38:199:38 | passwordString | semmle.label | passwordString | +| testCryptoKit.swift:199:38:199:53 | .utf8 | semmle.label | .utf8 | | testCryptoSwift.swift:154:30:154:30 | passwdArray | semmle.label | passwdArray | | testCryptoSwift.swift:157:31:157:31 | passwdArray | semmle.label | passwdArray | | testCryptoSwift.swift:160:47:160:47 | passwdArray | semmle.label | passwdArray | @@ -48,22 +48,22 @@ nodes subpaths #select | testCryptoKit.swift:65:47:65:47 | passwd | testCryptoKit.swift:65:47:65:47 | passwd | testCryptoKit.swift:65:47:65:47 | passwd | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:65:47:65:47 | passwd | password (passwd) | -| testCryptoKit.swift:71:44:71:44 | passwd | testCryptoKit.swift:71:44:71:44 | passwd | testCryptoKit.swift:71:44:71:44 | passwd | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:71:44:71:44 | passwd | password (passwd) | -| testCryptoKit.swift:77:37:77:37 | passwd | testCryptoKit.swift:77:37:77:37 | passwd | testCryptoKit.swift:77:37:77:37 | passwd | Insecure hashing algorithm (SHA256) depends on $@. | testCryptoKit.swift:77:37:77:37 | passwd | password (passwd) | -| testCryptoKit.swift:83:37:83:37 | passwd | testCryptoKit.swift:83:37:83:37 | passwd | testCryptoKit.swift:83:37:83:37 | passwd | Insecure hashing algorithm (SHA384) depends on $@. | testCryptoKit.swift:83:37:83:37 | passwd | password (passwd) | -| testCryptoKit.swift:89:37:89:37 | passwd | testCryptoKit.swift:89:37:89:37 | passwd | testCryptoKit.swift:89:37:89:37 | passwd | Insecure hashing algorithm (SHA512) depends on $@. | testCryptoKit.swift:89:37:89:37 | passwd | password (passwd) | -| testCryptoKit.swift:98:23:98:23 | passwd | testCryptoKit.swift:98:23:98:23 | passwd | testCryptoKit.swift:98:23:98:23 | passwd | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:98:23:98:23 | passwd | password (passwd) | -| testCryptoKit.swift:107:23:107:23 | passwd | testCryptoKit.swift:107:23:107:23 | passwd | testCryptoKit.swift:107:23:107:23 | passwd | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:107:23:107:23 | passwd | password (passwd) | -| testCryptoKit.swift:116:23:116:23 | passwd | testCryptoKit.swift:116:23:116:23 | passwd | testCryptoKit.swift:116:23:116:23 | passwd | Insecure hashing algorithm (SHA256) depends on $@. | testCryptoKit.swift:116:23:116:23 | passwd | password (passwd) | -| testCryptoKit.swift:125:23:125:23 | passwd | testCryptoKit.swift:125:23:125:23 | passwd | testCryptoKit.swift:125:23:125:23 | passwd | Insecure hashing algorithm (SHA384) depends on $@. | testCryptoKit.swift:125:23:125:23 | passwd | password (passwd) | -| testCryptoKit.swift:134:23:134:23 | passwd | testCryptoKit.swift:134:23:134:23 | passwd | testCryptoKit.swift:134:23:134:23 | passwd | Insecure hashing algorithm (SHA512) depends on $@. | testCryptoKit.swift:134:23:134:23 | passwd | password (passwd) | -| testCryptoKit.swift:143:32:143:32 | passwd | testCryptoKit.swift:143:32:143:32 | passwd | testCryptoKit.swift:143:32:143:32 | passwd | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:143:32:143:32 | passwd | password (passwd) | -| testCryptoKit.swift:152:32:152:32 | passwd | testCryptoKit.swift:152:32:152:32 | passwd | testCryptoKit.swift:152:32:152:32 | passwd | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:152:32:152:32 | passwd | password (passwd) | -| testCryptoKit.swift:161:32:161:32 | passwd | testCryptoKit.swift:161:32:161:32 | passwd | testCryptoKit.swift:161:32:161:32 | passwd | Insecure hashing algorithm (SHA256) depends on $@. | testCryptoKit.swift:161:32:161:32 | passwd | password (passwd) | -| testCryptoKit.swift:170:32:170:32 | passwd | testCryptoKit.swift:170:32:170:32 | passwd | testCryptoKit.swift:170:32:170:32 | passwd | Insecure hashing algorithm (SHA384) depends on $@. | testCryptoKit.swift:170:32:170:32 | passwd | password (passwd) | -| testCryptoKit.swift:179:32:179:32 | passwd | testCryptoKit.swift:179:32:179:32 | passwd | testCryptoKit.swift:179:32:179:32 | passwd | Insecure hashing algorithm (SHA512) depends on $@. | testCryptoKit.swift:179:32:179:32 | passwd | password (passwd) | -| testCryptoKit.swift:189:49:189:49 | passwordData | testCryptoKit.swift:189:49:189:49 | passwordData | testCryptoKit.swift:189:49:189:49 | passwordData | Insecure hashing algorithm (SHA512) depends on $@. | testCryptoKit.swift:189:49:189:49 | passwordData | password (passwordData) | -| testCryptoKit.swift:193:33:193:57 | call to Data.init(_:) | testCryptoKit.swift:193:38:193:38 | passwordString | testCryptoKit.swift:193:33:193:57 | call to Data.init(_:) | Insecure hashing algorithm (SHA512) depends on $@. | testCryptoKit.swift:193:38:193:38 | passwordString | password (passwordString) | +| testCryptoKit.swift:77:44:77:44 | passwd | testCryptoKit.swift:77:44:77:44 | passwd | testCryptoKit.swift:77:44:77:44 | passwd | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:77:44:77:44 | passwd | password (passwd) | +| testCryptoKit.swift:83:37:83:37 | passwd | testCryptoKit.swift:83:37:83:37 | passwd | testCryptoKit.swift:83:37:83:37 | passwd | Insecure hashing algorithm (SHA256) depends on $@. | testCryptoKit.swift:83:37:83:37 | passwd | password (passwd) | +| testCryptoKit.swift:89:37:89:37 | passwd | testCryptoKit.swift:89:37:89:37 | passwd | testCryptoKit.swift:89:37:89:37 | passwd | Insecure hashing algorithm (SHA384) depends on $@. | testCryptoKit.swift:89:37:89:37 | passwd | password (passwd) | +| testCryptoKit.swift:95:37:95:37 | passwd | testCryptoKit.swift:95:37:95:37 | passwd | testCryptoKit.swift:95:37:95:37 | passwd | Insecure hashing algorithm (SHA512) depends on $@. | testCryptoKit.swift:95:37:95:37 | passwd | password (passwd) | +| testCryptoKit.swift:104:23:104:23 | passwd | testCryptoKit.swift:104:23:104:23 | passwd | testCryptoKit.swift:104:23:104:23 | passwd | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:104:23:104:23 | passwd | password (passwd) | +| testCryptoKit.swift:113:23:113:23 | passwd | testCryptoKit.swift:113:23:113:23 | passwd | testCryptoKit.swift:113:23:113:23 | passwd | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:113:23:113:23 | passwd | password (passwd) | +| testCryptoKit.swift:122:23:122:23 | passwd | testCryptoKit.swift:122:23:122:23 | passwd | testCryptoKit.swift:122:23:122:23 | passwd | Insecure hashing algorithm (SHA256) depends on $@. | testCryptoKit.swift:122:23:122:23 | passwd | password (passwd) | +| testCryptoKit.swift:131:23:131:23 | passwd | testCryptoKit.swift:131:23:131:23 | passwd | testCryptoKit.swift:131:23:131:23 | passwd | Insecure hashing algorithm (SHA384) depends on $@. | testCryptoKit.swift:131:23:131:23 | passwd | password (passwd) | +| testCryptoKit.swift:140:23:140:23 | passwd | testCryptoKit.swift:140:23:140:23 | passwd | testCryptoKit.swift:140:23:140:23 | passwd | Insecure hashing algorithm (SHA512) depends on $@. | testCryptoKit.swift:140:23:140:23 | passwd | password (passwd) | +| testCryptoKit.swift:149:32:149:32 | passwd | testCryptoKit.swift:149:32:149:32 | passwd | testCryptoKit.swift:149:32:149:32 | passwd | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:149:32:149:32 | passwd | password (passwd) | +| testCryptoKit.swift:158:32:158:32 | passwd | testCryptoKit.swift:158:32:158:32 | passwd | testCryptoKit.swift:158:32:158:32 | passwd | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:158:32:158:32 | passwd | password (passwd) | +| testCryptoKit.swift:167:32:167:32 | passwd | testCryptoKit.swift:167:32:167:32 | passwd | testCryptoKit.swift:167:32:167:32 | passwd | Insecure hashing algorithm (SHA256) depends on $@. | testCryptoKit.swift:167:32:167:32 | passwd | password (passwd) | +| testCryptoKit.swift:176:32:176:32 | passwd | testCryptoKit.swift:176:32:176:32 | passwd | testCryptoKit.swift:176:32:176:32 | passwd | Insecure hashing algorithm (SHA384) depends on $@. | testCryptoKit.swift:176:32:176:32 | passwd | password (passwd) | +| testCryptoKit.swift:185:32:185:32 | passwd | testCryptoKit.swift:185:32:185:32 | passwd | testCryptoKit.swift:185:32:185:32 | passwd | Insecure hashing algorithm (SHA512) depends on $@. | testCryptoKit.swift:185:32:185:32 | passwd | password (passwd) | +| testCryptoKit.swift:195:49:195:49 | passwordData | testCryptoKit.swift:195:49:195:49 | passwordData | testCryptoKit.swift:195:49:195:49 | passwordData | Insecure hashing algorithm (SHA512) depends on $@. | testCryptoKit.swift:195:49:195:49 | passwordData | password (passwordData) | +| testCryptoKit.swift:199:33:199:57 | call to Data.init(_:) | testCryptoKit.swift:199:38:199:38 | passwordString | testCryptoKit.swift:199:33:199:57 | call to Data.init(_:) | Insecure hashing algorithm (SHA512) depends on $@. | testCryptoKit.swift:199:38:199:38 | passwordString | password (passwordString) | | testCryptoSwift.swift:154:30:154:30 | passwdArray | testCryptoSwift.swift:154:30:154:30 | passwdArray | testCryptoSwift.swift:154:30:154:30 | passwdArray | Insecure hashing algorithm (MD5) depends on $@. | testCryptoSwift.swift:154:30:154:30 | passwdArray | password (passwdArray) | | testCryptoSwift.swift:157:31:157:31 | passwdArray | testCryptoSwift.swift:157:31:157:31 | passwdArray | testCryptoSwift.swift:157:31:157:31 | passwdArray | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoSwift.swift:157:31:157:31 | passwdArray | password (passwdArray) | | testCryptoSwift.swift:160:47:160:47 | passwdArray | testCryptoSwift.swift:160:47:160:47 | passwdArray | testCryptoSwift.swift:160:47:160:47 | passwdArray | Insecure hashing algorithm (SHA2) depends on $@. | testCryptoSwift.swift:160:47:160:47 | passwdArray | password (passwdArray) | diff --git a/swift/ql/test/query-tests/Security/CWE-328/WeakSensitiveDataHashing.expected b/swift/ql/test/query-tests/Security/CWE-328/WeakSensitiveDataHashing.expected index 2cd31692f8d6..f65f4798debd 100644 --- a/swift/ql/test/query-tests/Security/CWE-328/WeakSensitiveDataHashing.expected +++ b/swift/ql/test/query-tests/Security/CWE-328/WeakSensitiveDataHashing.expected @@ -3,21 +3,21 @@ nodes | testCryptoKit.swift:66:43:66:43 | cert | semmle.label | cert | | testCryptoKit.swift:68:43:68:43 | account_no | semmle.label | account_no | | testCryptoKit.swift:69:43:69:43 | credit_card_no | semmle.label | credit_card_no | -| testCryptoKit.swift:72:44:72:44 | cert | semmle.label | cert | -| testCryptoKit.swift:74:44:74:44 | account_no | semmle.label | account_no | -| testCryptoKit.swift:75:44:75:44 | credit_card_no | semmle.label | credit_card_no | -| testCryptoKit.swift:99:23:99:23 | cert | semmle.label | cert | -| testCryptoKit.swift:101:23:101:23 | account_no | semmle.label | account_no | -| testCryptoKit.swift:102:23:102:23 | credit_card_no | semmle.label | credit_card_no | -| testCryptoKit.swift:108:23:108:23 | cert | semmle.label | cert | -| testCryptoKit.swift:110:23:110:23 | account_no | semmle.label | account_no | -| testCryptoKit.swift:111:23:111:23 | credit_card_no | semmle.label | credit_card_no | -| testCryptoKit.swift:144:32:144:32 | cert | semmle.label | cert | -| testCryptoKit.swift:146:32:146:32 | account_no | semmle.label | account_no | -| testCryptoKit.swift:147:32:147:32 | credit_card_no | semmle.label | credit_card_no | -| testCryptoKit.swift:153:32:153:32 | cert | semmle.label | cert | -| testCryptoKit.swift:155:32:155:32 | account_no | semmle.label | account_no | -| testCryptoKit.swift:156:32:156:32 | credit_card_no | semmle.label | credit_card_no | +| testCryptoKit.swift:78:44:78:44 | cert | semmle.label | cert | +| testCryptoKit.swift:80:44:80:44 | account_no | semmle.label | account_no | +| testCryptoKit.swift:81:44:81:44 | credit_card_no | semmle.label | credit_card_no | +| testCryptoKit.swift:105:23:105:23 | cert | semmle.label | cert | +| testCryptoKit.swift:107:23:107:23 | account_no | semmle.label | account_no | +| testCryptoKit.swift:108:23:108:23 | credit_card_no | semmle.label | credit_card_no | +| testCryptoKit.swift:114:23:114:23 | cert | semmle.label | cert | +| testCryptoKit.swift:116:23:116:23 | account_no | semmle.label | account_no | +| testCryptoKit.swift:117:23:117:23 | credit_card_no | semmle.label | credit_card_no | +| testCryptoKit.swift:150:32:150:32 | cert | semmle.label | cert | +| testCryptoKit.swift:152:32:152:32 | account_no | semmle.label | account_no | +| testCryptoKit.swift:153:32:153:32 | credit_card_no | semmle.label | credit_card_no | +| testCryptoKit.swift:159:32:159:32 | cert | semmle.label | cert | +| testCryptoKit.swift:161:32:161:32 | account_no | semmle.label | account_no | +| testCryptoKit.swift:162:32:162:32 | credit_card_no | semmle.label | credit_card_no | | testCryptoSwift.swift:153:30:153:30 | phoneNumberArray | semmle.label | phoneNumberArray | | testCryptoSwift.swift:156:31:156:31 | phoneNumberArray | semmle.label | phoneNumberArray | | testCryptoSwift.swift:166:20:166:20 | phoneNumberArray | semmle.label | phoneNumberArray | @@ -33,21 +33,21 @@ subpaths | testCryptoKit.swift:66:43:66:43 | cert | testCryptoKit.swift:66:43:66:43 | cert | testCryptoKit.swift:66:43:66:43 | cert | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:66:43:66:43 | cert | sensitive data (credential cert) | | testCryptoKit.swift:68:43:68:43 | account_no | testCryptoKit.swift:68:43:68:43 | account_no | testCryptoKit.swift:68:43:68:43 | account_no | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:68:43:68:43 | account_no | sensitive data (private information account_no) | | testCryptoKit.swift:69:43:69:43 | credit_card_no | testCryptoKit.swift:69:43:69:43 | credit_card_no | testCryptoKit.swift:69:43:69:43 | credit_card_no | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:69:43:69:43 | credit_card_no | sensitive data (private information credit_card_no) | -| testCryptoKit.swift:72:44:72:44 | cert | testCryptoKit.swift:72:44:72:44 | cert | testCryptoKit.swift:72:44:72:44 | cert | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:72:44:72:44 | cert | sensitive data (credential cert) | -| testCryptoKit.swift:74:44:74:44 | account_no | testCryptoKit.swift:74:44:74:44 | account_no | testCryptoKit.swift:74:44:74:44 | account_no | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:74:44:74:44 | account_no | sensitive data (private information account_no) | -| testCryptoKit.swift:75:44:75:44 | credit_card_no | testCryptoKit.swift:75:44:75:44 | credit_card_no | testCryptoKit.swift:75:44:75:44 | credit_card_no | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:75:44:75:44 | credit_card_no | sensitive data (private information credit_card_no) | -| testCryptoKit.swift:99:23:99:23 | cert | testCryptoKit.swift:99:23:99:23 | cert | testCryptoKit.swift:99:23:99:23 | cert | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:99:23:99:23 | cert | sensitive data (credential cert) | -| testCryptoKit.swift:101:23:101:23 | account_no | testCryptoKit.swift:101:23:101:23 | account_no | testCryptoKit.swift:101:23:101:23 | account_no | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:101:23:101:23 | account_no | sensitive data (private information account_no) | -| testCryptoKit.swift:102:23:102:23 | credit_card_no | testCryptoKit.swift:102:23:102:23 | credit_card_no | testCryptoKit.swift:102:23:102:23 | credit_card_no | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:102:23:102:23 | credit_card_no | sensitive data (private information credit_card_no) | -| testCryptoKit.swift:108:23:108:23 | cert | testCryptoKit.swift:108:23:108:23 | cert | testCryptoKit.swift:108:23:108:23 | cert | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:108:23:108:23 | cert | sensitive data (credential cert) | -| testCryptoKit.swift:110:23:110:23 | account_no | testCryptoKit.swift:110:23:110:23 | account_no | testCryptoKit.swift:110:23:110:23 | account_no | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:110:23:110:23 | account_no | sensitive data (private information account_no) | -| testCryptoKit.swift:111:23:111:23 | credit_card_no | testCryptoKit.swift:111:23:111:23 | credit_card_no | testCryptoKit.swift:111:23:111:23 | credit_card_no | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:111:23:111:23 | credit_card_no | sensitive data (private information credit_card_no) | -| testCryptoKit.swift:144:32:144:32 | cert | testCryptoKit.swift:144:32:144:32 | cert | testCryptoKit.swift:144:32:144:32 | cert | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:144:32:144:32 | cert | sensitive data (credential cert) | -| testCryptoKit.swift:146:32:146:32 | account_no | testCryptoKit.swift:146:32:146:32 | account_no | testCryptoKit.swift:146:32:146:32 | account_no | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:146:32:146:32 | account_no | sensitive data (private information account_no) | -| testCryptoKit.swift:147:32:147:32 | credit_card_no | testCryptoKit.swift:147:32:147:32 | credit_card_no | testCryptoKit.swift:147:32:147:32 | credit_card_no | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:147:32:147:32 | credit_card_no | sensitive data (private information credit_card_no) | -| testCryptoKit.swift:153:32:153:32 | cert | testCryptoKit.swift:153:32:153:32 | cert | testCryptoKit.swift:153:32:153:32 | cert | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:153:32:153:32 | cert | sensitive data (credential cert) | -| testCryptoKit.swift:155:32:155:32 | account_no | testCryptoKit.swift:155:32:155:32 | account_no | testCryptoKit.swift:155:32:155:32 | account_no | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:155:32:155:32 | account_no | sensitive data (private information account_no) | -| testCryptoKit.swift:156:32:156:32 | credit_card_no | testCryptoKit.swift:156:32:156:32 | credit_card_no | testCryptoKit.swift:156:32:156:32 | credit_card_no | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:156:32:156:32 | credit_card_no | sensitive data (private information credit_card_no) | +| testCryptoKit.swift:78:44:78:44 | cert | testCryptoKit.swift:78:44:78:44 | cert | testCryptoKit.swift:78:44:78:44 | cert | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:78:44:78:44 | cert | sensitive data (credential cert) | +| testCryptoKit.swift:80:44:80:44 | account_no | testCryptoKit.swift:80:44:80:44 | account_no | testCryptoKit.swift:80:44:80:44 | account_no | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:80:44:80:44 | account_no | sensitive data (private information account_no) | +| testCryptoKit.swift:81:44:81:44 | credit_card_no | testCryptoKit.swift:81:44:81:44 | credit_card_no | testCryptoKit.swift:81:44:81:44 | credit_card_no | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:81:44:81:44 | credit_card_no | sensitive data (private information credit_card_no) | +| testCryptoKit.swift:105:23:105:23 | cert | testCryptoKit.swift:105:23:105:23 | cert | testCryptoKit.swift:105:23:105:23 | cert | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:105:23:105:23 | cert | sensitive data (credential cert) | +| testCryptoKit.swift:107:23:107:23 | account_no | testCryptoKit.swift:107:23:107:23 | account_no | testCryptoKit.swift:107:23:107:23 | account_no | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:107:23:107:23 | account_no | sensitive data (private information account_no) | +| testCryptoKit.swift:108:23:108:23 | credit_card_no | testCryptoKit.swift:108:23:108:23 | credit_card_no | testCryptoKit.swift:108:23:108:23 | credit_card_no | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:108:23:108:23 | credit_card_no | sensitive data (private information credit_card_no) | +| testCryptoKit.swift:114:23:114:23 | cert | testCryptoKit.swift:114:23:114:23 | cert | testCryptoKit.swift:114:23:114:23 | cert | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:114:23:114:23 | cert | sensitive data (credential cert) | +| testCryptoKit.swift:116:23:116:23 | account_no | testCryptoKit.swift:116:23:116:23 | account_no | testCryptoKit.swift:116:23:116:23 | account_no | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:116:23:116:23 | account_no | sensitive data (private information account_no) | +| testCryptoKit.swift:117:23:117:23 | credit_card_no | testCryptoKit.swift:117:23:117:23 | credit_card_no | testCryptoKit.swift:117:23:117:23 | credit_card_no | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:117:23:117:23 | credit_card_no | sensitive data (private information credit_card_no) | +| testCryptoKit.swift:150:32:150:32 | cert | testCryptoKit.swift:150:32:150:32 | cert | testCryptoKit.swift:150:32:150:32 | cert | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:150:32:150:32 | cert | sensitive data (credential cert) | +| testCryptoKit.swift:152:32:152:32 | account_no | testCryptoKit.swift:152:32:152:32 | account_no | testCryptoKit.swift:152:32:152:32 | account_no | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:152:32:152:32 | account_no | sensitive data (private information account_no) | +| testCryptoKit.swift:153:32:153:32 | credit_card_no | testCryptoKit.swift:153:32:153:32 | credit_card_no | testCryptoKit.swift:153:32:153:32 | credit_card_no | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:153:32:153:32 | credit_card_no | sensitive data (private information credit_card_no) | +| testCryptoKit.swift:159:32:159:32 | cert | testCryptoKit.swift:159:32:159:32 | cert | testCryptoKit.swift:159:32:159:32 | cert | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:159:32:159:32 | cert | sensitive data (credential cert) | +| testCryptoKit.swift:161:32:161:32 | account_no | testCryptoKit.swift:161:32:161:32 | account_no | testCryptoKit.swift:161:32:161:32 | account_no | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:161:32:161:32 | account_no | sensitive data (private information account_no) | +| testCryptoKit.swift:162:32:162:32 | credit_card_no | testCryptoKit.swift:162:32:162:32 | credit_card_no | testCryptoKit.swift:162:32:162:32 | credit_card_no | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:162:32:162:32 | credit_card_no | sensitive data (private information credit_card_no) | | testCryptoSwift.swift:153:30:153:30 | phoneNumberArray | testCryptoSwift.swift:153:30:153:30 | phoneNumberArray | testCryptoSwift.swift:153:30:153:30 | phoneNumberArray | Insecure hashing algorithm (MD5) depends on $@. | testCryptoSwift.swift:153:30:153:30 | phoneNumberArray | sensitive data (private information phoneNumberArray) | | testCryptoSwift.swift:156:31:156:31 | phoneNumberArray | testCryptoSwift.swift:156:31:156:31 | phoneNumberArray | testCryptoSwift.swift:156:31:156:31 | phoneNumberArray | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoSwift.swift:156:31:156:31 | phoneNumberArray | sensitive data (private information phoneNumberArray) | | testCryptoSwift.swift:166:20:166:20 | phoneNumberArray | testCryptoSwift.swift:166:20:166:20 | phoneNumberArray | testCryptoSwift.swift:166:20:166:20 | phoneNumberArray | Insecure hashing algorithm (MD5) depends on $@. | testCryptoSwift.swift:166:20:166:20 | phoneNumberArray | sensitive data (private information phoneNumberArray) | diff --git a/swift/ql/test/query-tests/Security/CWE-328/testCryptoKit.swift b/swift/ql/test/query-tests/Security/CWE-328/testCryptoKit.swift index dd37c6238c0b..804815260581 100644 --- a/swift/ql/test/query-tests/Security/CWE-328/testCryptoKit.swift +++ b/swift/ql/test/query-tests/Security/CWE-328/testCryptoKit.swift @@ -68,6 +68,12 @@ func testHashMethods(passwd : UnsafeRawBufferPointer, cert: String, encrypted_pa hash = Crypto.Insecure.MD5.hash(data: account_no) // BAD hash = Crypto.Insecure.MD5.hash(data: credit_card_no) // BAD + + + + + + hash = Crypto.Insecure.SHA1.hash(data: passwd) // BAD hash = Crypto.Insecure.SHA1.hash(data: cert) // BAD hash = Crypto.Insecure.SHA1.hash(data: encrypted_passwd) // GOOD (not sensitive) From dc863c39a9ece4feef77b1f782f76b94316ccac1 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 1 May 2026 18:12:06 +0100 Subject: [PATCH 02/16] Swift: Add test cases for an alternative pattern of calls to Insecure.MD5.hash. --- .../Security/CWE-328/WeakPasswordHashing.expected | 2 ++ .../Security/CWE-328/WeakSensitiveDataHashing.expected | 6 ++++++ .../query-tests/Security/CWE-328/testCryptoKit.swift | 10 +++++----- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/swift/ql/test/query-tests/Security/CWE-328/WeakPasswordHashing.expected b/swift/ql/test/query-tests/Security/CWE-328/WeakPasswordHashing.expected index dfb0f794d96c..f8db62cedbc6 100644 --- a/swift/ql/test/query-tests/Security/CWE-328/WeakPasswordHashing.expected +++ b/swift/ql/test/query-tests/Security/CWE-328/WeakPasswordHashing.expected @@ -3,6 +3,7 @@ edges | testCryptoKit.swift:199:38:199:53 | .utf8 | testCryptoKit.swift:199:33:199:57 | call to Data.init(_:) | provenance | | nodes | testCryptoKit.swift:65:47:65:47 | passwd | semmle.label | passwd | +| testCryptoKit.swift:71:36:71:36 | passwd | semmle.label | passwd | | testCryptoKit.swift:77:44:77:44 | passwd | semmle.label | passwd | | testCryptoKit.swift:83:37:83:37 | passwd | semmle.label | passwd | | testCryptoKit.swift:89:37:89:37 | passwd | semmle.label | passwd | @@ -48,6 +49,7 @@ nodes subpaths #select | testCryptoKit.swift:65:47:65:47 | passwd | testCryptoKit.swift:65:47:65:47 | passwd | testCryptoKit.swift:65:47:65:47 | passwd | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:65:47:65:47 | passwd | password (passwd) | +| testCryptoKit.swift:71:36:71:36 | passwd | testCryptoKit.swift:71:36:71:36 | passwd | testCryptoKit.swift:71:36:71:36 | passwd | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:71:36:71:36 | passwd | password (passwd) | | testCryptoKit.swift:77:44:77:44 | passwd | testCryptoKit.swift:77:44:77:44 | passwd | testCryptoKit.swift:77:44:77:44 | passwd | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:77:44:77:44 | passwd | password (passwd) | | testCryptoKit.swift:83:37:83:37 | passwd | testCryptoKit.swift:83:37:83:37 | passwd | testCryptoKit.swift:83:37:83:37 | passwd | Insecure hashing algorithm (SHA256) depends on $@. | testCryptoKit.swift:83:37:83:37 | passwd | password (passwd) | | testCryptoKit.swift:89:37:89:37 | passwd | testCryptoKit.swift:89:37:89:37 | passwd | testCryptoKit.swift:89:37:89:37 | passwd | Insecure hashing algorithm (SHA384) depends on $@. | testCryptoKit.swift:89:37:89:37 | passwd | password (passwd) | diff --git a/swift/ql/test/query-tests/Security/CWE-328/WeakSensitiveDataHashing.expected b/swift/ql/test/query-tests/Security/CWE-328/WeakSensitiveDataHashing.expected index f65f4798debd..5da99db8068c 100644 --- a/swift/ql/test/query-tests/Security/CWE-328/WeakSensitiveDataHashing.expected +++ b/swift/ql/test/query-tests/Security/CWE-328/WeakSensitiveDataHashing.expected @@ -3,6 +3,9 @@ nodes | testCryptoKit.swift:66:43:66:43 | cert | semmle.label | cert | | testCryptoKit.swift:68:43:68:43 | account_no | semmle.label | account_no | | testCryptoKit.swift:69:43:69:43 | credit_card_no | semmle.label | credit_card_no | +| testCryptoKit.swift:72:36:72:36 | cert | semmle.label | cert | +| testCryptoKit.swift:74:36:74:36 | account_no | semmle.label | account_no | +| testCryptoKit.swift:75:36:75:36 | credit_card_no | semmle.label | credit_card_no | | testCryptoKit.swift:78:44:78:44 | cert | semmle.label | cert | | testCryptoKit.swift:80:44:80:44 | account_no | semmle.label | account_no | | testCryptoKit.swift:81:44:81:44 | credit_card_no | semmle.label | credit_card_no | @@ -33,6 +36,9 @@ subpaths | testCryptoKit.swift:66:43:66:43 | cert | testCryptoKit.swift:66:43:66:43 | cert | testCryptoKit.swift:66:43:66:43 | cert | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:66:43:66:43 | cert | sensitive data (credential cert) | | testCryptoKit.swift:68:43:68:43 | account_no | testCryptoKit.swift:68:43:68:43 | account_no | testCryptoKit.swift:68:43:68:43 | account_no | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:68:43:68:43 | account_no | sensitive data (private information account_no) | | testCryptoKit.swift:69:43:69:43 | credit_card_no | testCryptoKit.swift:69:43:69:43 | credit_card_no | testCryptoKit.swift:69:43:69:43 | credit_card_no | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:69:43:69:43 | credit_card_no | sensitive data (private information credit_card_no) | +| testCryptoKit.swift:72:36:72:36 | cert | testCryptoKit.swift:72:36:72:36 | cert | testCryptoKit.swift:72:36:72:36 | cert | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:72:36:72:36 | cert | sensitive data (credential cert) | +| testCryptoKit.swift:74:36:74:36 | account_no | testCryptoKit.swift:74:36:74:36 | account_no | testCryptoKit.swift:74:36:74:36 | account_no | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:74:36:74:36 | account_no | sensitive data (private information account_no) | +| testCryptoKit.swift:75:36:75:36 | credit_card_no | testCryptoKit.swift:75:36:75:36 | credit_card_no | testCryptoKit.swift:75:36:75:36 | credit_card_no | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:75:36:75:36 | credit_card_no | sensitive data (private information credit_card_no) | | testCryptoKit.swift:78:44:78:44 | cert | testCryptoKit.swift:78:44:78:44 | cert | testCryptoKit.swift:78:44:78:44 | cert | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:78:44:78:44 | cert | sensitive data (credential cert) | | testCryptoKit.swift:80:44:80:44 | account_no | testCryptoKit.swift:80:44:80:44 | account_no | testCryptoKit.swift:80:44:80:44 | account_no | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:80:44:80:44 | account_no | sensitive data (private information account_no) | | testCryptoKit.swift:81:44:81:44 | credit_card_no | testCryptoKit.swift:81:44:81:44 | credit_card_no | testCryptoKit.swift:81:44:81:44 | credit_card_no | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:81:44:81:44 | credit_card_no | sensitive data (private information credit_card_no) | diff --git a/swift/ql/test/query-tests/Security/CWE-328/testCryptoKit.swift b/swift/ql/test/query-tests/Security/CWE-328/testCryptoKit.swift index 804815260581..755bd27e3c73 100644 --- a/swift/ql/test/query-tests/Security/CWE-328/testCryptoKit.swift +++ b/swift/ql/test/query-tests/Security/CWE-328/testCryptoKit.swift @@ -68,11 +68,11 @@ func testHashMethods(passwd : UnsafeRawBufferPointer, cert: String, encrypted_pa hash = Crypto.Insecure.MD5.hash(data: account_no) // BAD hash = Crypto.Insecure.MD5.hash(data: credit_card_no) // BAD - - - - - + hash = Insecure.MD5.hash(data: passwd) // BAD + hash = Insecure.MD5.hash(data: cert) // BAD + hash = Insecure.MD5.hash(data: encrypted_passwd) // GOOD (not sensitive) + hash = Insecure.MD5.hash(data: account_no) // BAD + hash = Insecure.MD5.hash(data: credit_card_no) // BAD hash = Crypto.Insecure.SHA1.hash(data: passwd) // BAD hash = Crypto.Insecure.SHA1.hash(data: cert) // BAD From d95001f4069fab17ce172243bbe426ace747b730 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 6 May 2026 10:46:09 +0100 Subject: [PATCH 03/16] Rust: Additional test cases for sensitive data heuristics. --- .../test/library-tests/sensitivedata/test.rs | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/rust/ql/test/library-tests/sensitivedata/test.rs b/rust/ql/test/library-tests/sensitivedata/test.rs index f8d850beeb80..9b0581239dec 100644 --- a/rust/ql/test/library-tests/sensitivedata/test.rs +++ b/rust/ql/test/library-tests/sensitivedata/test.rs @@ -23,11 +23,14 @@ impl MyStruct { fn get_password() -> String { get_string() } fn test_passwords( - password: &str, pass_word: &str, passwd: &str, my_password: &str, password_str: &str, password_confirmation: &str, + password: &str, pass_word: &str, passwd: &str, my_password: &str, password_str: &str, password_confirmation: &str, profile_password: &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, + one_time_code: &str, api_token: &str, api_tok: &str, + harmless: &str, + encrypted_password: &str, unencrypted_password: &str, encoded_password: &str, unencoded_password: &str, + password_hash: &str, passwordFile: &str, coauthor: &str, + ms: &MyStruct ) { // passwords @@ -38,6 +41,9 @@ fn test_passwords( sink(my_password); // $ sensitive=password sink(password_str); // $ sensitive=password sink(password_confirmation); // $ sensitive=password + sink(profile_password); // $ MISSING: sensitive=password + sink(unencrypted_password); // $ MISSING: sensitive=password + sink(unencoded_password); // $ MISSING: sensitive=password sink(pass_phrase); // $ sensitive=password sink(passphrase); // $ sensitive=password sink(passPhrase); // $ sensitive=password @@ -51,6 +57,8 @@ fn test_passwords( sink(authenticationKey); // $ sensitive=password sink(oauth); // $ sensitive=password sink(one_time_code); // $ MISSING: sensitive=password + sink(api_token); // $ sensitive=password + sink(api_tok); // $ MISSING: sensitive=password sink(ms); // $ MISSING: sensitive=password sink(ms.password.as_str()); // $ sensitive=password @@ -67,8 +75,10 @@ fn test_passwords( sink(harmless); sink(encrypted_password); + sink(encoded_password); sink(password_hash); sink(passwordFile); + sink(coauthor); // $ SPURIOUS: sensitive=password sink(ms.harmless.as_str()); sink(ms.password_file_path.as_str()); @@ -187,6 +197,10 @@ struct Financials { harmless: String, my_bank_account_number: String, credit_card_no: String, + card_no: String, + cardNumber: String, + card_security_code: String, + credit_rating: i32, user_ccn: String, cvv: String, @@ -201,6 +215,7 @@ struct Financials { accounting: i32, unaccounted: bool, multiband: bool, + wildcard_not_matched: bool, } enum Gender { @@ -298,6 +313,9 @@ fn test_private_info( 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.card_no.as_str()); // $ MISSING: sensitive=private + sink(info.financials.cardNumber.as_str()); // $ MISSING: sensitive=private + sink(info.financials.card_security_code.as_str()); // $ MISSING: sensitive=private sink(info.financials.credit_rating); // $ sensitive=private sink(info.financials.user_ccn.as_str()); // $ sensitive=private sink(info.financials.cvv.as_str()); // $ sensitive=private @@ -350,6 +368,7 @@ fn test_private_info( sink(info.financials.accounting); sink(info.financials.unaccounted); sink(info.financials.multiband); + sink(info.financials.wildcard_not_matched); sink(ContactDetails::FavouriteColor("blue".to_string())); } From 07d4df18b911584c2058ca1b8311253dbdc4d91c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 6 May 2026 11:28:41 +0100 Subject: [PATCH 04/16] Shared: Add 'card.?no' sensitive data heuristic. --- rust/ql/test/library-tests/sensitivedata/test.rs | 6 +++--- .../codeql/concepts/internal/SensitiveDataHeuristics.qll | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rust/ql/test/library-tests/sensitivedata/test.rs b/rust/ql/test/library-tests/sensitivedata/test.rs index 9b0581239dec..a5af8efeab47 100644 --- a/rust/ql/test/library-tests/sensitivedata/test.rs +++ b/rust/ql/test/library-tests/sensitivedata/test.rs @@ -313,8 +313,8 @@ fn test_private_info( 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.card_no.as_str()); // $ MISSING: sensitive=private - sink(info.financials.cardNumber.as_str()); // $ MISSING: sensitive=private + sink(info.financials.card_no.as_str()); // $ sensitive=private + sink(info.financials.cardNumber.as_str()); // $ sensitive=private sink(info.financials.card_security_code.as_str()); // $ MISSING: sensitive=private sink(info.financials.credit_rating); // $ sensitive=private sink(info.financials.user_ccn.as_str()); // $ sensitive=private @@ -368,7 +368,7 @@ fn test_private_info( sink(info.financials.accounting); sink(info.financials.unaccounted); sink(info.financials.multiband); - sink(info.financials.wildcard_not_matched); + sink(info.financials.wildcard_not_matched); // $ SPURIOUS: sensitive=private sink(ContactDetails::FavouriteColor("blue".to_string())); } diff --git a/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll b/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll index 4271784577f0..c30a834fbd53 100644 --- a/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll +++ b/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll @@ -104,7 +104,7 @@ module HeuristicNames { // Geographic location - where the user is (or was) "latitude|longitude|nationality|" + // Financial data - such as credit card numbers, salary, bank accounts, and debts - "(credit|debit|bank|visa).?(card|num|no|acc(ou)?nt)|acc(ou)?nt.?(no|num|credit)|routing.?num|" + "(credit|debit|bank|visa).?(card|num|no|acc(ou)?nt)|(card|acc(ou)?nt).?(no|num|credit)|routing.?num|" + "salary|billing|beneficiary|credit.?(rating|score)|([_-]|\\b)(ccn|cvv|iban)([_-]|\\b)|" + // Communications - e-mail addresses, private e-mail messages, SMS text messages, chat logs, etc. // "e(mail|_mail)|" + // this seems too noisy From cb84e633fa647d4713b09fbbd8f741912da4d992 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 6 May 2026 11:52:05 +0100 Subject: [PATCH 05/16] Shared: Fix for 'wildcard'. --- rust/ql/test/library-tests/sensitivedata/test.rs | 2 +- .../codeql/concepts/internal/SensitiveDataHeuristics.qll | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rust/ql/test/library-tests/sensitivedata/test.rs b/rust/ql/test/library-tests/sensitivedata/test.rs index a5af8efeab47..db834b54b06f 100644 --- a/rust/ql/test/library-tests/sensitivedata/test.rs +++ b/rust/ql/test/library-tests/sensitivedata/test.rs @@ -368,7 +368,7 @@ fn test_private_info( sink(info.financials.accounting); sink(info.financials.unaccounted); sink(info.financials.multiband); - sink(info.financials.wildcard_not_matched); // $ SPURIOUS: sensitive=private + sink(info.financials.wildcard_not_matched); sink(ContactDetails::FavouriteColor("blue".to_string())); } diff --git a/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll b/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll index c30a834fbd53..32045c783c79 100644 --- a/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll +++ b/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll @@ -145,13 +145,13 @@ module HeuristicNames { * suggesting nouns within the string do not represent the meaning of the whole string (e.g. a URL or a SQL query). * * We also filter out common words like `certain` and `concert`, since otherwise these could - * be matched by the certificate regular expressions. Same for `accountable` (account), or - * `secretarial` (secret). + * be matched by the certificate regular expressions. Same for `accountable` (account), + * `secretarial` (secret), `wildcard` (card). */ string notSensitiveRegexp() { result = "(?is).*([^\\w$.-]|redact|censor|obfuscate|hash|md5|sha|random|((? Date: Wed, 6 May 2026 12:00:06 +0100 Subject: [PATCH 06/16] Shared: Fix for 'profile'. --- rust/ql/test/library-tests/sensitivedata/test.rs | 2 +- .../codeql/concepts/internal/SensitiveDataHeuristics.qll | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/ql/test/library-tests/sensitivedata/test.rs b/rust/ql/test/library-tests/sensitivedata/test.rs index db834b54b06f..a85db97fb729 100644 --- a/rust/ql/test/library-tests/sensitivedata/test.rs +++ b/rust/ql/test/library-tests/sensitivedata/test.rs @@ -41,7 +41,7 @@ fn test_passwords( sink(my_password); // $ sensitive=password sink(password_str); // $ sensitive=password sink(password_confirmation); // $ sensitive=password - sink(profile_password); // $ MISSING: sensitive=password + sink(profile_password); // $ sensitive=password sink(unencrypted_password); // $ MISSING: sensitive=password sink(unencoded_password); // $ MISSING: sensitive=password sink(pass_phrase); // $ sensitive=password diff --git a/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll b/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll index 32045c783c79..0f66d5b6c4fb 100644 --- a/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll +++ b/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll @@ -151,7 +151,7 @@ module HeuristicNames { string notSensitiveRegexp() { result = "(?is).*([^\\w$.-]|redact|censor|obfuscate|hash|md5|sha|random|((? Date: Wed, 6 May 2026 12:04:59 +0100 Subject: [PATCH 07/16] Shared: Fix for 'api_tok'. --- rust/ql/test/library-tests/sensitivedata/test.rs | 2 +- .../codeql/concepts/internal/SensitiveDataHeuristics.qll | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/ql/test/library-tests/sensitivedata/test.rs b/rust/ql/test/library-tests/sensitivedata/test.rs index a85db97fb729..1e1eca6a42b3 100644 --- a/rust/ql/test/library-tests/sensitivedata/test.rs +++ b/rust/ql/test/library-tests/sensitivedata/test.rs @@ -58,7 +58,7 @@ fn test_passwords( sink(oauth); // $ sensitive=password sink(one_time_code); // $ MISSING: sensitive=password sink(api_token); // $ sensitive=password - sink(api_tok); // $ MISSING: sensitive=password + sink(api_tok); // $ sensitive=password sink(ms); // $ MISSING: sensitive=password sink(ms.password.as_str()); // $ sensitive=password diff --git a/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll b/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll index 0f66d5b6c4fb..9cc414ef85fe 100644 --- a/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll +++ b/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll @@ -76,7 +76,7 @@ module HeuristicNames { string maybePassword() { result = "(?is).*(pass(wd|word|code|.?phrase)(?!.*question)|(auth(entication|ori[sz]ation)?).?key|oauth|" - + "api.?(key|token)|([_-]|\\b)mfa([_-]|\\b)).*" + + "api.?(key|tok)|([_-]|\\b)mfa([_-]|\\b)).*" } /** From 6e2fb6f0ff5fb048dbdd17068abdee84d8df73c8 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 6 May 2026 12:06:55 +0100 Subject: [PATCH 08/16] Shared: Fix for 'coauthor'. --- rust/ql/test/library-tests/sensitivedata/test.rs | 2 +- .../codeql/concepts/internal/SensitiveDataHeuristics.qll | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/ql/test/library-tests/sensitivedata/test.rs b/rust/ql/test/library-tests/sensitivedata/test.rs index 1e1eca6a42b3..81ef1b782ea4 100644 --- a/rust/ql/test/library-tests/sensitivedata/test.rs +++ b/rust/ql/test/library-tests/sensitivedata/test.rs @@ -78,7 +78,7 @@ fn test_passwords( sink(encoded_password); sink(password_hash); sink(passwordFile); - sink(coauthor); // $ SPURIOUS: sensitive=password + sink(coauthor); sink(ms.harmless.as_str()); sink(ms.password_file_path.as_str()); diff --git a/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll b/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll index 9cc414ef85fe..c16478902e44 100644 --- a/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll +++ b/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll @@ -146,12 +146,12 @@ module HeuristicNames { * * We also filter out common words like `certain` and `concert`, since otherwise these could * be matched by the certificate regular expressions. Same for `accountable` (account), - * `secretarial` (secret), `wildcard` (card). + * `secretarial` (secret), `wildcard` (card), `coauthor` (oauth). */ string notSensitiveRegexp() { result = "(?is).*([^\\w$.-]|redact|censor|obfuscate|hash|md5|sha|random|((? Date: Wed, 6 May 2026 14:43:23 +0100 Subject: [PATCH 09/16] Shared: Fix and simplify the exclusion for 'encrypted' values. --- rust/ql/test/library-tests/sensitivedata/test.rs | 4 ++-- .../codeql/concepts/internal/SensitiveDataHeuristics.qll | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/ql/test/library-tests/sensitivedata/test.rs b/rust/ql/test/library-tests/sensitivedata/test.rs index 81ef1b782ea4..2fa22152c83a 100644 --- a/rust/ql/test/library-tests/sensitivedata/test.rs +++ b/rust/ql/test/library-tests/sensitivedata/test.rs @@ -42,8 +42,8 @@ fn test_passwords( sink(password_str); // $ sensitive=password sink(password_confirmation); // $ sensitive=password sink(profile_password); // $ sensitive=password - sink(unencrypted_password); // $ MISSING: sensitive=password - sink(unencoded_password); // $ MISSING: sensitive=password + sink(unencrypted_password); // $ sensitive=password + sink(unencoded_password); // $ sensitive=password sink(pass_phrase); // $ sensitive=password sink(passphrase); // $ sensitive=password sink(passPhrase); // $ sensitive=password diff --git a/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll b/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll index c16478902e44..80ef76c76aca 100644 --- a/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll +++ b/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll @@ -150,7 +150,7 @@ module HeuristicNames { */ string notSensitiveRegexp() { result = - "(?is).*([^\\w$.-]|redact|censor|obfuscate|hash|md5|sha|random|((? Date: Wed, 6 May 2026 14:19:08 +0100 Subject: [PATCH 10/16] Shared: Add 'security_code' sensitive data heuristic. --- rust/ql/test/library-tests/sensitivedata/test.rs | 2 +- .../codeql/concepts/internal/SensitiveDataHeuristics.qll | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/rust/ql/test/library-tests/sensitivedata/test.rs b/rust/ql/test/library-tests/sensitivedata/test.rs index 2fa22152c83a..e2bb5a5f595c 100644 --- a/rust/ql/test/library-tests/sensitivedata/test.rs +++ b/rust/ql/test/library-tests/sensitivedata/test.rs @@ -315,7 +315,7 @@ fn test_private_info( sink(info.financials.credit_card_no.as_str()); // $ sensitive=private sink(info.financials.card_no.as_str()); // $ sensitive=private sink(info.financials.cardNumber.as_str()); // $ sensitive=private - sink(info.financials.card_security_code.as_str()); // $ MISSING: sensitive=private + sink(info.financials.card_security_code.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()); // $ sensitive=private diff --git a/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll b/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll index 80ef76c76aca..f3b979d2e3b9 100644 --- a/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll +++ b/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll @@ -106,6 +106,7 @@ module HeuristicNames { // Financial data - such as credit card numbers, salary, bank accounts, and debts "(credit|debit|bank|visa).?(card|num|no|acc(ou)?nt)|(card|acc(ou)?nt).?(no|num|credit)|routing.?num|" + "salary|billing|beneficiary|credit.?(rating|score)|([_-]|\\b)(ccn|cvv|iban)([_-]|\\b)|" + + "security.?code|" + // Communications - e-mail addresses, private e-mail messages, SMS text messages, chat logs, etc. // "e(mail|_mail)|" + // this seems too noisy // Health - medical conditions, insurance status, prescription records From 809da0f8e78347cbd3c2e00c70f575044b377aac Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 7 May 2026 10:01:56 +0100 Subject: [PATCH 11/16] Shared: Autoformat. --- .../codeql/concepts/internal/SensitiveDataHeuristics.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll b/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll index f3b979d2e3b9..94619488f1a9 100644 --- a/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll +++ b/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll @@ -151,8 +151,8 @@ module HeuristicNames { */ string notSensitiveRegexp() { result = - "(?is).*([^\\w$.-]|redact|censor|obfuscate|hash|md5|sha|random|(? Date: Thu, 7 May 2026 10:04:19 +0100 Subject: [PATCH 12/16] Swift: Accept test changes (improvement). --- .../query-tests/Security/CWE-311/CleartextTransmission.expected | 2 ++ .../test/query-tests/Security/CWE-311/SensitiveExprs.expected | 1 + swift/ql/test/query-tests/Security/CWE-311/testSend.swift | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected b/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected index c772466344ae..7665b72b11a6 100644 --- a/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected +++ b/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected @@ -64,6 +64,7 @@ nodes | testSend.swift:78:27:78:30 | .CarePlanID | semmle.label | .CarePlanID | | testSend.swift:79:27:79:30 | .BankCardNo | semmle.label | .BankCardNo | | testSend.swift:80:27:80:30 | .MyCreditRating | semmle.label | .MyCreditRating | +| testSend.swift:81:27:81:30 | .OneTimeCode | semmle.label | .OneTimeCode | | testSend.swift:86:7:86:7 | self | semmle.label | self | | testSend.swift:94:27:94:30 | .password | semmle.label | .password | | testSend.swift:94:27:94:39 | .value | semmle.label | .value | @@ -118,6 +119,7 @@ subpaths | testSend.swift:78:27:78:30 | .CarePlanID | testSend.swift:78:27:78:30 | .CarePlanID | testSend.swift:78:27:78:30 | .CarePlanID | This operation transmits '.CarePlanID', which may contain unencrypted sensitive data from $@. | testSend.swift:78:27:78:30 | .CarePlanID | .CarePlanID | | testSend.swift:79:27:79:30 | .BankCardNo | testSend.swift:79:27:79:30 | .BankCardNo | testSend.swift:79:27:79:30 | .BankCardNo | This operation transmits '.BankCardNo', which may contain unencrypted sensitive data from $@. | testSend.swift:79:27:79:30 | .BankCardNo | .BankCardNo | | testSend.swift:80:27:80:30 | .MyCreditRating | testSend.swift:80:27:80:30 | .MyCreditRating | testSend.swift:80:27:80:30 | .MyCreditRating | This operation transmits '.MyCreditRating', which may contain unencrypted sensitive data from $@. | testSend.swift:80:27:80:30 | .MyCreditRating | .MyCreditRating | +| testSend.swift:81:27:81:30 | .OneTimeCode | testSend.swift:81:27:81:30 | .OneTimeCode | testSend.swift:81:27:81:30 | .OneTimeCode | This operation transmits '.OneTimeCode', which may contain unencrypted sensitive data from $@. | testSend.swift:81:27:81:30 | .OneTimeCode | .OneTimeCode | | testSend.swift:94:27:94:39 | .value | testSend.swift:94:27:94:30 | .password | testSend.swift:94:27:94:39 | .value | This operation transmits '.value', which may contain unencrypted sensitive data from $@. | testSend.swift:94:27:94:30 | .password | .password | | testURL.swift:39:18:39:50 | ... .+(_:_:) ... | testURL.swift:39:50:39:50 | passwd | testURL.swift:39:18:39:50 | ... .+(_:_:) ... | This operation transmits '... .+(_:_:) ...', which may contain unencrypted sensitive data from $@. | testURL.swift:39:50:39:50 | passwd | passwd | | testURL.swift:41:18:41:51 | ... .+(_:_:) ... | testURL.swift:41:51:41:51 | account_no | testURL.swift:41:18:41:51 | ... .+(_:_:) ... | This operation transmits '... .+(_:_:) ...', which may contain unencrypted sensitive data from $@. | testURL.swift:41:51:41:51 | account_no | account_no | diff --git a/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected b/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected index c4ff7f42b2e1..62fc29a9a582 100644 --- a/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected +++ b/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected @@ -170,6 +170,7 @@ | testSend.swift:78:27:78:30 | .CarePlanID | label:CarePlanID, type:private information | | testSend.swift:79:27:79:30 | .BankCardNo | label:BankCardNo, type:private information | | testSend.swift:80:27:80:30 | .MyCreditRating | label:MyCreditRating, type:private information | +| testSend.swift:81:27:81:30 | .OneTimeCode | label:OneTimeCode, type:credential | | testSend.swift:94:27:94:30 | .password | label:password, type:password | | testURL.swift:39:50:39:50 | passwd | label:passwd, type:password | | testURL.swift:41:51:41:51 | account_no | label:account_no, type:private information | diff --git a/swift/ql/test/query-tests/Security/CWE-311/testSend.swift b/swift/ql/test/query-tests/Security/CWE-311/testSend.swift index 8acb83e51c19..bea4dfa16b63 100644 --- a/swift/ql/test/query-tests/Security/CWE-311/testSend.swift +++ b/swift/ql/test/query-tests/Security/CWE-311/testSend.swift @@ -78,7 +78,7 @@ func test2(password : String, license_key: String, ms: MyStruct, connection : NW connection.send(content: ms.CarePlanID, completion: .idempotent) // BAD connection.send(content: ms.BankCardNo, completion: .idempotent) // BAD connection.send(content: ms.MyCreditRating, completion: .idempotent) // BAD - connection.send(content: ms.OneTimeCode, completion: .idempotent) // BAD [NOT DETECTED] + connection.send(content: ms.OneTimeCode, completion: .idempotent) // BAD } struct MyOuter { From ea711b032bc400b7f299459ebfa237eb6c23d112 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 7 May 2026 10:12:35 +0100 Subject: [PATCH 13/16] Javascript: Accept test changes (regression). --- .../Security/CWE-312/CleartextLogging.expected | 12 ++++++++++++ .../test/query-tests/Security/CWE-312/passwords.js | 8 ++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/javascript/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected b/javascript/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected index af9e0f485c2d..77eefa87c2bd 100644 --- a/javascript/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected +++ b/javascript/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected @@ -9,6 +9,9 @@ | passwords.js:16:17:16:38 | `${name ... sword}` | passwords.js:16:29:16:36 | password | passwords.js:16:17:16:38 | `${name ... sword}` | This logs sensitive data returned by $@ as clear text. | passwords.js:16:29:16:36 | password | an access to password | | passwords.js:21:17:21:20 | obj1 | passwords.js:19:19:19:19 | x | passwords.js:21:17:21:20 | obj1 | This logs sensitive data returned by $@ as clear text. | passwords.js:19:19:19:19 | x | an access to password | | passwords.js:26:17:26:20 | obj2 | passwords.js:24:12:24:19 | password | passwords.js:26:17:26:20 | obj2 | This logs sensitive data returned by $@ as clear text. | passwords.js:24:12:24:19 | password | an access to password | +| passwords.js:41:17:41:37 | {passwo ... pt(pw)} | passwords.js:41:28:41:36 | crypt(pw) | passwords.js:41:17:41:37 | {passwo ... pt(pw)} | This logs sensitive data returned by $@ as clear text. | passwords.js:41:28:41:36 | crypt(pw) | an access to password | +| passwords.js:43:17:43:40 | actuall ... assword | passwords.js:43:17:43:40 | actuall ... assword | passwords.js:43:17:43:40 | actuall ... assword | This logs sensitive data returned by $@ as clear text. | passwords.js:43:17:43:40 | actuall ... assword | an access to actually_secure_password | +| passwords.js:47:17:47:21 | user1 | passwords.js:46:30:46:32 | x() | passwords.js:47:17:47:21 | user1 | This logs sensitive data returned by $@ as clear text. | passwords.js:46:30:46:32 | x() | an access to crypted_password | | passwords.js:78:17:78:38 | temp.en ... assword | passwords.js:77:37:77:53 | req.body.password | passwords.js:78:17:78:38 | temp.en ... assword | This logs sensitive data returned by $@ as clear text. | passwords.js:77:37:77:53 | req.body.password | an access to password | | passwords.js:81:17:81:31 | `pw: ${secret}` | passwords.js:80:18:80:25 | password | passwords.js:81:17:81:31 | `pw: ${secret}` | This logs sensitive data returned by $@ as clear text. | passwords.js:80:18:80:25 | password | an access to password | | passwords.js:93:21:93:46 | "Passwo ... assword | passwords.js:93:39:93:46 | password | passwords.js:93:21:93:46 | "Passwo ... assword | This logs sensitive data returned by $@ as clear text. | passwords.js:93:39:93:46 | password | an access to password | @@ -52,6 +55,9 @@ edges | passwords.js:23:9:23:12 | obj2 [x] | passwords.js:26:17:26:20 | obj2 | provenance | | | passwords.js:23:16:25:5 | {\\n ... ]\\n } [x] | passwords.js:23:9:23:12 | obj2 [x] | provenance | | | passwords.js:24:12:24:19 | password | passwords.js:23:16:25:5 | {\\n ... ]\\n } [x] | provenance | | +| passwords.js:41:28:41:36 | crypt(pw) | passwords.js:41:17:41:37 | {passwo ... pt(pw)} | provenance | | +| passwords.js:46:5:46:9 | [post update] user1 [crypted_password] | passwords.js:47:17:47:21 | user1 | provenance | | +| passwords.js:46:30:46:32 | x() | passwords.js:46:5:46:9 | [post update] user1 [crypted_password] | provenance | | | passwords.js:77:9:77:12 | temp [encryptedPassword] | passwords.js:78:17:78:20 | temp [encryptedPassword] | provenance | | | passwords.js:77:16:77:55 | { encry ... sword } [encryptedPassword] | passwords.js:77:9:77:12 | temp [encryptedPassword] | provenance | | | passwords.js:77:37:77:53 | req.body.password | passwords.js:77:16:77:55 | { encry ... sword } [encryptedPassword] | provenance | | @@ -139,6 +145,12 @@ nodes | passwords.js:23:16:25:5 | {\\n ... ]\\n } [x] | semmle.label | {\\n ... ]\\n } [x] | | passwords.js:24:12:24:19 | password | semmle.label | password | | passwords.js:26:17:26:20 | obj2 | semmle.label | obj2 | +| passwords.js:41:17:41:37 | {passwo ... pt(pw)} | semmle.label | {passwo ... pt(pw)} | +| passwords.js:41:28:41:36 | crypt(pw) | semmle.label | crypt(pw) | +| passwords.js:43:17:43:40 | actuall ... assword | semmle.label | actuall ... assword | +| passwords.js:46:5:46:9 | [post update] user1 [crypted_password] | semmle.label | [post update] user1 [crypted_password] | +| passwords.js:46:30:46:32 | x() | semmle.label | x() | +| passwords.js:47:17:47:21 | user1 | semmle.label | user1 | | passwords.js:77:9:77:12 | temp [encryptedPassword] | semmle.label | temp [encryptedPassword] | | passwords.js:77:16:77:55 | { encry ... sword } [encryptedPassword] | semmle.label | { encry ... sword } [encryptedPassword] | | passwords.js:77:37:77:53 | req.body.password | semmle.label | req.body.password | diff --git a/javascript/ql/test/query-tests/Security/CWE-312/passwords.js b/javascript/ql/test/query-tests/Security/CWE-312/passwords.js index 47304946e39c..ed1c9785f232 100644 --- a/javascript/ql/test/query-tests/Security/CWE-312/passwords.js +++ b/javascript/ql/test/query-tests/Security/CWE-312/passwords.js @@ -38,13 +38,13 @@ console.log(login.wrappedJSObject.encryptedPassword); console.log(HTML5QQ.encodedPassword); - console.log({password: crypt(pw)}); + console.log({password: crypt(pw)}); // $ SPURIOUS: Alert[js/clear-text-logging] var actually_secure_password = crypt(password); - console.log(actually_secure_password); + console.log(actually_secure_password); // $ SPURIOUS: Alert[js/clear-text-logging] var user1 = {}; - user1.crypted_password = x(); - console.log(user1); + user1.crypted_password = x(); // $ SPURIOUS: Source[js/clear-text-logging] + console.log(user1); // $ SPURIOUS: Alert[js/clear-text-logging] var user2 = {}; user2.password = hash(); From 1c704a091296094780246ff83a7c5389c8f9630a Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 7 May 2026 10:28:19 +0100 Subject: [PATCH 14/16] Python: Accept test changes (improvement). --- .../CWE-312-CleartextLogging/CleartextLogging.expected | 8 ++++++++ .../query-tests/Security/CWE-312-CleartextLogging/test.py | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected b/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected index dca1a33e73a3..7cb9e0151907 100644 --- a/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected +++ b/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected @@ -10,6 +10,8 @@ edges | test.py:48:14:48:35 | ControlFlowNode for social_security_number | test.py:49:15:49:36 | ControlFlowNode for social_security_number | provenance | | | test.py:48:38:48:40 | ControlFlowNode for ssn | test.py:50:15:50:17 | ControlFlowNode for ssn | provenance | | | test.py:48:54:48:63 | ControlFlowNode for passportNo | test.py:52:15:52:24 | ControlFlowNode for passportNo | provenance | | +| test.py:54:14:54:22 | ControlFlowNode for post_code | test.py:55:15:55:23 | ControlFlowNode for post_code | provenance | | +| test.py:54:25:54:31 | ControlFlowNode for zipCode | test.py:56:15:56:21 | ControlFlowNode for zipCode | provenance | | | test.py:54:34:54:45 | ControlFlowNode for home_address | test.py:57:15:57:26 | ControlFlowNode for home_address | provenance | | | test.py:59:14:59:26 | ControlFlowNode for user_latitude | test.py:60:15:60:27 | ControlFlowNode for user_latitude | provenance | | | test.py:59:29:59:42 | ControlFlowNode for user_longitude | test.py:61:15:61:28 | ControlFlowNode for user_longitude | provenance | | @@ -42,7 +44,11 @@ nodes | test.py:49:15:49:36 | ControlFlowNode for social_security_number | semmle.label | ControlFlowNode for social_security_number | | test.py:50:15:50:17 | ControlFlowNode for ssn | semmle.label | ControlFlowNode for ssn | | test.py:52:15:52:24 | ControlFlowNode for passportNo | semmle.label | ControlFlowNode for passportNo | +| test.py:54:14:54:22 | ControlFlowNode for post_code | semmle.label | ControlFlowNode for post_code | +| test.py:54:25:54:31 | ControlFlowNode for zipCode | semmle.label | ControlFlowNode for zipCode | | test.py:54:34:54:45 | ControlFlowNode for home_address | semmle.label | ControlFlowNode for home_address | +| test.py:55:15:55:23 | ControlFlowNode for post_code | semmle.label | ControlFlowNode for post_code | +| test.py:56:15:56:21 | ControlFlowNode for zipCode | semmle.label | ControlFlowNode for zipCode | | test.py:57:15:57:26 | ControlFlowNode for home_address | semmle.label | ControlFlowNode for home_address | | test.py:59:14:59:26 | ControlFlowNode for user_latitude | semmle.label | ControlFlowNode for user_latitude | | test.py:59:29:59:42 | ControlFlowNode for user_longitude | semmle.label | ControlFlowNode for user_longitude | @@ -79,6 +85,8 @@ subpaths | test.py:49:15:49:36 | ControlFlowNode for social_security_number | test.py:48:14:48:35 | ControlFlowNode for social_security_number | test.py:49:15:49:36 | ControlFlowNode for social_security_number | This expression logs $@ as clear text. | test.py:48:14:48:35 | ControlFlowNode for social_security_number | sensitive data (private) | | test.py:50:15:50:17 | ControlFlowNode for ssn | test.py:48:38:48:40 | ControlFlowNode for ssn | test.py:50:15:50:17 | ControlFlowNode for ssn | This expression logs $@ as clear text. | test.py:48:38:48:40 | ControlFlowNode for ssn | sensitive data (private) | | test.py:52:15:52:24 | ControlFlowNode for passportNo | test.py:48:54:48:63 | ControlFlowNode for passportNo | test.py:52:15:52:24 | ControlFlowNode for passportNo | This expression logs $@ as clear text. | test.py:48:54:48:63 | ControlFlowNode for passportNo | sensitive data (private) | +| test.py:55:15:55:23 | ControlFlowNode for post_code | test.py:54:14:54:22 | ControlFlowNode for post_code | test.py:55:15:55:23 | ControlFlowNode for post_code | This expression logs $@ as clear text. | test.py:54:14:54:22 | ControlFlowNode for post_code | sensitive data (private) | +| test.py:56:15:56:21 | ControlFlowNode for zipCode | test.py:54:25:54:31 | ControlFlowNode for zipCode | test.py:56:15:56:21 | ControlFlowNode for zipCode | This expression logs $@ as clear text. | test.py:54:25:54:31 | ControlFlowNode for zipCode | sensitive data (private) | | test.py:57:15:57:26 | ControlFlowNode for home_address | test.py:54:34:54:45 | ControlFlowNode for home_address | test.py:57:15:57:26 | ControlFlowNode for home_address | This expression logs $@ as clear text. | test.py:54:34:54:45 | ControlFlowNode for home_address | sensitive data (private) | | test.py:60:15:60:27 | ControlFlowNode for user_latitude | test.py:59:14:59:26 | ControlFlowNode for user_latitude | test.py:60:15:60:27 | ControlFlowNode for user_latitude | This expression logs $@ as clear text. | test.py:59:14:59:26 | ControlFlowNode for user_latitude | sensitive data (private) | | test.py:61:15:61:28 | ControlFlowNode for user_longitude | test.py:59:29:59:42 | ControlFlowNode for user_longitude | test.py:61:15:61:28 | ControlFlowNode for user_longitude | This expression logs $@ as clear text. | test.py:59:29:59:42 | ControlFlowNode for user_longitude | sensitive data (private) | diff --git a/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/test.py b/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/test.py index d8d70c56bd57..ff01680ed81c 100644 --- a/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/test.py +++ b/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/test.py @@ -52,8 +52,8 @@ def log1(social_security_number, ssn, className, passportNo): print(passportNo) # NOT OK def log2(post_code, zipCode, home_address): - print(post_code) # NOT OK, but NOT FOUND - "code" is treated as encrypted and thus not sensitive - print(zipCode) # NOT OK, but NOT FOUND - "code" is treated as encrypted and thus not sensitive + print(post_code) # NOT OK + print(zipCode) # NOT OK print(home_address) # NOT OK def log3(user_latitude, user_longitude): From df37b500516e7f633f0b640a12924bd35e34b2bf Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 7 May 2026 10:35:04 +0100 Subject: [PATCH 15/16] Shared: Small adjustment to the encrypt not-sensitive regex. --- .../Security/CWE-312/CleartextLogging.expected | 12 ------------ .../test/query-tests/Security/CWE-312/passwords.js | 8 ++++---- .../concepts/internal/SensitiveDataHeuristics.qll | 3 ++- 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/javascript/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected b/javascript/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected index 77eefa87c2bd..af9e0f485c2d 100644 --- a/javascript/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected +++ b/javascript/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected @@ -9,9 +9,6 @@ | passwords.js:16:17:16:38 | `${name ... sword}` | passwords.js:16:29:16:36 | password | passwords.js:16:17:16:38 | `${name ... sword}` | This logs sensitive data returned by $@ as clear text. | passwords.js:16:29:16:36 | password | an access to password | | passwords.js:21:17:21:20 | obj1 | passwords.js:19:19:19:19 | x | passwords.js:21:17:21:20 | obj1 | This logs sensitive data returned by $@ as clear text. | passwords.js:19:19:19:19 | x | an access to password | | passwords.js:26:17:26:20 | obj2 | passwords.js:24:12:24:19 | password | passwords.js:26:17:26:20 | obj2 | This logs sensitive data returned by $@ as clear text. | passwords.js:24:12:24:19 | password | an access to password | -| passwords.js:41:17:41:37 | {passwo ... pt(pw)} | passwords.js:41:28:41:36 | crypt(pw) | passwords.js:41:17:41:37 | {passwo ... pt(pw)} | This logs sensitive data returned by $@ as clear text. | passwords.js:41:28:41:36 | crypt(pw) | an access to password | -| passwords.js:43:17:43:40 | actuall ... assword | passwords.js:43:17:43:40 | actuall ... assword | passwords.js:43:17:43:40 | actuall ... assword | This logs sensitive data returned by $@ as clear text. | passwords.js:43:17:43:40 | actuall ... assword | an access to actually_secure_password | -| passwords.js:47:17:47:21 | user1 | passwords.js:46:30:46:32 | x() | passwords.js:47:17:47:21 | user1 | This logs sensitive data returned by $@ as clear text. | passwords.js:46:30:46:32 | x() | an access to crypted_password | | passwords.js:78:17:78:38 | temp.en ... assword | passwords.js:77:37:77:53 | req.body.password | passwords.js:78:17:78:38 | temp.en ... assword | This logs sensitive data returned by $@ as clear text. | passwords.js:77:37:77:53 | req.body.password | an access to password | | passwords.js:81:17:81:31 | `pw: ${secret}` | passwords.js:80:18:80:25 | password | passwords.js:81:17:81:31 | `pw: ${secret}` | This logs sensitive data returned by $@ as clear text. | passwords.js:80:18:80:25 | password | an access to password | | passwords.js:93:21:93:46 | "Passwo ... assword | passwords.js:93:39:93:46 | password | passwords.js:93:21:93:46 | "Passwo ... assword | This logs sensitive data returned by $@ as clear text. | passwords.js:93:39:93:46 | password | an access to password | @@ -55,9 +52,6 @@ edges | passwords.js:23:9:23:12 | obj2 [x] | passwords.js:26:17:26:20 | obj2 | provenance | | | passwords.js:23:16:25:5 | {\\n ... ]\\n } [x] | passwords.js:23:9:23:12 | obj2 [x] | provenance | | | passwords.js:24:12:24:19 | password | passwords.js:23:16:25:5 | {\\n ... ]\\n } [x] | provenance | | -| passwords.js:41:28:41:36 | crypt(pw) | passwords.js:41:17:41:37 | {passwo ... pt(pw)} | provenance | | -| passwords.js:46:5:46:9 | [post update] user1 [crypted_password] | passwords.js:47:17:47:21 | user1 | provenance | | -| passwords.js:46:30:46:32 | x() | passwords.js:46:5:46:9 | [post update] user1 [crypted_password] | provenance | | | passwords.js:77:9:77:12 | temp [encryptedPassword] | passwords.js:78:17:78:20 | temp [encryptedPassword] | provenance | | | passwords.js:77:16:77:55 | { encry ... sword } [encryptedPassword] | passwords.js:77:9:77:12 | temp [encryptedPassword] | provenance | | | passwords.js:77:37:77:53 | req.body.password | passwords.js:77:16:77:55 | { encry ... sword } [encryptedPassword] | provenance | | @@ -145,12 +139,6 @@ nodes | passwords.js:23:16:25:5 | {\\n ... ]\\n } [x] | semmle.label | {\\n ... ]\\n } [x] | | passwords.js:24:12:24:19 | password | semmle.label | password | | passwords.js:26:17:26:20 | obj2 | semmle.label | obj2 | -| passwords.js:41:17:41:37 | {passwo ... pt(pw)} | semmle.label | {passwo ... pt(pw)} | -| passwords.js:41:28:41:36 | crypt(pw) | semmle.label | crypt(pw) | -| passwords.js:43:17:43:40 | actuall ... assword | semmle.label | actuall ... assword | -| passwords.js:46:5:46:9 | [post update] user1 [crypted_password] | semmle.label | [post update] user1 [crypted_password] | -| passwords.js:46:30:46:32 | x() | semmle.label | x() | -| passwords.js:47:17:47:21 | user1 | semmle.label | user1 | | passwords.js:77:9:77:12 | temp [encryptedPassword] | semmle.label | temp [encryptedPassword] | | passwords.js:77:16:77:55 | { encry ... sword } [encryptedPassword] | semmle.label | { encry ... sword } [encryptedPassword] | | passwords.js:77:37:77:53 | req.body.password | semmle.label | req.body.password | diff --git a/javascript/ql/test/query-tests/Security/CWE-312/passwords.js b/javascript/ql/test/query-tests/Security/CWE-312/passwords.js index ed1c9785f232..47304946e39c 100644 --- a/javascript/ql/test/query-tests/Security/CWE-312/passwords.js +++ b/javascript/ql/test/query-tests/Security/CWE-312/passwords.js @@ -38,13 +38,13 @@ console.log(login.wrappedJSObject.encryptedPassword); console.log(HTML5QQ.encodedPassword); - console.log({password: crypt(pw)}); // $ SPURIOUS: Alert[js/clear-text-logging] + console.log({password: crypt(pw)}); var actually_secure_password = crypt(password); - console.log(actually_secure_password); // $ SPURIOUS: Alert[js/clear-text-logging] + console.log(actually_secure_password); var user1 = {}; - user1.crypted_password = x(); // $ SPURIOUS: Source[js/clear-text-logging] - console.log(user1); // $ SPURIOUS: Alert[js/clear-text-logging] + user1.crypted_password = x(); + console.log(user1); var user2 = {}; user2.password = hash(); diff --git a/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll b/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll index 94619488f1a9..13861dfdd257 100644 --- a/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll +++ b/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll @@ -151,7 +151,8 @@ module HeuristicNames { */ string notSensitiveRegexp() { result = - "(?is).*([^\\w$.-]|redact|censor|obfuscate|hash|md5|sha|random|(? Date: Thu, 7 May 2026 17:21:13 +0100 Subject: [PATCH 16/16] Shared: Autoformat. --- .../codeql/concepts/internal/SensitiveDataHeuristics.qll | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll b/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll index 13861dfdd257..b2bda909e3ba 100644 --- a/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll +++ b/shared/concepts/codeql/concepts/internal/SensitiveDataHeuristics.qll @@ -151,8 +151,7 @@ module HeuristicNames { */ string notSensitiveRegexp() { result = - "(?is).*([^\\w$.-]|redact|censor|obfuscate|hash|md5|sha|random|(?