From 30cc5575a1370097593eb4b4146fb7e97ff573cc Mon Sep 17 00:00:00 2001
From: cx-jose-fernandes <172773198+cx-jose-fernandes@users.noreply.github.com>
Date: Mon, 2 Mar 2026 17:04:04 +0000
Subject: [PATCH 01/11] Fix AST-134899 - Add special characters support for
generic credential rule
---
engine/rules/ruledefine/generic_credential.go | 4 ++--
engine/rules/ruledefine/generic_credential_test.go | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/engine/rules/ruledefine/generic_credential.go b/engine/rules/ruledefine/generic_credential.go
index 27513163..2dc59801 100644
--- a/engine/rules/ruledefine/generic_credential.go
+++ b/engine/rules/ruledefine/generic_credential.go
@@ -16,7 +16,7 @@ var genericCredentialRegex = generateSemiGenericRegexIncludingXml([]string{
"passw(?:or)?d",
"secret",
"token",
-}, `[\w.=-]{10,150}|[a-z0-9][a-z0-9+/]{11,}={0,3}`, true).String()
+}, `[\w.=\-~?!:@]{10,150}|[a-z0-9][a-z0-9+/]{11,}={0,3}`, true).String()
func GenericCredential() *Rule {
return &Rule{
@@ -60,7 +60,7 @@ func GenericCredential() *Rule {
`|rapid|capital` + // common words containing "api"
`|[a-z0-9-]*?api[a-z0-9-]*?:jar:` + // Maven META-INF dependencies that contain "api" in the name.
// Auth
- `|author` +
+ `|\bauthor\b` +
`|X-MS-Exchange-Organization-Auth` + // email header
`|Authentication-Results` + // email header
// Credentials
diff --git a/engine/rules/ruledefine/generic_credential_test.go b/engine/rules/ruledefine/generic_credential_test.go
index 4449663e..799b045b 100644
--- a/engine/rules/ruledefine/generic_credential_test.go
+++ b/engine/rules/ruledefine/generic_credential_test.go
@@ -85,6 +85,7 @@ func TestGenericCredential(t *testing.T) {
" utils.GetEnvOrDefault(\"api_token\", \"dafa7817-e246-48f3-91a7-e87653d587b8\")",
// xml cases
"API_KEY\nAIzaSyATDL7Wz3Ze6BU31Yv3fVVth30Skyib29g",
+ "Authorization.ClientSecret: e55wsdasfsgs-sdsdas_2sdasjVM~ggadASaADASsad",
},
falsePositives: []string{
"issuerKeyHash=npmXsmT2_C1iJZ-SD7RuL8exZ=6ucd",
From 30a15d86d95146ac0b184134d52984ec725754d9 Mon Sep 17 00:00:00 2001
From: Jose Pinto Fernandes
<172773198+cx-jose-fernandes@users.noreply.github.com>
Date: Mon, 2 Mar 2026 17:13:36 +0000
Subject: [PATCH 02/11] Add unit test from generic_credential_test.go
---
.2ms.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.2ms.yml b/.2ms.yml
index 8e10e02d..d33acbc7 100644
--- a/.2ms.yml
+++ b/.2ms.yml
@@ -1383,3 +1383,4 @@ ignore-result:
- fcaf9a97bbcf85b33f88738b1e817e098e9c37e1 # unit test from e2e_test.go
- fe08c7c6c7f8bb715022aa4cd16ae1c69906ebba # test data from expectedReportWithValidation.json
- 5858849b35c4d0c6061a61c28c39e28b98844333 # unit test from rule_test.go
+- 93a8246bc5d82a9d47d8b683b4343b51dc3bb918 # unit test from generic_credential_test.go
From 35fcb7b7a17352334275fabbaf47cf3c8ed0e340 Mon Sep 17 00:00:00 2001
From: cx-jose-fernandes <172773198+cx-jose-fernandes@users.noreply.github.com>
Date: Mon, 2 Mar 2026 18:06:06 +0000
Subject: [PATCH 03/11] Remove : from the generic rule
---
engine/rules/ruledefine/generic_credential.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/engine/rules/ruledefine/generic_credential.go b/engine/rules/ruledefine/generic_credential.go
index 2dc59801..d1b78cca 100644
--- a/engine/rules/ruledefine/generic_credential.go
+++ b/engine/rules/ruledefine/generic_credential.go
@@ -16,7 +16,7 @@ var genericCredentialRegex = generateSemiGenericRegexIncludingXml([]string{
"passw(?:or)?d",
"secret",
"token",
-}, `[\w.=\-~?!:@]{10,150}|[a-z0-9][a-z0-9+/]{11,}={0,3}`, true).String()
+}, `[\w.=\-~?!@]{10,150}|[a-z0-9][a-z0-9+/]{11,}={0,3}`, true).String()
func GenericCredential() *Rule {
return &Rule{
From bc6f54f0e651f53a99bc55e0b8d7ec732889d08f Mon Sep 17 00:00:00 2001
From: cx-jose-fernandes <172773198+cx-jose-fernandes@users.noreply.github.com>
Date: Mon, 2 Mar 2026 18:25:04 +0000
Subject: [PATCH 04/11] Fix the false positive
---
engine/rules/ruledefine/generic_credential.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/engine/rules/ruledefine/generic_credential.go b/engine/rules/ruledefine/generic_credential.go
index d1b78cca..7d901aa2 100644
--- a/engine/rules/ruledefine/generic_credential.go
+++ b/engine/rules/ruledefine/generic_credential.go
@@ -16,7 +16,7 @@ var genericCredentialRegex = generateSemiGenericRegexIncludingXml([]string{
"passw(?:or)?d",
"secret",
"token",
-}, `[\w.=\-~?!@]{10,150}|[a-z0-9][a-z0-9+/]{11,}={0,3}`, true).String()
+}, `[\w.=\-~?!:@]{10,150}|[a-z0-9][a-z0-9+/]{11,}={0,3}`, true).String()
func GenericCredential() *Rule {
return &Rule{
@@ -42,7 +42,7 @@ func GenericCredential() *Rule {
// NOTE: this is a goofy hack to get around the fact there golang's regex engine does not support positive lookaheads.
// Ideally we would want to ensure the secret contains both numbers and alphabetical characters, not just alphabetical characters.
Regexes: []string{
- regexp.MustCompile(`^[a-zA-Z_.-]+$`).String(),
+ regexp.MustCompile(`^[a-zA-Z_.-]+:?$`).String(),
},
},
{
From fe2d785c429aa8179ebfe68d411a73ea865e26aa Mon Sep 17 00:00:00 2001
From: cx-jose-fernandes <172773198+cx-jose-fernandes@users.noreply.github.com>
Date: Wed, 4 Mar 2026 15:29:03 +0000
Subject: [PATCH 05/11] Fixing swissknife FP AND FN
---
engine/rules/ruledefine/generic_credential.go | 6 ++++++
engine/rules/ruledefine/generic_credential_test.go | 9 +++++++++
2 files changed, 15 insertions(+)
diff --git a/engine/rules/ruledefine/generic_credential.go b/engine/rules/ruledefine/generic_credential.go
index 7d901aa2..1aebc7fe 100644
--- a/engine/rules/ruledefine/generic_credential.go
+++ b/engine/rules/ruledefine/generic_credential.go
@@ -94,6 +94,12 @@ func GenericCredential() *Rule {
// Empty variables capturing the next line (e.g., .env files)
`|(?-i:(?:[A-Z_]+=\n[A-Z_]+=|[a-z_]+=\n[a-z_]+=)(?:\n|\z))` +
`|(?-i:(?:[A-Z.]+=\n[A-Z.]+=|[a-z.]+=\n[a-z.]+=)(?:\n|\z))` +
+ // Code constant references (e.g. AnnotationWithConstants::INTEGER).
+ `|(?-i:\w+::[A-Z][A-Z0-9_]*)` +
+ // Encrypted key: ignore only when value also starts with "encrypted" (encrypted_xxx = encrypted_yyy), not when value is a real secret. Underscore after "encrypted" optional.
+ `|encrypted_?[a-f0-9]+_(?:key|iv)\s*=\s*encrypted_?` +
+ // Any secret in valid date/datetime format (e.g. ISO 8601: 2018-04-22T10:28:49.876Z) — not a credential
+ `|\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})?` +
`)`).String(),
},
StopWords: append(DefaultStopWords,
diff --git a/engine/rules/ruledefine/generic_credential_test.go b/engine/rules/ruledefine/generic_credential_test.go
index 799b045b..21ec3db0 100644
--- a/engine/rules/ruledefine/generic_credential_test.go
+++ b/engine/rules/ruledefine/generic_credential_test.go
@@ -86,6 +86,7 @@ func TestGenericCredential(t *testing.T) {
// xml cases
"API_KEY\nAIzaSyATDL7Wz3Ze6BU31Yv3fVVth30Skyib29g",
"Authorization.ClientSecret: e55wsdasfsgs-sdsdas_2sdasjVM~ggadASaADASsad",
+ "Authorization.ClientSecret: e55wsdasfsgs-sds::das_2sdasjVM~ggad?ASaAD!ASs@ad",
},
falsePositives: []string{
"issuerKeyHash=npmXsmT2_C1iJZ-SD7RuL8exZ=6ucd",
@@ -97,6 +98,14 @@ func TestGenericCredential(t *testing.T) {
"GOOGLE_APP_ID\n1:407966239993:ios:0d7534f14f8cfe19",
"\"a_b_key\": \"x-someval-127.0.0.1\",",
"KeyVaultSecretsUser: '62168719-64c5-453d-b4ef-b51d8b1ad44d'",
+ "maxAPIResponseBytes: tc.maxAPIBytes , maxTotalScanBytes: tc.maxTotalBytes,",
+ "SOME_KEY = AnnotationWithConstants::INTEGER",
+ "SOME_KEY = AnnotationWithConstants::TANTO_FAZ",
+ "encrypted_0dfb31adf922_key = encrypted_0dfb31adf922_iv=",
+ "AuthnInstant=2018-04-22T10:28:49.876Z",
+ "AuthnInstant=2018-04-22T10:28:49Z",
+ "AuthnInstant=2018-04-22T10:28:49+00:00",
+ "PasswordStorage::SECTION_DELIMITER",
},
},
}
From 85540cdc9acd30304a733a33e4799b1cf9c9adfc Mon Sep 17 00:00:00 2001
From: cx-jose-fernandes <172773198+cx-jose-fernandes@users.noreply.github.com>
Date: Wed, 4 Mar 2026 15:33:13 +0000
Subject: [PATCH 06/11] Fixing swissknife FP AND FN
---
engine/rules/ruledefine/generic_credential.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/engine/rules/ruledefine/generic_credential.go b/engine/rules/ruledefine/generic_credential.go
index 1aebc7fe..f7e0dc12 100644
--- a/engine/rules/ruledefine/generic_credential.go
+++ b/engine/rules/ruledefine/generic_credential.go
@@ -96,7 +96,7 @@ func GenericCredential() *Rule {
`|(?-i:(?:[A-Z.]+=\n[A-Z.]+=|[a-z.]+=\n[a-z.]+=)(?:\n|\z))` +
// Code constant references (e.g. AnnotationWithConstants::INTEGER).
`|(?-i:\w+::[A-Z][A-Z0-9_]*)` +
- // Encrypted key: ignore only when value also starts with "encrypted" (encrypted_xxx = encrypted_yyy), not when value is a real secret. Underscore after "encrypted" optional.
+ // Ignore only when value also starts with "encrypted" (encrypted_xxx = encrypted_yyy), not when value is a real secret.
`|encrypted_?[a-f0-9]+_(?:key|iv)\s*=\s*encrypted_?` +
// Any secret in valid date/datetime format (e.g. ISO 8601: 2018-04-22T10:28:49.876Z) — not a credential
`|\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})?` +
From 6c74d482791542e3e6a1c74b58994181bc1bb7b5 Mon Sep 17 00:00:00 2001
From: cx-jose-fernandes <172773198+cx-jose-fernandes@users.noreply.github.com>
Date: Wed, 4 Mar 2026 15:48:30 +0000
Subject: [PATCH 07/11] Fixing swissknife FP AND FN
---
.2ms.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.2ms.yml b/.2ms.yml
index d33acbc7..82614135 100644
--- a/.2ms.yml
+++ b/.2ms.yml
@@ -1384,3 +1384,4 @@ ignore-result:
- fe08c7c6c7f8bb715022aa4cd16ae1c69906ebba # test data from expectedReportWithValidation.json
- 5858849b35c4d0c6061a61c28c39e28b98844333 # unit test from rule_test.go
- 93a8246bc5d82a9d47d8b683b4343b51dc3bb918 # unit test from generic_credential_test.go
+- ce952993fb8d6762a1feb0a1860dd806e0a36d40 # unit test from generic_credential_test.go
From 44a6a18f2d460f74a43f0626cb3165dd1325bb04 Mon Sep 17 00:00:00 2001
From: cx-jose-fernandes <172773198+cx-jose-fernandes@users.noreply.github.com>
Date: Wed, 4 Mar 2026 15:57:23 +0000
Subject: [PATCH 08/11] Fixing swissknife FP AND FN
---
.2ms.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.2ms.yml b/.2ms.yml
index 82614135..b02d24ba 100644
--- a/.2ms.yml
+++ b/.2ms.yml
@@ -1385,3 +1385,4 @@ ignore-result:
- 5858849b35c4d0c6061a61c28c39e28b98844333 # unit test from rule_test.go
- 93a8246bc5d82a9d47d8b683b4343b51dc3bb918 # unit test from generic_credential_test.go
- ce952993fb8d6762a1feb0a1860dd806e0a36d40 # unit test from generic_credential_test.go
+- 0ee50cf76ca12b4b03bfb8f233527d846965ae8a # unit test from generic_credential_test.go (remove later)
\ No newline at end of file
From ae6ddd2d203118838726b62d51de90560ce15eaf Mon Sep 17 00:00:00 2001
From: cx-jose-fernandes <172773198+cx-jose-fernandes@users.noreply.github.com>
Date: Thu, 5 Mar 2026 09:35:36 +0000
Subject: [PATCH 09/11] Fixing swissknife FP AND FN
---
.2ms.yml | 3 +--
engine/rules/ruledefine/generic_credential.go | 2 --
engine/rules/ruledefine/generic_credential_test.go | 1 -
3 files changed, 1 insertion(+), 5 deletions(-)
diff --git a/.2ms.yml b/.2ms.yml
index b02d24ba..ca9e8712 100644
--- a/.2ms.yml
+++ b/.2ms.yml
@@ -1384,5 +1384,4 @@ ignore-result:
- fe08c7c6c7f8bb715022aa4cd16ae1c69906ebba # test data from expectedReportWithValidation.json
- 5858849b35c4d0c6061a61c28c39e28b98844333 # unit test from rule_test.go
- 93a8246bc5d82a9d47d8b683b4343b51dc3bb918 # unit test from generic_credential_test.go
-- ce952993fb8d6762a1feb0a1860dd806e0a36d40 # unit test from generic_credential_test.go
-- 0ee50cf76ca12b4b03bfb8f233527d846965ae8a # unit test from generic_credential_test.go (remove later)
\ No newline at end of file
+- ce952993fb8d6762a1feb0a1860dd806e0a36d40 # unit test from generic_credential_test.go
\ No newline at end of file
diff --git a/engine/rules/ruledefine/generic_credential.go b/engine/rules/ruledefine/generic_credential.go
index f7e0dc12..d28dacc0 100644
--- a/engine/rules/ruledefine/generic_credential.go
+++ b/engine/rules/ruledefine/generic_credential.go
@@ -96,8 +96,6 @@ func GenericCredential() *Rule {
`|(?-i:(?:[A-Z.]+=\n[A-Z.]+=|[a-z.]+=\n[a-z.]+=)(?:\n|\z))` +
// Code constant references (e.g. AnnotationWithConstants::INTEGER).
`|(?-i:\w+::[A-Z][A-Z0-9_]*)` +
- // Ignore only when value also starts with "encrypted" (encrypted_xxx = encrypted_yyy), not when value is a real secret.
- `|encrypted_?[a-f0-9]+_(?:key|iv)\s*=\s*encrypted_?` +
// Any secret in valid date/datetime format (e.g. ISO 8601: 2018-04-22T10:28:49.876Z) — not a credential
`|\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})?` +
`)`).String(),
diff --git a/engine/rules/ruledefine/generic_credential_test.go b/engine/rules/ruledefine/generic_credential_test.go
index 21ec3db0..eb0462bf 100644
--- a/engine/rules/ruledefine/generic_credential_test.go
+++ b/engine/rules/ruledefine/generic_credential_test.go
@@ -101,7 +101,6 @@ func TestGenericCredential(t *testing.T) {
"maxAPIResponseBytes: tc.maxAPIBytes , maxTotalScanBytes: tc.maxTotalBytes,",
"SOME_KEY = AnnotationWithConstants::INTEGER",
"SOME_KEY = AnnotationWithConstants::TANTO_FAZ",
- "encrypted_0dfb31adf922_key = encrypted_0dfb31adf922_iv=",
"AuthnInstant=2018-04-22T10:28:49.876Z",
"AuthnInstant=2018-04-22T10:28:49Z",
"AuthnInstant=2018-04-22T10:28:49+00:00",
From ff158ef8dc7b39b0b71f22a5e6494b8a278fbc6e Mon Sep 17 00:00:00 2001
From: cx-jose-fernandes <172773198+cx-jose-fernandes@users.noreply.github.com>
Date: Thu, 5 Mar 2026 10:50:11 +0000
Subject: [PATCH 10/11] Fixing swissknife FP AND FN
---
.2ms.yml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/.2ms.yml b/.2ms.yml
index ca9e8712..f35e5a56 100644
--- a/.2ms.yml
+++ b/.2ms.yml
@@ -1384,4 +1384,6 @@ ignore-result:
- fe08c7c6c7f8bb715022aa4cd16ae1c69906ebba # test data from expectedReportWithValidation.json
- 5858849b35c4d0c6061a61c28c39e28b98844333 # unit test from rule_test.go
- 93a8246bc5d82a9d47d8b683b4343b51dc3bb918 # unit test from generic_credential_test.go
-- ce952993fb8d6762a1feb0a1860dd806e0a36d40 # unit test from generic_credential_test.go
\ No newline at end of file
+- ce952993fb8d6762a1feb0a1860dd806e0a36d40 # unit test from generic_credential_test.go
+- 0ee50cf76ca12b4b03bfb8f233527d846965ae8a # unit test from generic_credential_test.go (remove later)
+- 1ab798f14ecce9ea8a9229803c33f06e0093306a # unit test from generic_credential_test.go (remove later)
\ No newline at end of file
From b7e3c0a84c65cd930950efa49bc6e112e96e0f1a Mon Sep 17 00:00:00 2001
From: cx-jose-fernandes <172773198+cx-jose-fernandes@users.noreply.github.com>
Date: Thu, 5 Mar 2026 10:54:26 +0000
Subject: [PATCH 11/11] Fixing swissknife FP AND FN
---
.2ms.yml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/.2ms.yml b/.2ms.yml
index f35e5a56..ab55d19d 100644
--- a/.2ms.yml
+++ b/.2ms.yml
@@ -1386,4 +1386,6 @@ ignore-result:
- 93a8246bc5d82a9d47d8b683b4343b51dc3bb918 # unit test from generic_credential_test.go
- ce952993fb8d6762a1feb0a1860dd806e0a36d40 # unit test from generic_credential_test.go
- 0ee50cf76ca12b4b03bfb8f233527d846965ae8a # unit test from generic_credential_test.go (remove later)
-- 1ab798f14ecce9ea8a9229803c33f06e0093306a # unit test from generic_credential_test.go (remove later)
\ No newline at end of file
+- 1ab798f14ecce9ea8a9229803c33f06e0093306a # unit test from generic_credential_test.go (remove later)
+- 4154ccf54f5d43a54103495dcf0e228353dc02f4 # unit test from generic_credential_test.go (remove later)
+- 783d3aa8f0e14f6d1527879bbcb3ae6195134b33 # unit test from generic_credential_test.go (remove later)
\ No newline at end of file