Просмотр исходного кода

Make config generation utils public (#1480)

* chore(generate): make utils public

* chore(generate): change validate log messages

* chore(generate): split functions into files

* chore(config): add warning for public funcs
Richard Gomez 1 год назад
Родитель
Сommit
bd81872eee
100 измененных файлов с 577 добавлено и 632 удалено
  1. 4 3
      cmd/generate/config/rules/adafruit.go
  2. 7 6
      cmd/generate/config/rules/adobe.go
  3. 2 1
      cmd/generate/config/rules/age.go
  4. 4 3
      cmd/generate/config/rules/airtable.go
  5. 4 3
      cmd/generate/config/rules/algolia.go
  6. 8 7
      cmd/generate/config/rules/alibaba.go
  7. 7 6
      cmd/generate/config/rules/asana.go
  8. 6 5
      cmd/generate/config/rules/atlassian.go
  9. 8 7
      cmd/generate/config/rules/authress.go
  10. 3 2
      cmd/generate/config/rules/aws.go
  11. 4 3
      cmd/generate/config/rules/beamer.go
  12. 7 6
      cmd/generate/config/rules/bitbucket.go
  13. 7 6
      cmd/generate/config/rules/bittrex.go
  14. 3 2
      cmd/generate/config/rules/clojars.go
  15. 7 6
      cmd/generate/config/rules/cloudflare.go
  16. 4 3
      cmd/generate/config/rules/codecov.go
  17. 6 5
      cmd/generate/config/rules/coinbase.go
  18. 7 6
      cmd/generate/config/rules/confluent.go
  19. 5 4
      cmd/generate/config/rules/contentful.go
  20. 4 3
      cmd/generate/config/rules/databricks.go
  21. 5 4
      cmd/generate/config/rules/datadog.go
  22. 4 3
      cmd/generate/config/rules/definednetworking.go
  23. 10 9
      cmd/generate/config/rules/digitalocean.go
  24. 10 9
      cmd/generate/config/rules/discord.go
  25. 3 2
      cmd/generate/config/rules/doppler.go
  26. 4 3
      cmd/generate/config/rules/droneci.go
  27. 6 5
      cmd/generate/config/rules/dropbox.go
  28. 3 2
      cmd/generate/config/rules/duffel.go
  29. 3 2
      cmd/generate/config/rules/dynatrace.go
  30. 5 4
      cmd/generate/config/rules/easypost.go
  31. 4 3
      cmd/generate/config/rules/etsy.go
  32. 8 7
      cmd/generate/config/rules/facebook.go
  33. 4 3
      cmd/generate/config/rules/fastly.go
  34. 7 6
      cmd/generate/config/rules/finicity.go
  35. 4 3
      cmd/generate/config/rules/finnhub.go
  36. 4 3
      cmd/generate/config/rules/flickr.go
  37. 7 6
      cmd/generate/config/rules/flutterwave.go
  38. 3 2
      cmd/generate/config/rules/frameio.go
  39. 4 3
      cmd/generate/config/rules/freshbooks.go
  40. 5 4
      cmd/generate/config/rules/gcp.go
  41. 5 4
      cmd/generate/config/rules/generic.go
  42. 12 11
      cmd/generate/config/rules/github.go
  43. 7 6
      cmd/generate/config/rules/gitlab.go
  44. 6 5
      cmd/generate/config/rules/gitter.go
  45. 4 3
      cmd/generate/config/rules/gocardless.go
  46. 14 13
      cmd/generate/config/rules/grafana.go
  47. 5 4
      cmd/generate/config/rules/harness.go
  48. 5 4
      cmd/generate/config/rules/hashicorp.go
  49. 3 2
      cmd/generate/config/rules/heroku.go
  50. 3 2
      cmd/generate/config/rules/hubspot.go
  51. 3 2
      cmd/generate/config/rules/huggingface.go
  52. 4 3
      cmd/generate/config/rules/infracost.go
  53. 4 3
      cmd/generate/config/rules/intercom.go
  54. 5 4
      cmd/generate/config/rules/intra42.go
  55. 10 9
      cmd/generate/config/rules/jfrog.go
  56. 4 3
      cmd/generate/config/rules/jwt.go
  57. 6 5
      cmd/generate/config/rules/kraken.go
  58. 5 4
      cmd/generate/config/rules/kubernetes.go
  59. 7 6
      cmd/generate/config/rules/kucoin.go
  60. 4 3
      cmd/generate/config/rules/launchdarkly.go
  61. 6 5
      cmd/generate/config/rules/linear.go
  62. 9 8
      cmd/generate/config/rules/linkedin.go
  63. 7 6
      cmd/generate/config/rules/lob.go
  64. 4 3
      cmd/generate/config/rules/mailchimp.go
  65. 10 9
      cmd/generate/config/rules/mailgun.go
  66. 4 3
      cmd/generate/config/rules/mapbox.go
  67. 4 3
      cmd/generate/config/rules/mattermost.go
  68. 10 9
      cmd/generate/config/rules/messagebird.go
  69. 5 4
      cmd/generate/config/rules/netlify.go
  70. 14 13
      cmd/generate/config/rules/newrelic.go
  71. 4 3
      cmd/generate/config/rules/npm.go
  72. 5 4
      cmd/generate/config/rules/nytimes.go
  73. 5 4
      cmd/generate/config/rules/okta.go
  74. 4 3
      cmd/generate/config/rules/openai.go
  75. 2 1
      cmd/generate/config/rules/openshift.go
  76. 11 10
      cmd/generate/config/rules/plaid.go
  77. 16 15
      cmd/generate/config/rules/planetscale.go
  78. 4 3
      cmd/generate/config/rules/postman.go
  79. 4 3
      cmd/generate/config/rules/prefect.go
  80. 2 1
      cmd/generate/config/rules/privatekey.go
  81. 4 3
      cmd/generate/config/rules/pulumi.go
  82. 4 3
      cmd/generate/config/rules/pypi.go
  83. 6 5
      cmd/generate/config/rules/rapidapi.go
  84. 4 3
      cmd/generate/config/rules/readme.go
  85. 4 3
      cmd/generate/config/rules/rubygems.go
  86. 0 154
      cmd/generate/config/rules/rule.go
  87. 4 3
      cmd/generate/config/rules/scalingo.go
  88. 7 6
      cmd/generate/config/rules/sendbird.go
  89. 4 3
      cmd/generate/config/rules/sendgrid.go
  90. 4 3
      cmd/generate/config/rules/sendinblue.go
  91. 4 3
      cmd/generate/config/rules/sentry.go
  92. 5 4
      cmd/generate/config/rules/shippo.go
  93. 9 8
      cmd/generate/config/rules/shopify.go
  94. 4 3
      cmd/generate/config/rules/sidekiq.go
  95. 31 30
      cmd/generate/config/rules/slack.go
  96. 3 2
      cmd/generate/config/rules/snyk.go
  97. 7 6
      cmd/generate/config/rules/square.go
  98. 4 3
      cmd/generate/config/rules/squarespace.go
  99. 5 4
      cmd/generate/config/rules/stripe.go
  100. 8 7
      cmd/generate/config/rules/sumologic.go

+ 4 - 3
cmd/generate/config/rules/adafruit.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,13 +11,13 @@ func AdafruitAPIKey() *config.Rule {
 	r := config.Rule{
 		Description: "Identified a potential Adafruit API Key, which could lead to unauthorized access to Adafruit services and sensitive data exposure.",
 		RuleID:      "adafruit-api-key",
-		Regex:       generateSemiGenericRegex([]string{"adafruit"}, alphaNumericExtendedShort("32"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"adafruit"}, utils.AlphaNumericExtendedShort("32"), true),
 		Keywords:    []string{"adafruit"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("adafruit", secrets.NewSecret(alphaNumericExtendedShort("32"))),
+		utils.GenerateSampleSecret("adafruit", secrets.NewSecret(utils.AlphaNumericExtendedShort("32"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 7 - 6
cmd/generate/config/rules/adobe.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,15 +11,15 @@ func AdobeClientID() *config.Rule {
 	r := config.Rule{
 		Description: "Detected a pattern that resembles an Adobe OAuth Web Client ID, posing a risk of compromised Adobe integrations and data breaches.",
 		RuleID:      "adobe-client-id",
-		Regex:       generateSemiGenericRegex([]string{"adobe"}, hex("32"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"adobe"}, utils.Hex("32"), true),
 		Keywords:    []string{"adobe"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("adobe", secrets.NewSecret(hex("32"))),
+		utils.GenerateSampleSecret("adobe", secrets.NewSecret(utils.Hex("32"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func AdobeClientSecret() *config.Rule {
@@ -26,13 +27,13 @@ func AdobeClientSecret() *config.Rule {
 	r := config.Rule{
 		Description: "Discovered a potential Adobe Client Secret, which, if exposed, could allow unauthorized Adobe service access and data manipulation.",
 		RuleID:      "adobe-client-secret",
-		Regex:       generateUniqueTokenRegex(`(p8e-)(?i)[a-z0-9]{32}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`(p8e-)(?i)[a-z0-9]{32}`, true),
 		Keywords:    []string{"p8e-"},
 	}
 
 	// validate
 	tps := []string{
-		"adobeClient := \"p8e-" + secrets.NewSecret(hex("32")) + "\"",
+		"adobeClient := \"p8e-" + secrets.NewSecret(utils.Hex("32")) + "\"",
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 2 - 1
cmd/generate/config/rules/age.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/config"
@@ -19,5 +20,5 @@ func AgeSecretKey() *config.Rule {
 	tps := []string{
 		`apiKey := "AGE-SECRET-KEY-1QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ`, // gitleaks:allow
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/airtable.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,13 +11,13 @@ func Airtable() *config.Rule {
 	r := config.Rule{
 		Description: "Uncovered a possible Airtable API Key, potentially compromising database access and leading to data leakage or alteration.",
 		RuleID:      "airtable-api-key",
-		Regex:       generateSemiGenericRegex([]string{"airtable"}, alphaNumeric("17"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"airtable"}, utils.AlphaNumeric("17"), true),
 		Keywords:    []string{"airtable"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("airtable", secrets.NewSecret(alphaNumeric("17"))),
+		utils.GenerateSampleSecret("airtable", secrets.NewSecret(utils.AlphaNumeric("17"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/algolia.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,13 +11,13 @@ func AlgoliaApiKey() *config.Rule {
 	r := config.Rule{
 		Description: "Identified an Algolia API Key, which could result in unauthorized search operations and data exposure on Algolia-managed platforms.",
 		RuleID:      "algolia-api-key",
-		Regex:       generateSemiGenericRegex([]string{"algolia"}, `[a-z0-9]{32}`, true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"algolia"}, `[a-z0-9]{32}`, true),
 		Keywords:    []string{"algolia"},
 	}
 
 	// validate
 	tps := []string{
-		"algolia_key := " + secrets.NewSecret(hex("32")),
+		"algolia_key := " + secrets.NewSecret(utils.Hex("32")),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 8 - 7
cmd/generate/config/rules/alibaba.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,15 +11,15 @@ func AlibabaAccessKey() *config.Rule {
 	r := config.Rule{
 		Description: "Detected an Alibaba Cloud AccessKey ID, posing a risk of unauthorized cloud resource access and potential data compromise.",
 		RuleID:      "alibaba-access-key-id",
-		Regex:       generateUniqueTokenRegex(`(LTAI)(?i)[a-z0-9]{20}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`(LTAI)(?i)[a-z0-9]{20}`, true),
 		Keywords:    []string{"LTAI"},
 	}
 
 	// validate
 	tps := []string{
-		"alibabaKey := \"LTAI" + secrets.NewSecret(hex("20")) + "\"",
+		"alibabaKey := \"LTAI" + secrets.NewSecret(utils.Hex("20")) + "\"",
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 // TODO
@@ -27,15 +28,15 @@ func AlibabaSecretKey() *config.Rule {
 	r := config.Rule{
 		Description: "Discovered a potential Alibaba Cloud Secret Key, potentially allowing unauthorized operations and data access within Alibaba Cloud.",
 		RuleID:      "alibaba-secret-key",
-		Regex: generateSemiGenericRegex([]string{"alibaba"},
-			alphaNumeric("30"), true),
+		Regex: utils.GenerateSemiGenericRegex([]string{"alibaba"},
+			utils.AlphaNumeric("30"), true),
 
 		Keywords: []string{"alibaba"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("alibaba", secrets.NewSecret(alphaNumeric("30"))),
+		utils.GenerateSampleSecret("alibaba", secrets.NewSecret(utils.AlphaNumeric("30"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 7 - 6
cmd/generate/config/rules/asana.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,15 +11,15 @@ func AsanaClientID() *config.Rule {
 	r := config.Rule{
 		Description: "Discovered a potential Asana Client ID, risking unauthorized access to Asana projects and sensitive task information.",
 		RuleID:      "asana-client-id",
-		Regex:       generateSemiGenericRegex([]string{"asana"}, numeric("16"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"asana"}, utils.Numeric("16"), true),
 		Keywords:    []string{"asana"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("asana", secrets.NewSecret(numeric("16"))),
+		utils.GenerateSampleSecret("asana", secrets.NewSecret(utils.Numeric("16"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func AsanaClientSecret() *config.Rule {
@@ -26,14 +27,14 @@ func AsanaClientSecret() *config.Rule {
 	r := config.Rule{
 		Description: "Identified an Asana Client Secret, which could lead to compromised project management integrity and unauthorized access.",
 		RuleID:      "asana-client-secret",
-		Regex:       generateSemiGenericRegex([]string{"asana"}, alphaNumeric("32"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"asana"}, utils.AlphaNumeric("32"), true),
 
 		Keywords: []string{"asana"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("asana", secrets.NewSecret(alphaNumeric("32"))),
+		utils.GenerateSampleSecret("asana", secrets.NewSecret(utils.AlphaNumeric("32"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 6 - 5
cmd/generate/config/rules/atlassian.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,15 +11,15 @@ func Atlassian() *config.Rule {
 	r := config.Rule{
 		Description: "Detected an Atlassian API token, posing a threat to project management and collaboration tool security and data confidentiality.",
 		RuleID:      "atlassian-api-token",
-		Regex: generateSemiGenericRegex([]string{
-			"atlassian", "confluence", "jira"}, alphaNumeric("24"), true),
+		Regex: utils.GenerateSemiGenericRegex([]string{
+			"atlassian", "confluence", "jira"}, utils.AlphaNumeric("24"), true),
 		Keywords: []string{"atlassian", "confluence", "jira"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("atlassian", secrets.NewSecret(alphaNumeric("24"))),
-		generateSampleSecret("confluence", secrets.NewSecret(alphaNumeric("24"))),
+		utils.GenerateSampleSecret("atlassian", secrets.NewSecret(utils.AlphaNumeric("24"))),
+		utils.GenerateSampleSecret("confluence", secrets.NewSecret(utils.AlphaNumeric("24"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 8 - 7
cmd/generate/config/rules/authress.go

@@ -2,6 +2,7 @@ package rules
 
 import (
 	"fmt"
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
@@ -13,19 +14,19 @@ func Authress() *config.Rule {
 	r := config.Rule{
 		Description: "Uncovered a possible Authress Service Client Access Key, which may compromise access control services and sensitive data.",
 		RuleID:      "authress-service-client-access-key",
-		Regex:       generateUniqueTokenRegex(`(?:sc|ext|scauth|authress)_[a-z0-9]{5,30}\.[a-z0-9]{4,6}\.acc[_-][a-z0-9-]{10,32}\.[a-z0-9+/_=-]{30,120}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`(?:sc|ext|scauth|authress)_[a-z0-9]{5,30}\.[a-z0-9]{4,6}\.acc[_-][a-z0-9-]{10,32}\.[a-z0-9+/_=-]{30,120}`, true),
 		Keywords:    []string{"sc_", "ext_", "scauth_", "authress_"},
 	}
 
 	// validate
 	// https://authress.io/knowledge-base/docs/authorization/service-clients/secrets-scanning/#1-detection
-	service_client_id := "sc_" + alphaNumeric("10")
-	access_key_id := alphaNumeric("4")
-	account_id := "acc_" + alphaNumeric("10")
-	signature_key := alphaNumericExtendedShort("40")
+	service_client_id := "sc_" + utils.AlphaNumeric("10")
+	access_key_id := utils.AlphaNumeric("4")
+	account_id := "acc_" + utils.AlphaNumeric("10")
+	signature_key := utils.AlphaNumericExtendedShort("40")
 
 	tps := []string{
-		generateSampleSecret("authress", secrets.NewSecret(fmt.Sprintf(`%s\.%s\.%s\.%s`, service_client_id, access_key_id, account_id, signature_key))),
+		utils.GenerateSampleSecret("authress", secrets.NewSecret(fmt.Sprintf(`%s\.%s\.%s\.%s`, service_client_id, access_key_id, account_id, signature_key))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 3 - 2
cmd/generate/config/rules/aws.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/config"
@@ -22,6 +23,6 @@ func AWS() *config.Rule {
 	}
 
 	// validate
-	tps := []string{generateSampleSecret("AWS", "AKIALALEMEL33243OLIB")} // gitleaks:allow
-	return validate(r, tps, nil)
+	tps := []string{utils.GenerateSampleSecret("AWS", "AKIALALEMEL33243OLIB")} // gitleaks:allow
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/beamer.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,14 +11,14 @@ func Beamer() *config.Rule {
 	r := config.Rule{
 		Description: "Detected a Beamer API token, potentially compromising content management and exposing sensitive notifications and updates.",
 		RuleID:      "beamer-api-token",
-		Regex: generateSemiGenericRegex([]string{"beamer"},
+		Regex: utils.GenerateSemiGenericRegex([]string{"beamer"},
 			`b_[a-z0-9=_\-]{44}`, true),
 		Keywords: []string{"beamer"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("beamer", "b_"+secrets.NewSecret(alphaNumericExtended("44"))),
+		utils.GenerateSampleSecret("beamer", "b_"+secrets.NewSecret(utils.AlphaNumericExtended("44"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 7 - 6
cmd/generate/config/rules/bitbucket.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,15 +11,15 @@ func BitBucketClientID() *config.Rule {
 	r := config.Rule{
 		Description: "Discovered a potential Bitbucket Client ID, risking unauthorized repository access and potential codebase exposure.",
 		RuleID:      "bitbucket-client-id",
-		Regex:       generateSemiGenericRegex([]string{"bitbucket"}, alphaNumeric("32"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"bitbucket"}, utils.AlphaNumeric("32"), true),
 		Keywords:    []string{"bitbucket"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("bitbucket", secrets.NewSecret(alphaNumeric("32"))),
+		utils.GenerateSampleSecret("bitbucket", secrets.NewSecret(utils.AlphaNumeric("32"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func BitBucketClientSecret() *config.Rule {
@@ -26,14 +27,14 @@ func BitBucketClientSecret() *config.Rule {
 	r := config.Rule{
 		Description: "Discovered a potential Bitbucket Client Secret, posing a risk of compromised code repositories and unauthorized access.",
 		RuleID:      "bitbucket-client-secret",
-		Regex:       generateSemiGenericRegex([]string{"bitbucket"}, alphaNumericExtended("64"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"bitbucket"}, utils.AlphaNumericExtended("64"), true),
 
 		Keywords: []string{"bitbucket"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("bitbucket", secrets.NewSecret(alphaNumeric("64"))),
+		utils.GenerateSampleSecret("bitbucket", secrets.NewSecret(utils.AlphaNumeric("64"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 7 - 6
cmd/generate/config/rules/bittrex.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,15 +11,15 @@ func BittrexAccessKey() *config.Rule {
 	r := config.Rule{
 		Description: "Identified a Bittrex Access Key, which could lead to unauthorized access to cryptocurrency trading accounts and financial loss.",
 		RuleID:      "bittrex-access-key",
-		Regex:       generateSemiGenericRegex([]string{"bittrex"}, alphaNumeric("32"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"bittrex"}, utils.AlphaNumeric("32"), true),
 		Keywords:    []string{"bittrex"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("bittrex", secrets.NewSecret(alphaNumeric("32"))),
+		utils.GenerateSampleSecret("bittrex", secrets.NewSecret(utils.AlphaNumeric("32"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func BittrexSecretKey() *config.Rule {
@@ -26,14 +27,14 @@ func BittrexSecretKey() *config.Rule {
 	r := config.Rule{
 		Description: "Detected a Bittrex Secret Key, potentially compromising cryptocurrency transactions and financial security.",
 		RuleID:      "bittrex-secret-key",
-		Regex:       generateSemiGenericRegex([]string{"bittrex"}, alphaNumeric("32"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"bittrex"}, utils.AlphaNumeric("32"), true),
 
 		Keywords: []string{"bittrex"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("bittrex", secrets.NewSecret(alphaNumeric("32"))),
+		utils.GenerateSampleSecret("bittrex", secrets.NewSecret(utils.AlphaNumeric("32"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 3 - 2
cmd/generate/config/rules/clojars.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
@@ -18,7 +19,7 @@ func Clojars() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("clojars", "CLOJARS_"+secrets.NewSecret(alphaNumeric("60"))),
+		utils.GenerateSampleSecret("clojars", "CLOJARS_"+secrets.NewSecret(utils.AlphaNumeric("60"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 7 - 6
cmd/generate/config/rules/cloudflare.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
 
@@ -28,7 +29,7 @@ func CloudflareGlobalAPIKey() *config.Rule {
 	r := config.Rule{
 		Description: "Detected a Cloudflare Global API Key, potentially compromising cloud application deployments and operational security.",
 		RuleID:      "cloudflare-global-api-key",
-		Regex:       generateSemiGenericRegex(identifiers, hex("37"), true),
+		Regex:       utils.GenerateSemiGenericRegex(identifiers, utils.Hex("37"), true),
 
 		Keywords: identifiers,
 	}
@@ -37,7 +38,7 @@ func CloudflareGlobalAPIKey() *config.Rule {
 	tps := global_keys
 	fps := append(api_keys, origin_ca_keys...)
 
-	return validate(r, tps, fps)
+	return utils.Validate(r, tps, fps)
 }
 
 func CloudflareAPIKey() *config.Rule {
@@ -45,7 +46,7 @@ func CloudflareAPIKey() *config.Rule {
 	r := config.Rule{
 		Description: "Detected a Cloudflare API Key, potentially compromising cloud application deployments and operational security.",
 		RuleID:      "cloudflare-api-key",
-		Regex:       generateSemiGenericRegex(identifiers, alphaNumericExtendedShort("40"), true),
+		Regex:       utils.GenerateSemiGenericRegex(identifiers, utils.AlphaNumericExtendedShort("40"), true),
 
 		Keywords: identifiers,
 	}
@@ -54,7 +55,7 @@ func CloudflareAPIKey() *config.Rule {
 	tps := api_keys
 	fps := append(global_keys, origin_ca_keys...)
 
-	return validate(r, tps, fps)
+	return utils.Validate(r, tps, fps)
 }
 
 func CloudflareOriginCAKey() *config.Rule {
@@ -63,7 +64,7 @@ func CloudflareOriginCAKey() *config.Rule {
 	r := config.Rule{
 		Description: "Detected a Cloudflare Origin CA Key, potentially compromising cloud application deployments and operational security.",
 		RuleID:      "cloudflare-origin-ca-key",
-		Regex:       generateUniqueTokenRegex(`v1\.0-`+hex("24")+"-"+hex("146"), false),
+		Regex:       utils.GenerateUniqueTokenRegex(`v1\.0-`+utils.Hex("24")+"-"+utils.Hex("146"), false),
 
 		Keywords: ca_identifiers,
 	}
@@ -72,5 +73,5 @@ func CloudflareOriginCAKey() *config.Rule {
 	tps := origin_ca_keys
 	fps := append(global_keys, api_keys...)
 
-	return validate(r, tps, fps)
+	return utils.Validate(r, tps, fps)
 }

+ 4 - 3
cmd/generate/config/rules/codecov.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func CodecovAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "codecov-access-token",
 		Description: "Found a pattern resembling a Codecov Access Token, posing a risk of unauthorized access to code coverage reports and sensitive data.",
-		Regex:       generateSemiGenericRegex([]string{"codecov"}, alphaNumeric("32"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"codecov"}, utils.AlphaNumeric("32"), true),
 		Keywords: []string{
 			"codecov",
 		},
@@ -18,7 +19,7 @@ func CodecovAccessToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("codecov", secrets.NewSecret(alphaNumeric("32"))),
+		utils.GenerateSampleSecret("codecov", secrets.NewSecret(utils.AlphaNumeric("32"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 6 - 5
cmd/generate/config/rules/coinbase.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,8 +11,8 @@ func CoinbaseAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "coinbase-access-token",
 		Description: "Detected a Coinbase Access Token, posing a risk of unauthorized access to cryptocurrency accounts and financial transactions.",
-		Regex: generateSemiGenericRegex([]string{"coinbase"},
-			alphaNumericExtendedShort("64"), true),
+		Regex: utils.GenerateSemiGenericRegex([]string{"coinbase"},
+			utils.AlphaNumericExtendedShort("64"), true),
 		Keywords: []string{
 			"coinbase",
 		},
@@ -19,8 +20,8 @@ func CoinbaseAccessToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("coinbase",
-			secrets.NewSecret(alphaNumericExtendedShort("64"))),
+		utils.GenerateSampleSecret("coinbase",
+			secrets.NewSecret(utils.AlphaNumericExtendedShort("64"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 7 - 6
cmd/generate/config/rules/confluent.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func ConfluentSecretKey() *config.Rule {
 	r := config.Rule{
 		RuleID:      "confluent-secret-key",
 		Description: "Found a Confluent Secret Key, potentially risking unauthorized operations and data access within Confluent services.",
-		Regex:       generateSemiGenericRegex([]string{"confluent"}, alphaNumeric("64"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"confluent"}, utils.AlphaNumeric("64"), true),
 		Keywords: []string{
 			"confluent",
 		},
@@ -18,9 +19,9 @@ func ConfluentSecretKey() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("confluent", secrets.NewSecret(alphaNumeric("64"))),
+		utils.GenerateSampleSecret("confluent", secrets.NewSecret(utils.AlphaNumeric("64"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func ConfluentAccessToken() *config.Rule {
@@ -28,7 +29,7 @@ func ConfluentAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "confluent-access-token",
 		Description: "Identified a Confluent Access Token, which could compromise access to streaming data platforms and sensitive data flow.",
-		Regex:       generateSemiGenericRegex([]string{"confluent"}, alphaNumeric("16"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"confluent"}, utils.AlphaNumeric("16"), true),
 
 		Keywords: []string{
 			"confluent",
@@ -37,7 +38,7 @@ func ConfluentAccessToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("confluent", secrets.NewSecret(alphaNumeric("16"))),
+		utils.GenerateSampleSecret("confluent", secrets.NewSecret(utils.AlphaNumeric("16"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 5 - 4
cmd/generate/config/rules/contentful.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,14 +11,14 @@ func Contentful() *config.Rule {
 	r := config.Rule{
 		Description: "Discovered a Contentful delivery API token, posing a risk to content management systems and data integrity.",
 		RuleID:      "contentful-delivery-api-token",
-		Regex: generateSemiGenericRegex([]string{"contentful"},
-			alphaNumericExtended("43"), true),
+		Regex: utils.GenerateSemiGenericRegex([]string{"contentful"},
+			utils.AlphaNumericExtended("43"), true),
 		Keywords: []string{"contentful"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("contentful", secrets.NewSecret(alphaNumeric("43"))),
+		utils.GenerateSampleSecret("contentful", secrets.NewSecret(utils.AlphaNumeric("43"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/databricks.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,13 +11,13 @@ func Databricks() *config.Rule {
 	r := config.Rule{
 		Description: "Uncovered a Databricks API token, which may compromise big data analytics platforms and sensitive data processing.",
 		RuleID:      "databricks-api-token",
-		Regex:       generateUniqueTokenRegex(`dapi[a-h0-9]{32}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`dapi[a-h0-9]{32}`, true),
 		Keywords:    []string{"dapi"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("databricks", "dapi"+secrets.NewSecret(hex("32"))),
+		utils.GenerateSampleSecret("databricks", "dapi"+secrets.NewSecret(utils.Hex("32"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 5 - 4
cmd/generate/config/rules/datadog.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,8 +11,8 @@ func DatadogtokenAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "datadog-access-token",
 		Description: "Detected a Datadog Access Token, potentially risking monitoring and analytics data exposure and manipulation.",
-		Regex: generateSemiGenericRegex([]string{"datadog"},
-			alphaNumeric("40"), true),
+		Regex: utils.GenerateSemiGenericRegex([]string{"datadog"},
+			utils.AlphaNumeric("40"), true),
 		Keywords: []string{
 			"datadog",
 		},
@@ -19,7 +20,7 @@ func DatadogtokenAccessToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("datadog", secrets.NewSecret(alphaNumeric("40"))),
+		utils.GenerateSampleSecret("datadog", secrets.NewSecret(utils.AlphaNumeric("40"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/definednetworking.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -15,7 +16,7 @@ func DefinedNetworkingAPIToken() *config.Rule {
 		RuleID: "defined-networking-api-token",
 
 		// Regex used for detecting secrets. See regex section below for more details
-		Regex: generateSemiGenericRegex([]string{"dnkey"}, `dnkey-[a-z0-9=_\-]{26}-[a-z0-9=_\-]{52}`, true),
+		Regex: utils.GenerateSemiGenericRegex([]string{"dnkey"}, `dnkey-[a-z0-9=_\-]{26}-[a-z0-9=_\-]{52}`, true),
 
 		// Keywords used for string matching on fragments (think of this as a prefilter)
 		Keywords: []string{"dnkey"},
@@ -23,7 +24,7 @@ func DefinedNetworkingAPIToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("dnkey", "dnkey-"+secrets.NewSecret(alphaNumericExtended("26"))+"-"+secrets.NewSecret(alphaNumericExtended("52"))),
+		utils.GenerateSampleSecret("dnkey", "dnkey-"+secrets.NewSecret(utils.AlphaNumericExtended("26"))+"-"+secrets.NewSecret(utils.AlphaNumericExtended("52"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 10 - 9
cmd/generate/config/rules/digitalocean.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -9,14 +10,14 @@ func DigitalOceanPAT() *config.Rule {
 	r := config.Rule{
 		Description: "Discovered a DigitalOcean Personal Access Token, posing a threat to cloud infrastructure security and data privacy.",
 		RuleID:      "digitalocean-pat",
-		Regex:       generateUniqueTokenRegex(`dop_v1_[a-f0-9]{64}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`dop_v1_[a-f0-9]{64}`, true),
 		Keywords:    []string{"dop_v1_"},
 	}
 
 	tps := []string{
-		generateSampleSecret("do", "dop_v1_"+secrets.NewSecret(hex("64"))),
+		utils.GenerateSampleSecret("do", "dop_v1_"+secrets.NewSecret(utils.Hex("64"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func DigitalOceanOAuthToken() *config.Rule {
@@ -24,14 +25,14 @@ func DigitalOceanOAuthToken() *config.Rule {
 		Description: "Found a DigitalOcean OAuth Access Token, risking unauthorized cloud resource access and data compromise.",
 		RuleID:      "digitalocean-access-token",
 
-		Regex:    generateUniqueTokenRegex(`doo_v1_[a-f0-9]{64}`, true),
+		Regex:    utils.GenerateUniqueTokenRegex(`doo_v1_[a-f0-9]{64}`, true),
 		Keywords: []string{"doo_v1_"},
 	}
 
 	tps := []string{
-		generateSampleSecret("do", "doo_v1_"+secrets.NewSecret(hex("64"))),
+		utils.GenerateSampleSecret("do", "doo_v1_"+secrets.NewSecret(utils.Hex("64"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func DigitalOceanRefreshToken() *config.Rule {
@@ -39,12 +40,12 @@ func DigitalOceanRefreshToken() *config.Rule {
 		Description: "Uncovered a DigitalOcean OAuth Refresh Token, which could allow prolonged unauthorized access and resource manipulation.",
 		RuleID:      "digitalocean-refresh-token",
 
-		Regex:    generateUniqueTokenRegex(`dor_v1_[a-f0-9]{64}`, true),
+		Regex:    utils.GenerateUniqueTokenRegex(`dor_v1_[a-f0-9]{64}`, true),
 		Keywords: []string{"dor_v1_"},
 	}
 
 	tps := []string{
-		generateSampleSecret("do", "dor_v1_"+secrets.NewSecret(hex("64"))),
+		utils.GenerateSampleSecret("do", "dor_v1_"+secrets.NewSecret(utils.Hex("64"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 10 - 9
cmd/generate/config/rules/discord.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,15 +11,15 @@ func DiscordAPIToken() *config.Rule {
 	r := config.Rule{
 		Description: "Detected a Discord API key, potentially compromising communication channels and user data privacy on Discord.",
 		RuleID:      "discord-api-token",
-		Regex:       generateSemiGenericRegex([]string{"discord"}, hex("64"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"discord"}, utils.Hex("64"), true),
 		Keywords:    []string{"discord"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("discord", secrets.NewSecret(hex("64"))),
+		utils.GenerateSampleSecret("discord", secrets.NewSecret(utils.Hex("64"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func DiscordClientID() *config.Rule {
@@ -26,15 +27,15 @@ func DiscordClientID() *config.Rule {
 	r := config.Rule{
 		Description: "Identified a Discord client ID, which may lead to unauthorized integrations and data exposure in Discord applications.",
 		RuleID:      "discord-client-id",
-		Regex:       generateSemiGenericRegex([]string{"discord"}, numeric("18"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"discord"}, utils.Numeric("18"), true),
 		Keywords:    []string{"discord"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("discord", secrets.NewSecret(numeric("18"))),
+		utils.GenerateSampleSecret("discord", secrets.NewSecret(utils.Numeric("18"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func DiscordClientSecret() *config.Rule {
@@ -42,13 +43,13 @@ func DiscordClientSecret() *config.Rule {
 	r := config.Rule{
 		Description: "Discovered a potential Discord client secret, risking compromised Discord bot integrations and data leaks.",
 		RuleID:      "discord-client-secret",
-		Regex:       generateSemiGenericRegex([]string{"discord"}, alphaNumericExtended("32"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"discord"}, utils.AlphaNumericExtended("32"), true),
 		Keywords:    []string{"discord"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("discord", secrets.NewSecret(numeric("32"))),
+		utils.GenerateSampleSecret("discord", secrets.NewSecret(utils.Numeric("32"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 3 - 2
cmd/generate/config/rules/doppler.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
@@ -18,9 +19,9 @@ func Doppler() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("doppler", "dp.pt."+secrets.NewSecret(alphaNumeric("43"))),
+		utils.GenerateSampleSecret("doppler", "dp.pt."+secrets.NewSecret(utils.AlphaNumeric("43"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 // TODO add additional doppler formats:

+ 4 - 3
cmd/generate/config/rules/droneci.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func DroneciAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "droneci-access-token",
 		Description: "Detected a Droneci Access Token, potentially compromising continuous integration and deployment workflows.",
-		Regex:       generateSemiGenericRegex([]string{"droneci"}, alphaNumeric("32"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"droneci"}, utils.AlphaNumeric("32"), true),
 
 		Keywords: []string{
 			"droneci",
@@ -19,7 +20,7 @@ func DroneciAccessToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("droneci", secrets.NewSecret(alphaNumeric("32"))),
+		utils.GenerateSampleSecret("droneci", secrets.NewSecret(utils.AlphaNumeric("32"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 6 - 5
cmd/generate/config/rules/dropbox.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,16 +11,16 @@ func DropBoxAPISecret() *config.Rule {
 	r := config.Rule{
 		Description: "Identified a Dropbox API secret, which could lead to unauthorized file access and data breaches in Dropbox storage.",
 		RuleID:      "dropbox-api-token",
-		Regex:       generateSemiGenericRegex([]string{"dropbox"}, alphaNumeric("15"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"dropbox"}, utils.AlphaNumeric("15"), true),
 
 		Keywords: []string{"dropbox"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("dropbox", secrets.NewSecret(alphaNumeric("15"))),
+		utils.GenerateSampleSecret("dropbox", secrets.NewSecret(utils.AlphaNumeric("15"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func DropBoxShortLivedAPIToken() *config.Rule {
@@ -27,7 +28,7 @@ func DropBoxShortLivedAPIToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "dropbox-short-lived-api-token",
 		Description: "Discovered a Dropbox short-lived API token, posing a risk of temporary but potentially harmful data access and manipulation.",
-		Regex:       generateSemiGenericRegex([]string{"dropbox"}, `sl\.[a-z0-9\-=_]{135}`, true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"dropbox"}, `sl\.[a-z0-9\-=_]{135}`, true),
 		Keywords:    []string{"dropbox"},
 	}
 
@@ -40,7 +41,7 @@ func DropBoxLongLivedAPIToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "dropbox-long-lived-api-token",
 		Description: "Found a Dropbox long-lived API token, risking prolonged unauthorized access to cloud storage and sensitive data.",
-		Regex:       generateSemiGenericRegex([]string{"dropbox"}, `[a-z0-9]{11}(AAAAAAAAAA)[a-z0-9\-_=]{43}`, true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"dropbox"}, `[a-z0-9]{11}(AAAAAAAAAA)[a-z0-9\-_=]{43}`, true),
 		Keywords:    []string{"dropbox"},
 	}
 

+ 3 - 2
cmd/generate/config/rules/duffel.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
@@ -18,7 +19,7 @@ func Duffel() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("duffel", "duffel_test_"+secrets.NewSecret(alphaNumericExtended("43"))),
+		utils.GenerateSampleSecret("duffel", "duffel_test_"+secrets.NewSecret(utils.AlphaNumericExtended("43"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 3 - 2
cmd/generate/config/rules/dynatrace.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
@@ -18,7 +19,7 @@ func Dynatrace() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("dynatrace", "dt0c01."+secrets.NewSecret(alphaNumeric("24"))+"."+secrets.NewSecret(alphaNumeric("64"))),
+		utils.GenerateSampleSecret("dynatrace", "dt0c01."+secrets.NewSecret(utils.AlphaNumeric("24"))+"."+secrets.NewSecret(utils.AlphaNumeric("64"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 5 - 4
cmd/generate/config/rules/easypost.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
@@ -18,9 +19,9 @@ func EasyPost() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("EZAK", "EZAK"+secrets.NewSecret(alphaNumeric("54"))),
+		utils.GenerateSampleSecret("EZAK", "EZAK"+secrets.NewSecret(utils.AlphaNumeric("54"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func EasyPostTestAPI() *config.Rule {
@@ -34,7 +35,7 @@ func EasyPostTestAPI() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("EZTK", "EZTK"+secrets.NewSecret(alphaNumeric("54"))),
+		utils.GenerateSampleSecret("EZTK", "EZTK"+secrets.NewSecret(utils.AlphaNumeric("54"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/etsy.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func EtsyAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "etsy-access-token",
 		Description: "Found an Etsy Access Token, potentially compromising Etsy shop management and customer data.",
-		Regex:       generateSemiGenericRegex([]string{"etsy"}, alphaNumeric("24"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"etsy"}, utils.AlphaNumeric("24"), true),
 
 		Keywords: []string{
 			"etsy",
@@ -19,7 +20,7 @@ func EtsyAccessToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("etsy", secrets.NewSecret(alphaNumeric("24"))),
+		utils.GenerateSampleSecret("etsy", secrets.NewSecret(utils.AlphaNumeric("24"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 8 - 7
cmd/generate/config/rules/facebook.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -12,18 +13,18 @@ func FacebookSecret() *config.Rule {
 	r := config.Rule{
 		Description: "Discovered a Facebook Application secret, posing a risk of unauthorized access to Facebook accounts and personal data exposure.",
 		RuleID:      "facebook-secret",
-		Regex:       generateSemiGenericRegex([]string{"facebook"}, hex("32"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"facebook"}, utils.Hex("32"), true),
 
 		Keywords: []string{"facebook"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("facebook", secrets.NewSecret(hex("32"))),
+		utils.GenerateSampleSecret("facebook", secrets.NewSecret(utils.Hex("32"))),
 		`facebook_app_secret = "6dca6432e45d933e13650d1882bd5e69"`,       // gitleaks:allow
 		`facebook_client_access_token: 26f5fd13099f2c1331aafb86f6489692`, // gitleaks:allow
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 // https://developers.facebook.com/docs/facebook-login/guides/access-tokens/#apptokens
@@ -32,7 +33,7 @@ func FacebookAccessToken() *config.Rule {
 	r := config.Rule{
 		Description: "Discovered a Facebook Access Token, posing a risk of unauthorized access to Facebook accounts and personal data exposure.",
 		RuleID:      "facebook-access-token",
-		Regex:       generateUniqueTokenRegex(`\d{15,16}(\||%)[0-9a-z\-_]{27,40}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`\d{15,16}(\||%)[0-9a-z\-_]{27,40}`, true),
 	}
 
 	// validate
@@ -41,7 +42,7 @@ func FacebookAccessToken() *config.Rule {
 		`1308742762612587|rhoK1cbv0DOU_RTX_87O4MkX7AI`,                                         // gitleaks:allow
 		`1477036645700765|wRPf2v3mt2JfMqCLK8n7oltrEmc`,                                         // gitleaks:allow
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 // https://developers.facebook.com/docs/facebook-login/guides/access-tokens/#pagetokens
@@ -50,7 +51,7 @@ func FacebookPageAccessToken() *config.Rule {
 	r := config.Rule{
 		Description: "Discovered a Facebook Page Access Token, posing a risk of unauthorized access to Facebook accounts and personal data exposure.",
 		RuleID:      "facebook-page-access-token",
-		Regex:       generateUniqueTokenRegex("EAA[MC]"+alphaNumeric("20,"), true),
+		Regex:       utils.GenerateUniqueTokenRegex("EAA[MC]"+utils.AlphaNumeric("20,"), true),
 		Keywords:    []string{"EAAM", "EAAC"},
 	}
 
@@ -61,5 +62,5 @@ func FacebookPageAccessToken() *config.Rule {
 		`- name: FACEBOOK_TOKEN
 		value: "EAACEdEose0cBA1bad3afsf2aew"`, // gitleaks:allow
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/fastly.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,14 +11,14 @@ func FastlyAPIToken() *config.Rule {
 	r := config.Rule{
 		Description: "Uncovered a Fastly API key, which may compromise CDN and edge cloud services, leading to content delivery and security issues.",
 		RuleID:      "fastly-api-token",
-		Regex:       generateSemiGenericRegex([]string{"fastly"}, alphaNumericExtended("32"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"fastly"}, utils.AlphaNumericExtended("32"), true),
 
 		Keywords: []string{"fastly"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("fastly", secrets.NewSecret(alphaNumericExtended("32"))),
+		utils.GenerateSampleSecret("fastly", secrets.NewSecret(utils.AlphaNumericExtended("32"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 7 - 6
cmd/generate/config/rules/finicity.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,16 +11,16 @@ func FinicityClientSecret() *config.Rule {
 	r := config.Rule{
 		Description: "Identified a Finicity Client Secret, which could lead to compromised financial service integrations and data breaches.",
 		RuleID:      "finicity-client-secret",
-		Regex:       generateSemiGenericRegex([]string{"finicity"}, alphaNumeric("20"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"finicity"}, utils.AlphaNumeric("20"), true),
 
 		Keywords: []string{"finicity"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("finicity", secrets.NewSecret(alphaNumeric("20"))),
+		utils.GenerateSampleSecret("finicity", secrets.NewSecret(utils.AlphaNumeric("20"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func FinicityAPIToken() *config.Rule {
@@ -27,14 +28,14 @@ func FinicityAPIToken() *config.Rule {
 	r := config.Rule{
 		Description: "Detected a Finicity API token, potentially risking financial data access and unauthorized financial operations.",
 		RuleID:      "finicity-api-token",
-		Regex:       generateSemiGenericRegex([]string{"finicity"}, hex("32"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"finicity"}, utils.Hex("32"), true),
 
 		Keywords: []string{"finicity"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("finicity", secrets.NewSecret(hex("32"))),
+		utils.GenerateSampleSecret("finicity", secrets.NewSecret(utils.Hex("32"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/finnhub.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func FinnhubAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "finnhub-access-token",
 		Description: "Found a Finnhub Access Token, risking unauthorized access to financial market data and analytics.",
-		Regex:       generateSemiGenericRegex([]string{"finnhub"}, alphaNumeric("20"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"finnhub"}, utils.AlphaNumeric("20"), true),
 
 		Keywords: []string{
 			"finnhub",
@@ -19,7 +20,7 @@ func FinnhubAccessToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("finnhub", secrets.NewSecret(alphaNumeric("20"))),
+		utils.GenerateSampleSecret("finnhub", secrets.NewSecret(utils.AlphaNumeric("20"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/flickr.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func FlickrAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "flickr-access-token",
 		Description: "Discovered a Flickr Access Token, posing a risk of unauthorized photo management and potential data leakage.",
-		Regex:       generateSemiGenericRegex([]string{"flickr"}, alphaNumeric("32"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"flickr"}, utils.AlphaNumeric("32"), true),
 
 		Keywords: []string{
 			"flickr",
@@ -19,7 +20,7 @@ func FlickrAccessToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("flickr", secrets.NewSecret(alphaNumeric("32"))),
+		utils.GenerateSampleSecret("flickr", secrets.NewSecret(utils.AlphaNumeric("32"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 7 - 6
cmd/generate/config/rules/flutterwave.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
@@ -18,9 +19,9 @@ func FlutterwavePublicKey() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("flutterwavePubKey", "FLWPUBK_TEST-"+secrets.NewSecret(hex("32"))+"-X"),
+		utils.GenerateSampleSecret("flutterwavePubKey", "FLWPUBK_TEST-"+secrets.NewSecret(utils.Hex("32"))+"-X"),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func FlutterwaveSecretKey() *config.Rule {
@@ -34,9 +35,9 @@ func FlutterwaveSecretKey() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("flutterwavePubKey", "FLWSECK_TEST-"+secrets.NewSecret(hex("32"))+"-X"),
+		utils.GenerateSampleSecret("flutterwavePubKey", "FLWSECK_TEST-"+secrets.NewSecret(utils.Hex("32"))+"-X"),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func FlutterwaveEncKey() *config.Rule {
@@ -50,7 +51,7 @@ func FlutterwaveEncKey() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("flutterwavePubKey", "FLWSECK_TEST-"+secrets.NewSecret(hex("12"))),
+		utils.GenerateSampleSecret("flutterwavePubKey", "FLWSECK_TEST-"+secrets.NewSecret(utils.Hex("12"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 3 - 2
cmd/generate/config/rules/frameio.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
@@ -18,7 +19,7 @@ func FrameIO() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("frameio", "fio-u-"+secrets.NewSecret(alphaNumericExtended("64"))),
+		utils.GenerateSampleSecret("frameio", "fio-u-"+secrets.NewSecret(utils.AlphaNumericExtended("64"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/freshbooks.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func FreshbooksAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "freshbooks-access-token",
 		Description: "Discovered a Freshbooks Access Token, posing a risk to accounting software access and sensitive financial data exposure.",
-		Regex:       generateSemiGenericRegex([]string{"freshbooks"}, alphaNumeric("64"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"freshbooks"}, utils.AlphaNumeric("64"), true),
 
 		Keywords: []string{
 			"freshbooks",
@@ -19,7 +20,7 @@ func FreshbooksAccessToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("freshbooks", secrets.NewSecret(alphaNumeric("64"))),
+		utils.GenerateSampleSecret("freshbooks", secrets.NewSecret(utils.AlphaNumeric("64"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 5 - 4
cmd/generate/config/rules/gcp.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
@@ -21,7 +22,7 @@ func GCPServiceAccount() *config.Rule {
 	tps := []string{
 		`"type": "service_account"`,
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func GCPAPIKey() *config.Rule {
@@ -29,7 +30,7 @@ func GCPAPIKey() *config.Rule {
 	r := config.Rule{
 		RuleID:      "gcp-api-key",
 		Description: "Uncovered a GCP API key, which could lead to unauthorized access to Google Cloud services and data breaches.",
-		Regex:       generateUniqueTokenRegex(`AIza[0-9A-Za-z\\-_]{35}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`AIza[0-9A-Za-z\\-_]{35}`, true),
 
 		Keywords: []string{
 			"AIza",
@@ -38,7 +39,7 @@ func GCPAPIKey() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("gcp", secrets.NewSecret(`AIza[0-9A-Za-z\\-_]{35}`)),
+		utils.GenerateSampleSecret("gcp", secrets.NewSecret(`AIza[0-9A-Za-z\\-_]{35}`)),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 5 - 4
cmd/generate/config/rules/generic.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
 
@@ -9,7 +10,7 @@ func GenericCredential() *config.Rule {
 	r := config.Rule{
 		RuleID:      "generic-api-key",
 		Description: "Detected a Generic API Key, potentially exposing access to various services and sensitive operations.",
-		Regex: generateSemiGenericRegex([]string{
+		Regex: utils.GenerateSemiGenericRegex([]string{
 			"key",
 			"api",
 			"token",
@@ -39,8 +40,8 @@ func GenericCredential() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("generic", "CLOJARS_34bf0e88955ff5a1c328d6a7491acc4f48e865a7b8dd4d70a70749037443"),
-		generateSampleSecret("generic", "Zf3D0LXCM3EIMbgJpUNnkRtOfOueHznB"),
+		utils.GenerateSampleSecret("generic", "CLOJARS_34bf0e88955ff5a1c328d6a7491acc4f48e865a7b8dd4d70a70749037443"),
+		utils.GenerateSampleSecret("generic", "Zf3D0LXCM3EIMbgJpUNnkRtOfOueHznB"),
 		`"client_id" : "0afae57f3ccfd9d7f5767067bc48b30f719e271ba470488056e37ab35d4b6506"`,
 		`"client_secret" : "6da89121079f83b2eb6acccf8219ea982c3d79bccc3e9c6a85856480661f8fde",`,
 	}
@@ -50,5 +51,5 @@ func GenericCredential() *config.Rule {
 
 R5: Regulatory--21`,
 	}
-	return validate(r, tps, fps)
+	return utils.Validate(r, tps, fps)
 }

+ 12 - 11
cmd/generate/config/rules/github.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
@@ -18,9 +19,9 @@ func GitHubPat() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("github", "ghp_"+secrets.NewSecret(alphaNumeric("36"))),
+		utils.GenerateSampleSecret("github", "ghp_"+secrets.NewSecret(utils.AlphaNumeric("36"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func GitHubFineGrainedPat() *config.Rule {
@@ -34,9 +35,9 @@ func GitHubFineGrainedPat() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("github", "github_pat_"+secrets.NewSecret(alphaNumeric("82"))),
+		utils.GenerateSampleSecret("github", "github_pat_"+secrets.NewSecret(utils.AlphaNumeric("82"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func GitHubOauth() *config.Rule {
@@ -50,9 +51,9 @@ func GitHubOauth() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("github", "gho_"+secrets.NewSecret(alphaNumeric("36"))),
+		utils.GenerateSampleSecret("github", "gho_"+secrets.NewSecret(utils.AlphaNumeric("36"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func GitHubApp() *config.Rule {
@@ -66,10 +67,10 @@ func GitHubApp() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("github", "ghu_"+secrets.NewSecret(alphaNumeric("36"))),
-		generateSampleSecret("github", "ghs_"+secrets.NewSecret(alphaNumeric("36"))),
+		utils.GenerateSampleSecret("github", "ghu_"+secrets.NewSecret(utils.AlphaNumeric("36"))),
+		utils.GenerateSampleSecret("github", "ghs_"+secrets.NewSecret(utils.AlphaNumeric("36"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func GitHubRefresh() *config.Rule {
@@ -83,7 +84,7 @@ func GitHubRefresh() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("github", "ghr_"+secrets.NewSecret(alphaNumeric("36"))),
+		utils.GenerateSampleSecret("github", "ghr_"+secrets.NewSecret(utils.AlphaNumeric("36"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 7 - 6
cmd/generate/config/rules/gitlab.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
@@ -18,9 +19,9 @@ func GitlabPat() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("gitlab", "glpat-"+secrets.NewSecret(alphaNumeric("20"))),
+		utils.GenerateSampleSecret("gitlab", "glpat-"+secrets.NewSecret(utils.AlphaNumeric("20"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func GitlabPipelineTriggerToken() *config.Rule {
@@ -34,9 +35,9 @@ func GitlabPipelineTriggerToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("gitlab", "glptt-"+secrets.NewSecret(hex("40"))),
+		utils.GenerateSampleSecret("gitlab", "glptt-"+secrets.NewSecret(utils.Hex("40"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func GitlabRunnerRegistrationToken() *config.Rule {
@@ -50,7 +51,7 @@ func GitlabRunnerRegistrationToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("gitlab", "GR1348941"+secrets.NewSecret(alphaNumeric("20"))),
+		utils.GenerateSampleSecret("gitlab", "GR1348941"+secrets.NewSecret(utils.AlphaNumeric("20"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 6 - 5
cmd/generate/config/rules/gitter.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,8 +11,8 @@ func GitterAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "gitter-access-token",
 		Description: "Uncovered a Gitter Access Token, which may lead to unauthorized access to chat and communication services.",
-		Regex: generateSemiGenericRegex([]string{"gitter"},
-			alphaNumericExtendedShort("40"), true),
+		Regex: utils.GenerateSemiGenericRegex([]string{"gitter"},
+			utils.AlphaNumericExtendedShort("40"), true),
 
 		Keywords: []string{
 			"gitter",
@@ -20,8 +21,8 @@ func GitterAccessToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("gitter",
-			secrets.NewSecret(alphaNumericExtendedShort("40"))),
+		utils.GenerateSampleSecret("gitter",
+			secrets.NewSecret(utils.AlphaNumericExtendedShort("40"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/gocardless.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func GoCardless() *config.Rule {
 	r := config.Rule{
 		RuleID:      "gocardless-api-token",
 		Description: "Detected a GoCardless API token, potentially risking unauthorized direct debit payment operations and financial data exposure.",
-		Regex:       generateSemiGenericRegex([]string{"gocardless"}, `live_(?i)[a-z0-9\-_=]{40}`, true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"gocardless"}, `live_(?i)[a-z0-9\-_=]{40}`, true),
 
 		Keywords: []string{
 			"live_",
@@ -20,7 +21,7 @@ func GoCardless() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("gocardless", "live_"+secrets.NewSecret(alphaNumericExtended("40"))),
+		utils.GenerateSampleSecret("gocardless", "live_"+secrets.NewSecret(utils.AlphaNumericExtended("40"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 14 - 13
cmd/generate/config/rules/grafana.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -11,17 +12,17 @@ func GrafanaApiKey() *config.Rule {
 		Description: "Identified a Grafana API key, which could compromise monitoring dashboards and sensitive data analytics.",
 		RuleID:      "grafana-api-key",
 
-		Regex:    generateUniqueTokenRegex(`eyJrIjoi[A-Za-z0-9]{70,400}={0,2}`, true),
+		Regex:    utils.GenerateUniqueTokenRegex(`eyJrIjoi[A-Za-z0-9]{70,400}={0,2}`, true),
 		Keywords: []string{"eyJrIjoi"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("grafana-api-key",
+		utils.GenerateSampleSecret("grafana-api-key",
 			"eyJrIjoi"+
-				secrets.NewSecret(alphaNumeric("70"))),
+				secrets.NewSecret(utils.AlphaNumeric("70"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func GrafanaCloudApiToken() *config.Rule {
@@ -30,17 +31,17 @@ func GrafanaCloudApiToken() *config.Rule {
 		Description: "Found a Grafana cloud API token, risking unauthorized access to cloud-based monitoring services and data exposure.",
 		RuleID:      "grafana-cloud-api-token",
 
-		Regex:    generateUniqueTokenRegex(`glc_[A-Za-z0-9+/]{32,400}={0,2}`, true),
+		Regex:    utils.GenerateUniqueTokenRegex(`glc_[A-Za-z0-9+/]{32,400}={0,2}`, true),
 		Keywords: []string{"glc_"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("grafana-cloud-api-token",
+		utils.GenerateSampleSecret("grafana-cloud-api-token",
 			"glc_"+
-				secrets.NewSecret(alphaNumeric("32"))),
+				secrets.NewSecret(utils.AlphaNumeric("32"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func GrafanaServiceAccountToken() *config.Rule {
@@ -49,17 +50,17 @@ func GrafanaServiceAccountToken() *config.Rule {
 		Description: "Discovered a Grafana service account token, posing a risk of compromised monitoring services and data integrity.",
 		RuleID:      "grafana-service-account-token",
 
-		Regex:    generateUniqueTokenRegex(`glsa_[A-Za-z0-9]{32}_[A-Fa-f0-9]{8}`, true),
+		Regex:    utils.GenerateUniqueTokenRegex(`glsa_[A-Za-z0-9]{32}_[A-Fa-f0-9]{8}`, true),
 		Keywords: []string{"glsa_"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("grafana-service-account-token",
+		utils.GenerateSampleSecret("grafana-service-account-token",
 			"glsa_"+
-				secrets.NewSecret(alphaNumeric("32"))+
+				secrets.NewSecret(utils.AlphaNumeric("32"))+
 				"_"+
-				secrets.NewSecret((hex("8")))),
+				secrets.NewSecret((utils.Hex("8")))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 5 - 4
cmd/generate/config/rules/harness.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
@@ -18,10 +19,10 @@ func HarnessApiKey() *config.Rule {
 
 	// Generate a sample secret for validation
 	tps := []string{
-		generateSampleSecret("harness", "pat."+secrets.NewSecret(alphaNumeric("22"))+"."+secrets.NewSecret(alphaNumeric("24"))+"."+secrets.NewSecret(alphaNumeric("20"))),
-		generateSampleSecret("harness", "sat."+secrets.NewSecret(alphaNumeric("22"))+"."+secrets.NewSecret(alphaNumeric("24"))+"."+secrets.NewSecret(alphaNumeric("20"))),
+		utils.GenerateSampleSecret("harness", "pat."+secrets.NewSecret(utils.AlphaNumeric("22"))+"."+secrets.NewSecret(utils.AlphaNumeric("24"))+"."+secrets.NewSecret(utils.AlphaNumeric("20"))),
+		utils.GenerateSampleSecret("harness", "sat."+secrets.NewSecret(utils.AlphaNumeric("22"))+"."+secrets.NewSecret(utils.AlphaNumeric("24"))+"."+secrets.NewSecret(utils.AlphaNumeric("20"))),
 	}
 
-	// Validate the rule
-	return validate(r, tps, nil)
+	// validate the rule
+	return utils.Validate(r, tps, nil)
 }

+ 5 - 4
cmd/generate/config/rules/hashicorp.go

@@ -2,6 +2,7 @@ package rules
 
 import (
 	"fmt"
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
@@ -20,13 +21,13 @@ func HashiCorpTerraform() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("hashicorpToken", secrets.NewSecret(hex("14"))+".atlasv1."+secrets.NewSecret(alphaNumericExtended("60,70"))),
+		utils.GenerateSampleSecret("hashicorpToken", secrets.NewSecret(utils.Hex("14"))+".atlasv1."+secrets.NewSecret(utils.AlphaNumericExtended("60,70"))),
 		`#token = "hE1hlYILrSqpqh.atlasv1.ARjZuyzl33F71WR55s6ln5GQ1HWIwTDDH3MiRjz7OnpCfaCb1RCF5zGaSncCWmJdcYA"`,
 	}
 	fps := []string{
 		`token        = "xxxxxxxxxxxxxx.atlasv1.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"`, // low entropy
 	}
-	return validate(r, tps, fps)
+	return utils.Validate(r, tps, fps)
 }
 
 func HashicorpField() *config.Rule {
@@ -35,7 +36,7 @@ func HashicorpField() *config.Rule {
 	r := config.Rule{
 		Description: "Identified a HashiCorp Terraform password field, risking unauthorized infrastructure configuration and security breaches.",
 		RuleID:      "hashicorp-tf-password",
-		Regex:       generateSemiGenericRegex(keywords, fmt.Sprintf(`"%s"`, alphaNumericExtended("8,20")), true),
+		Regex:       utils.GenerateSemiGenericRegex(keywords, fmt.Sprintf(`"%s"`, utils.AlphaNumericExtended("8,20")), true),
 		Keywords:    keywords,
 		Path:        regexp.MustCompile(`(?i)\.(?:tf|hcl)$`),
 	}
@@ -52,5 +53,5 @@ func HashicorpField() *config.Rule {
 		"unrelated.js": "password       = " + `"rootpasswd"`,
 	}
 
-	return validateWithPaths(r, tps, fps)
+	return utils.ValidateWithPaths(r, tps, fps)
 }

+ 3 - 2
cmd/generate/config/rules/heroku.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
 
@@ -9,7 +10,7 @@ func Heroku() *config.Rule {
 	r := config.Rule{
 		Description: "Detected a Heroku API Key, potentially compromising cloud application deployments and operational security.",
 		RuleID:      "heroku-api-key",
-		Regex:       generateSemiGenericRegex([]string{"heroku"}, hex8_4_4_4_12(), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"heroku"}, utils.Hex8_4_4_4_12(), true),
 
 		Keywords: []string{"heroku"},
 	}
@@ -19,5 +20,5 @@ func Heroku() *config.Rule {
 		`const HEROKU_KEY = "12345678-ABCD-ABCD-ABCD-1234567890AB"`, // gitleaks:allow
 		`heroku_api_key = "832d2129-a846-4e27-99f4-7004b6ad53ef"`,   // gitleaks:allow
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 3 - 2
cmd/generate/config/rules/hubspot.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
 
@@ -9,7 +10,7 @@ func HubSpot() *config.Rule {
 	r := config.Rule{
 		Description: "Found a HubSpot API Token, posing a risk to CRM data integrity and unauthorized marketing operations.",
 		RuleID:      "hubspot-api-key",
-		Regex: generateSemiGenericRegex([]string{"hubspot"},
+		Regex: utils.GenerateSemiGenericRegex([]string{"hubspot"},
 			`[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}`, true),
 
 		Keywords: []string{"hubspot"},
@@ -19,5 +20,5 @@ func HubSpot() *config.Rule {
 	tps := []string{
 		`const hubspotKey = "12345678-ABCD-ABCD-ABCD-1234567890AB"`, // gitleaks:allow
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 3 - 2
cmd/generate/config/rules/huggingface.go

@@ -2,6 +2,7 @@ package rules
 
 import (
 	"fmt"
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
@@ -63,7 +64,7 @@ func HuggingFaceAccessToken() *config.Rule {
 		`# HuggingFace API Token https://huggingface.co/settings/tokens
 		HUGGINGFACE_API_TOKEN=hf_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,`,
 	}
-	return validate(r, tps, fps)
+	return utils.Validate(r, tps, fps)
 }
 
 // Will be deprecated Aug 1st, 2023.
@@ -111,5 +112,5 @@ func HuggingFaceOrganizationApiToken() *config.Rule {
 		You should see a token hf_xxxxx (old tokens are api_XXXXXXXX or api_org_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx).
 		If you do not submit your API token when sending requests to the API, you will not be able to run inference on your private models.`,
 	}
-	return validate(r, tps, fps)
+	return utils.Validate(r, tps, fps)
 }

+ 4 - 3
cmd/generate/config/rules/infracost.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -17,7 +18,7 @@ func InfracostAPIToken() *config.Rule {
 		// Regex capture group for the actual secret
 
 		// Regex used for detecting secrets. See regex section below for more details
-		Regex: generateUniqueTokenRegex(`ico-[a-zA-Z0-9]{32}`, true),
+		Regex: utils.GenerateUniqueTokenRegex(`ico-[a-zA-Z0-9]{32}`, true),
 
 		// Keywords used for string matching on fragments (think of this as a prefilter)
 		Keywords: []string{"ico-"},
@@ -25,7 +26,7 @@ func InfracostAPIToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("ico", "ico-"+secrets.NewSecret("[A-Za-z0-9]{32}")),
+		utils.GenerateSampleSecret("ico", "ico-"+secrets.NewSecret("[A-Za-z0-9]{32}")),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/intercom.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,14 +11,14 @@ func Intercom() *config.Rule {
 	r := config.Rule{
 		Description: "Identified an Intercom API Token, which could compromise customer communication channels and data privacy.",
 		RuleID:      "intercom-api-key",
-		Regex:       generateSemiGenericRegex([]string{"intercom"}, alphaNumericExtended("60"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"intercom"}, utils.AlphaNumericExtended("60"), true),
 
 		Keywords: []string{"intercom"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("intercom", secrets.NewSecret(alphaNumericExtended("60"))),
+		utils.GenerateSampleSecret("intercom", secrets.NewSecret(utils.AlphaNumericExtended("60"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 5 - 4
cmd/generate/config/rules/intra42.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func Intra42ClientSecret() *config.Rule {
 	r := config.Rule{
 		Description: "Found a Intra42 client secret, which could lead to unauthorized access to the 42School API and sensitive data.",
 		RuleID:      "intra42-client-secret",
-		Regex:       generateUniqueTokenRegex(`s-s4t2(?:ud|af)-[abcdef0123456789]{64}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`s-s4t2(?:ud|af)-[abcdef0123456789]{64}`, true),
 		Keywords: []string{
 			"intra",
 			"s-s4t2ud-",
@@ -20,10 +21,10 @@ func Intra42ClientSecret() *config.Rule {
 
 	// validate
 	tps := []string{
-		"clientSecret := \"s-s4t2ud-" + secrets.NewSecret(hex("64")) + "\"",
-		"clientSecret := \"s-s4t2af-" + secrets.NewSecret(hex("64")) + "\"",
+		"clientSecret := \"s-s4t2ud-" + secrets.NewSecret(utils.Hex("64")) + "\"",
+		"clientSecret := \"s-s4t2af-" + secrets.NewSecret(utils.Hex("64")) + "\"",
 		"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", // gitleaks:allow
 		"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", // gitleaks:allow
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 10 - 9
cmd/generate/config/rules/jfrog.go

@@ -2,6 +2,7 @@ package rules
 
 import (
 	"fmt"
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
@@ -21,16 +22,16 @@ func JFrogAPIKey() *config.Rule {
 		// Regex capture group for the actual secret
 
 		// Regex used for detecting secrets. See regex section below for more details
-		Regex: generateSemiGenericRegex(keywords, alphaNumeric("73"), true),
+		Regex: utils.GenerateSemiGenericRegex(keywords, utils.AlphaNumeric("73"), true),
 
 		// Keywords used for string matching on fragments (think of this as a prefilter)
 		Keywords: keywords,
 	}
 	// validate
 	tps := []string{
-		fmt.Sprintf("--set imagePullSecretJfrog.password=%s", secrets.NewSecret(alphaNumeric("73"))),
+		fmt.Sprintf("--set imagePullSecretJfrog.password=%s", secrets.NewSecret(utils.AlphaNumeric("73"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func JFrogIdentityToken() *config.Rule {
@@ -47,7 +48,7 @@ func JFrogIdentityToken() *config.Rule {
 		// Regex capture group for the actual secret
 
 		// Regex used for detecting secrets. See regex section below for more details
-		Regex: generateSemiGenericRegex(keywords, alphaNumeric("64"), true),
+		Regex: utils.GenerateSemiGenericRegex(keywords, utils.AlphaNumeric("64"), true),
 
 		// Keywords used for string matching on fragments (think of this as a prefilter)
 		Keywords: keywords,
@@ -55,10 +56,10 @@ func JFrogIdentityToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("jfrog", secrets.NewSecret(alphaNumeric("64"))),
-		generateSampleSecret("artifactory", secrets.NewSecret(alphaNumeric("64"))),
-		generateSampleSecret("bintray", secrets.NewSecret(alphaNumeric("64"))),
-		generateSampleSecret("xray", secrets.NewSecret(alphaNumeric("64"))),
+		utils.GenerateSampleSecret("jfrog", secrets.NewSecret(utils.AlphaNumeric("64"))),
+		utils.GenerateSampleSecret("artifactory", secrets.NewSecret(utils.AlphaNumeric("64"))),
+		utils.GenerateSampleSecret("bintray", secrets.NewSecret(utils.AlphaNumeric("64"))),
+		utils.GenerateSampleSecret("xray", secrets.NewSecret(utils.AlphaNumeric("64"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/jwt.go

@@ -3,6 +3,7 @@ package rules
 import (
 	b64 "encoding/base64"
 	"fmt"
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/config"
@@ -13,7 +14,7 @@ func JWT() *config.Rule {
 	r := config.Rule{
 		Description: "Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.",
 		RuleID:      "jwt",
-		Regex:       generateUniqueTokenRegex(`ey[a-zA-Z0-9]{17,}\.ey[a-zA-Z0-9\/\\_-]{17,}\.(?:[a-zA-Z0-9\/\\_-]{10,}={0,2})?`, false),
+		Regex:       utils.GenerateUniqueTokenRegex(`ey[a-zA-Z0-9]{17,}\.ey[a-zA-Z0-9\/\\_-]{17,}\.(?:[a-zA-Z0-9\/\\_-]{10,}={0,2})?`, false),
 		Keywords:    []string{"ey"},
 	}
 
@@ -61,7 +62,7 @@ func JWT() *config.Rule {
 		`# Req: Invoke-RestMethod -Uri 'http://localhost:8085/users' -Headers @{ 'X-API-KEY' = 'eyJhbGciOiJub25lIn0.eyJ1c2VybmFtZSI6Im1vcnR5Iiwic3ViIjoiMTIzIn0.' }`, // gitleaks:allow
 	}
 	fps := []string{}
-	return validate(r, tps, fps)
+	return utils.Validate(r, tps, fps)
 }
 
 func JWTBase64() *config.Rule {
@@ -109,7 +110,7 @@ vHVobJ8A
 =mIC1
 -----END PGP PUBLIC KEY BLOCK-----`,
 	}
-	return validate(r, tps, fps)
+	return utils.Validate(r, tps, fps)
 }
 
 func generateTestValues() []string {

+ 6 - 5
cmd/generate/config/rules/kraken.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,8 +11,8 @@ func KrakenAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "kraken-access-token",
 		Description: "Identified a Kraken Access Token, potentially compromising cryptocurrency trading accounts and financial security.",
-		Regex: generateSemiGenericRegex([]string{"kraken"},
-			alphaNumericExtendedLong("80,90"), true),
+		Regex: utils.GenerateSemiGenericRegex([]string{"kraken"},
+			utils.AlphaNumericExtendedLong("80,90"), true),
 
 		Keywords: []string{
 			"kraken",
@@ -20,8 +21,8 @@ func KrakenAccessToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("kraken",
-			secrets.NewSecret(alphaNumericExtendedLong("80,90"))),
+		utils.GenerateSampleSecret("kraken",
+			secrets.NewSecret(utils.AlphaNumericExtendedLong("80,90"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 5 - 4
cmd/generate/config/rules/kubernetes.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/config"
@@ -15,7 +16,7 @@ func KubernetesSecretWithDataBefore() *config.Rule {
 		RuleID:      "kubernetes-secret-with-data-before",
 		Description: "Possible Kubernetes Secret detected, posing a risk of leaking credentials/tokens from your deployments",
 		// We try to match secrets by looking if we have the keyword
-		Regex: generateUniqueTokenRegex(`(?i)(?:\b(?:data:))(\W+(?:\w+\W+){0,200}?)\bkind:.{0,10}Secret\b`, true),
+		Regex: utils.GenerateUniqueTokenRegex(`(?i)(?:\b(?:data:))(\W+(?:\w+\W+){0,200}?)\bkind:.{0,10}Secret\b`, true),
 
 		Keywords: []string{
 			"Secret",
@@ -34,7 +35,7 @@ func KubernetesSecretWithDataBefore() *config.Rule {
 		"kubernetes-quoted-1.yaml": "apiVersion: v1'\n' data:'\n' extra: YmFyCg=='\n' kind: 'Secret''\n' metadata:'\n' name: 'secret-sa-sample''\n' annotations:'\n' kubernetes.io/service-account.name: 'sa-name'", // gitleaks:allow
 		"kubernetes-quoted-2.yaml": "apiVersion: v1'\n' data:'\n' extra: YmFyCg=='\n' kind: 'secret''\n' metadata:'\n' name: 'secret-sa-sample''\n' annotations:'\n' kubernetes.io/service-account.name: 'sa-name'", // gitleaks:allow
 	}
-	return validateWithPaths(r, tps, nil)
+	return utils.ValidateWithPaths(r, tps, nil)
 }
 
 // KubernetesSecretWithDataAfter validates if we detected a kubernetes secret which contains data, after the resource identifier!
@@ -44,7 +45,7 @@ func KubernetesSecretWithDataAfter() *config.Rule {
 		RuleID:      "kubernetes-secret-with-data-after",
 		Description: "Possible Kubernetes Secret detected, posing a risk of leaking credentials/tokens from your deployments",
 		// We try to match secrets by looking if we have the keyword
-		Regex: generateUniqueTokenRegex(`(?i)(?:\bkind:.{0,10}Secret\b)(?:.|\s){0,200}?\b(?:data:)\s*(.+)`, true),
+		Regex: utils.GenerateUniqueTokenRegex(`(?i)(?:\bkind:.{0,10}Secret\b)(?:.|\s){0,200}?\b(?:data:)\s*(.+)`, true),
 
 		Keywords: []string{
 			"Secret",
@@ -64,5 +65,5 @@ func KubernetesSecretWithDataAfter() *config.Rule {
 		"kubernetes-quoted-2.yaml": "apiVersion: v1'\n' kind: 'secret''\n' data:'\n' password: UyFCXCpkJHpEc2I9'\n' username: YWRtaW4='\n' metadata:'\n' name: db-user-pass'\n' namespace: default'\n' type: Opaque", // gitleaks:allow
 	}
 
-	return validateWithPaths(r, tps, nil)
+	return utils.ValidateWithPaths(r, tps, nil)
 }

+ 7 - 6
cmd/generate/config/rules/kucoin.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func KucoinAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "kucoin-access-token",
 		Description: "Found a Kucoin Access Token, risking unauthorized access to cryptocurrency exchange services and transactions.",
-		Regex:       generateSemiGenericRegex([]string{"kucoin"}, hex("24"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"kucoin"}, utils.Hex("24"), true),
 
 		Keywords: []string{
 			"kucoin",
@@ -19,9 +20,9 @@ func KucoinAccessToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("kucoin", secrets.NewSecret(hex("24"))),
+		utils.GenerateSampleSecret("kucoin", secrets.NewSecret(utils.Hex("24"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func KucoinSecretKey() *config.Rule {
@@ -29,7 +30,7 @@ func KucoinSecretKey() *config.Rule {
 	r := config.Rule{
 		RuleID:      "kucoin-secret-key",
 		Description: "Discovered a Kucoin Secret Key, which could lead to compromised cryptocurrency operations and financial data breaches.",
-		Regex:       generateSemiGenericRegex([]string{"kucoin"}, hex8_4_4_4_12(), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"kucoin"}, utils.Hex8_4_4_4_12(), true),
 
 		Keywords: []string{
 			"kucoin",
@@ -38,7 +39,7 @@ func KucoinSecretKey() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("kucoin", secrets.NewSecret(hex8_4_4_4_12())),
+		utils.GenerateSampleSecret("kucoin", secrets.NewSecret(utils.Hex8_4_4_4_12())),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/launchdarkly.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func LaunchDarklyAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "launchdarkly-access-token",
 		Description: "Uncovered a Launchdarkly Access Token, potentially compromising feature flag management and application functionality.",
-		Regex:       generateSemiGenericRegex([]string{"launchdarkly"}, alphaNumericExtended("40"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"launchdarkly"}, utils.AlphaNumericExtended("40"), true),
 
 		Keywords: []string{
 			"launchdarkly",
@@ -19,7 +20,7 @@ func LaunchDarklyAccessToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("launchdarkly", secrets.NewSecret(alphaNumericExtended("40"))),
+		utils.GenerateSampleSecret("launchdarkly", secrets.NewSecret(utils.AlphaNumericExtended("40"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 6 - 5
cmd/generate/config/rules/linear.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
@@ -18,9 +19,9 @@ func LinearAPIToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("linear", "lin_api_"+secrets.NewSecret(alphaNumeric("40"))),
+		utils.GenerateSampleSecret("linear", "lin_api_"+secrets.NewSecret(utils.AlphaNumeric("40"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func LinearClientSecret() *config.Rule {
@@ -28,13 +29,13 @@ func LinearClientSecret() *config.Rule {
 	r := config.Rule{
 		Description: "Identified a Linear Client Secret, which may compromise secure integrations and sensitive project management data.",
 		RuleID:      "linear-client-secret",
-		Regex:       generateSemiGenericRegex([]string{"linear"}, hex("32"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"linear"}, utils.Hex("32"), true),
 		Keywords:    []string{"linear"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("linear", secrets.NewSecret(hex("32"))),
+		utils.GenerateSampleSecret("linear", secrets.NewSecret(utils.Hex("32"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 9 - 8
cmd/generate/config/rules/linkedin.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,10 +11,10 @@ func LinkedinClientSecret() *config.Rule {
 	r := config.Rule{
 		RuleID:      "linkedin-client-secret",
 		Description: "Discovered a LinkedIn Client secret, potentially compromising LinkedIn application integrations and user data.",
-		Regex: generateSemiGenericRegex([]string{
+		Regex: utils.GenerateSemiGenericRegex([]string{
 			"linkedin",
 			"linked-in",
-		}, alphaNumeric("16"), true),
+		}, utils.AlphaNumeric("16"), true),
 
 		Keywords: []string{
 			"linkedin",
@@ -23,9 +24,9 @@ func LinkedinClientSecret() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("linkedin", secrets.NewSecret(alphaNumeric("16"))),
+		utils.GenerateSampleSecret("linkedin", secrets.NewSecret(utils.AlphaNumeric("16"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func LinkedinClientID() *config.Rule {
@@ -33,10 +34,10 @@ func LinkedinClientID() *config.Rule {
 	r := config.Rule{
 		RuleID:      "linkedin-client-id",
 		Description: "Found a LinkedIn Client ID, risking unauthorized access to LinkedIn integrations and professional data exposure.",
-		Regex: generateSemiGenericRegex([]string{
+		Regex: utils.GenerateSemiGenericRegex([]string{
 			"linkedin",
 			"linked-in",
-		}, alphaNumeric("14"), true),
+		}, utils.AlphaNumeric("14"), true),
 
 		Keywords: []string{
 			"linkedin",
@@ -46,7 +47,7 @@ func LinkedinClientID() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("linkedin", secrets.NewSecret(alphaNumeric("14"))),
+		utils.GenerateSampleSecret("linkedin", secrets.NewSecret(utils.AlphaNumeric("14"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 7 - 6
cmd/generate/config/rules/lob.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func LobPubAPIToken() *config.Rule {
 	r := config.Rule{
 		Description: "Detected a Lob Publishable API Key, posing a risk of exposing mail and print service integrations.",
 		RuleID:      "lob-pub-api-key",
-		Regex:       generateSemiGenericRegex([]string{"lob"}, `(test|live)_pub_[a-f0-9]{31}`, true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"lob"}, `(test|live)_pub_[a-f0-9]{31}`, true),
 
 		Keywords: []string{
 			"test_pub",
@@ -21,9 +22,9 @@ func LobPubAPIToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("lob", "test_pub_"+secrets.NewSecret(hex("31"))),
+		utils.GenerateSampleSecret("lob", "test_pub_"+secrets.NewSecret(utils.Hex("31"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func LobAPIToken() *config.Rule {
@@ -31,7 +32,7 @@ func LobAPIToken() *config.Rule {
 	r := config.Rule{
 		Description: "Uncovered a Lob API Key, which could lead to unauthorized access to mailing and address verification services.",
 		RuleID:      "lob-api-key",
-		Regex:       generateSemiGenericRegex([]string{"lob"}, `(live|test)_[a-f0-9]{35}`, true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"lob"}, `(live|test)_[a-f0-9]{35}`, true),
 		Keywords: []string{
 			"test_",
 			"live_",
@@ -40,7 +41,7 @@ func LobAPIToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("lob", "test_"+secrets.NewSecret(hex("35"))),
+		utils.GenerateSampleSecret("lob", "test_"+secrets.NewSecret(utils.Hex("35"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/mailchimp.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func MailChimp() *config.Rule {
 	r := config.Rule{
 		RuleID:      "mailchimp-api-key",
 		Description: "Identified a Mailchimp API key, potentially compromising email marketing campaigns and subscriber data.",
-		Regex:       generateSemiGenericRegex([]string{"MailchimpSDK.initialize", "mailchimp"}, hex("32")+`-us\d\d`, true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"MailchimpSDK.initialize", "mailchimp"}, utils.Hex("32")+`-us\d\d`, true),
 
 		Keywords: []string{
 			"mailchimp",
@@ -19,7 +20,7 @@ func MailChimp() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("mailchimp", secrets.NewSecret(hex("32"))+"-us20"),
+		utils.GenerateSampleSecret("mailchimp", secrets.NewSecret(utils.Hex("32"))+"-us20"),
 		`mailchimp_api_key: cefa780880ba5f5696192a34f6292c35-us18`, // gitleaks:allow
 		`MAILCHIMPE_KEY = "b5b9f8e50c640da28993e8b6a48e3e53-us18"`, // gitleaks:allow
 	}
@@ -27,5 +28,5 @@ func MailChimp() *config.Rule {
 		// False Negative
 		`MailchimpSDK.initialize(token: 3012a5754bbd716926f99c028f7ea428-us18)`, // gitleaks:allow
 	}
-	return validate(r, tps, fps)
+	return utils.Validate(r, tps, fps)
 }

+ 10 - 9
cmd/generate/config/rules/mailgun.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func MailGunPrivateAPIToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "mailgun-private-api-token",
 		Description: "Found a Mailgun private API token, risking unauthorized email service operations and data breaches.",
-		Regex:       generateSemiGenericRegex([]string{"mailgun"}, `key-[a-f0-9]{32}`, true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"mailgun"}, `key-[a-f0-9]{32}`, true),
 
 		Keywords: []string{
 			"mailgun",
@@ -19,9 +20,9 @@ func MailGunPrivateAPIToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("mailgun", "key-"+secrets.NewSecret(hex("32"))),
+		utils.GenerateSampleSecret("mailgun", "key-"+secrets.NewSecret(utils.Hex("32"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func MailGunPubAPIToken() *config.Rule {
@@ -29,7 +30,7 @@ func MailGunPubAPIToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "mailgun-pub-key",
 		Description: "Discovered a Mailgun public validation key, which could expose email verification processes and associated data.",
-		Regex:       generateSemiGenericRegex([]string{"mailgun"}, `pubkey-[a-f0-9]{32}`, true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"mailgun"}, `pubkey-[a-f0-9]{32}`, true),
 
 		Keywords: []string{
 			"mailgun",
@@ -38,9 +39,9 @@ func MailGunPubAPIToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("mailgun", "pubkey-"+secrets.NewSecret(hex("32"))),
+		utils.GenerateSampleSecret("mailgun", "pubkey-"+secrets.NewSecret(utils.Hex("32"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func MailGunSigningKey() *config.Rule {
@@ -48,7 +49,7 @@ func MailGunSigningKey() *config.Rule {
 	r := config.Rule{
 		RuleID:      "mailgun-signing-key",
 		Description: "Uncovered a Mailgun webhook signing key, potentially compromising email automation and data integrity.",
-		Regex:       generateSemiGenericRegex([]string{"mailgun"}, `[a-h0-9]{32}-[a-h0-9]{8}-[a-h0-9]{8}`, true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"mailgun"}, `[a-h0-9]{32}-[a-h0-9]{8}-[a-h0-9]{8}`, true),
 
 		Keywords: []string{
 			"mailgun",
@@ -57,7 +58,7 @@ func MailGunSigningKey() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("mailgun", secrets.NewSecret(hex("32"))+"-00001111-22223333"),
+		utils.GenerateSampleSecret("mailgun", secrets.NewSecret(utils.Hex("32"))+"-00001111-22223333"),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/mapbox.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,14 +11,14 @@ func MapBox() *config.Rule {
 	r := config.Rule{
 		Description: "Detected a MapBox API token, posing a risk to geospatial services and sensitive location data exposure.",
 		RuleID:      "mapbox-api-token",
-		Regex:       generateSemiGenericRegex([]string{"mapbox"}, `pk\.[a-z0-9]{60}\.[a-z0-9]{22}`, true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"mapbox"}, `pk\.[a-z0-9]{60}\.[a-z0-9]{22}`, true),
 
 		Keywords: []string{"mapbox"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("mapbox", "pk."+secrets.NewSecret(alphaNumeric("60"))+"."+secrets.NewSecret(alphaNumeric("22"))),
+		utils.GenerateSampleSecret("mapbox", "pk."+secrets.NewSecret(utils.AlphaNumeric("60"))+"."+secrets.NewSecret(utils.AlphaNumeric("22"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/mattermost.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func MattermostAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "mattermost-access-token",
 		Description: "Identified a Mattermost Access Token, which may compromise team communication channels and data privacy.",
-		Regex:       generateSemiGenericRegex([]string{"mattermost"}, alphaNumeric("26"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"mattermost"}, utils.AlphaNumeric("26"), true),
 
 		Keywords: []string{
 			"mattermost",
@@ -19,7 +20,7 @@ func MattermostAccessToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("mattermost", secrets.NewSecret(alphaNumeric("26"))),
+		utils.GenerateSampleSecret("mattermost", secrets.NewSecret(utils.AlphaNumeric("26"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 10 - 9
cmd/generate/config/rules/messagebird.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,11 +11,11 @@ func MessageBirdAPIToken() *config.Rule {
 	r := config.Rule{
 		Description: "Found a MessageBird API token, risking unauthorized access to communication platforms and message data.",
 		RuleID:      "messagebird-api-token",
-		Regex: generateSemiGenericRegex([]string{
+		Regex: utils.GenerateSemiGenericRegex([]string{
 			"messagebird",
 			"message-bird",
 			"message_bird",
-		}, alphaNumeric("25"), true),
+		}, utils.AlphaNumeric("25"), true),
 
 		Keywords: []string{
 			"messagebird",
@@ -25,11 +26,11 @@ func MessageBirdAPIToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("messagebird", secrets.NewSecret(alphaNumeric("25"))),
-		generateSampleSecret("message-bird", secrets.NewSecret(alphaNumeric("25"))),
-		generateSampleSecret("message_bird", secrets.NewSecret(alphaNumeric("25"))),
+		utils.GenerateSampleSecret("messagebird", secrets.NewSecret(utils.AlphaNumeric("25"))),
+		utils.GenerateSampleSecret("message-bird", secrets.NewSecret(utils.AlphaNumeric("25"))),
+		utils.GenerateSampleSecret("message_bird", secrets.NewSecret(utils.AlphaNumeric("25"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func MessageBirdClientID() *config.Rule {
@@ -37,11 +38,11 @@ func MessageBirdClientID() *config.Rule {
 	r := config.Rule{
 		Description: "Discovered a MessageBird client ID, potentially compromising API integrations and sensitive communication data.",
 		RuleID:      "messagebird-client-id",
-		Regex: generateSemiGenericRegex([]string{
+		Regex: utils.GenerateSemiGenericRegex([]string{
 			"messagebird",
 			"message-bird",
 			"message_bird",
-		}, hex8_4_4_4_12(), true),
+		}, utils.Hex8_4_4_4_12(), true),
 
 		Keywords: []string{
 			"messagebird",
@@ -54,5 +55,5 @@ func MessageBirdClientID() *config.Rule {
 	tps := []string{
 		`const MessageBirdClientID = "12345678-ABCD-ABCD-ABCD-1234567890AB"`, // gitleaks:allow
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 5 - 4
cmd/generate/config/rules/netlify.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,8 +11,8 @@ func NetlifyAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "netlify-access-token",
 		Description: "Detected a Netlify Access Token, potentially compromising web hosting services and site management.",
-		Regex: generateSemiGenericRegex([]string{"netlify"},
-			alphaNumericExtended("40,46"), true),
+		Regex: utils.GenerateSemiGenericRegex([]string{"netlify"},
+			utils.AlphaNumericExtended("40,46"), true),
 
 		Keywords: []string{
 			"netlify",
@@ -20,7 +21,7 @@ func NetlifyAccessToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("netlify", secrets.NewSecret(alphaNumericExtended("40,46"))),
+		utils.GenerateSampleSecret("netlify", secrets.NewSecret(utils.AlphaNumericExtended("40,46"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 14 - 13
cmd/generate/config/rules/newrelic.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func NewRelicUserID() *config.Rule {
 	r := config.Rule{
 		RuleID:      "new-relic-user-api-key",
 		Description: "Discovered a New Relic user API Key, which could lead to compromised application insights and performance monitoring.",
-		Regex: generateSemiGenericRegex([]string{
+		Regex: utils.GenerateSemiGenericRegex([]string{
 			"new-relic",
 			"newrelic",
 			"new_relic",
@@ -23,9 +24,9 @@ func NewRelicUserID() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("new-relic", "NRAK-"+secrets.NewSecret(alphaNumeric("27"))),
+		utils.GenerateSampleSecret("new-relic", "NRAK-"+secrets.NewSecret(utils.AlphaNumeric("27"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func NewRelicUserKey() *config.Rule {
@@ -33,11 +34,11 @@ func NewRelicUserKey() *config.Rule {
 	r := config.Rule{
 		RuleID:      "new-relic-user-api-id",
 		Description: "Found a New Relic user API ID, posing a risk to application monitoring services and data integrity.",
-		Regex: generateSemiGenericRegex([]string{
+		Regex: utils.GenerateSemiGenericRegex([]string{
 			"new-relic",
 			"newrelic",
 			"new_relic",
-		}, alphaNumeric("64"), true),
+		}, utils.AlphaNumeric("64"), true),
 
 		Keywords: []string{
 			"new-relic",
@@ -48,9 +49,9 @@ func NewRelicUserKey() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("new-relic", secrets.NewSecret(alphaNumeric("64"))),
+		utils.GenerateSampleSecret("new-relic", secrets.NewSecret(utils.AlphaNumeric("64"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func NewRelicBrowserAPIKey() *config.Rule {
@@ -58,7 +59,7 @@ func NewRelicBrowserAPIKey() *config.Rule {
 	r := config.Rule{
 		RuleID:      "new-relic-browser-api-token",
 		Description: "Identified a New Relic ingest browser API token, risking unauthorized access to application performance data and analytics.",
-		Regex: generateSemiGenericRegex([]string{
+		Regex: utils.GenerateSemiGenericRegex([]string{
 			"new-relic",
 			"newrelic",
 			"new_relic",
@@ -71,9 +72,9 @@ func NewRelicBrowserAPIKey() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("new-relic", "NRJS-"+secrets.NewSecret(hex("19"))),
+		utils.GenerateSampleSecret("new-relic", "NRJS-"+secrets.NewSecret(utils.Hex("19"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func NewRelicInsertKey() *config.Rule {
@@ -81,7 +82,7 @@ func NewRelicInsertKey() *config.Rule {
 	r := config.Rule{
 		RuleID:      "new-relic-insert-key",
 		Description: "Discovered a New Relic insight insert key, compromising data injection into the platform.",
-		Regex: generateSemiGenericRegex([]string{
+		Regex: utils.GenerateSemiGenericRegex([]string{
 			"new-relic",
 			"newrelic",
 			"new_relic",
@@ -94,7 +95,7 @@ func NewRelicInsertKey() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("new-relic", "NRII-"+secrets.NewSecret(hex("32"))),
+		utils.GenerateSampleSecret("new-relic", "NRII-"+secrets.NewSecret(utils.Hex("32"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/npm.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func NPM() *config.Rule {
 	r := config.Rule{
 		RuleID:      "npm-access-token",
 		Description: "Uncovered an npm access token, potentially compromising package management and code repository access.",
-		Regex:       generateUniqueTokenRegex(`npm_[a-z0-9]{36}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`npm_[a-z0-9]{36}`, true),
 
 		Keywords: []string{
 			"npm_",
@@ -19,7 +20,7 @@ func NPM() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("npmAccessToken", "npm_"+secrets.NewSecret(alphaNumeric("36"))),
+		utils.GenerateSampleSecret("npmAccessToken", "npm_"+secrets.NewSecret(utils.AlphaNumeric("36"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 5 - 4
cmd/generate/config/rules/nytimes.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,9 +11,9 @@ func NytimesAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "nytimes-access-token",
 		Description: "Detected a Nytimes Access Token, risking unauthorized access to New York Times APIs and content services.",
-		Regex: generateSemiGenericRegex([]string{
+		Regex: utils.GenerateSemiGenericRegex([]string{
 			"nytimes", "new-york-times,", "newyorktimes"},
-			alphaNumericExtended("32"), true),
+			utils.AlphaNumericExtended("32"), true),
 
 		Keywords: []string{
 			"nytimes",
@@ -23,7 +24,7 @@ func NytimesAccessToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("nytimes", secrets.NewSecret(alphaNumeric("32"))),
+		utils.GenerateSampleSecret("nytimes", secrets.NewSecret(utils.AlphaNumeric("32"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 5 - 4
cmd/generate/config/rules/okta.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,8 +11,8 @@ func OktaAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "okta-access-token",
 		Description: "Identified an Okta Access Token, which may compromise identity management services and user authentication data.",
-		Regex: generateSemiGenericRegex([]string{"okta"},
-			alphaNumericExtended("42"), true),
+		Regex: utils.GenerateSemiGenericRegex([]string{"okta"},
+			utils.AlphaNumericExtended("42"), true),
 
 		Keywords: []string{
 			"okta",
@@ -20,7 +21,7 @@ func OktaAccessToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("okta", secrets.NewSecret(alphaNumeric("42"))),
+		utils.GenerateSampleSecret("okta", secrets.NewSecret(utils.AlphaNumeric("42"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/openai.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func OpenAI() *config.Rule {
 	r := config.Rule{
 		RuleID:      "openai-api-key",
 		Description: "Found an OpenAI API Key, posing a risk of unauthorized access to AI services and data manipulation.",
-		Regex:       generateUniqueTokenRegex(`sk-[a-zA-Z0-9]{20}T3BlbkFJ[a-zA-Z0-9]{20}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`sk-[a-zA-Z0-9]{20}T3BlbkFJ[a-zA-Z0-9]{20}`, true),
 
 		Keywords: []string{
 			"T3BlbkFJ",
@@ -19,7 +20,7 @@ func OpenAI() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("openaiApiKey", "sk-"+secrets.NewSecret(alphaNumeric("20"))+"T3BlbkFJ"+secrets.NewSecret(alphaNumeric("20"))),
+		utils.GenerateSampleSecret("openaiApiKey", "sk-"+secrets.NewSecret(utils.AlphaNumeric("20"))+"T3BlbkFJ"+secrets.NewSecret(utils.AlphaNumeric("20"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 2 - 1
cmd/generate/config/rules/openshift.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
@@ -33,5 +34,5 @@ func OpenshiftUserToken() *config.Rule {
 		`oc login --token=sha256~_xxxxxx_xxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxx-X \
     --server=https://api.${zone}.appuio.cloud:6443`,
 	}
-	return validate(r, tps, fps)
+	return utils.Validate(r, tps, fps)
 }

+ 11 - 10
cmd/generate/config/rules/plaid.go

@@ -2,6 +2,7 @@ package rules
 
 import (
 	"fmt"
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
@@ -12,7 +13,7 @@ func PlaidAccessID() *config.Rule {
 	r := config.Rule{
 		RuleID:      "plaid-client-id",
 		Description: "Uncovered a Plaid Client ID, which could lead to unauthorized financial service integrations and data breaches.",
-		Regex:       generateSemiGenericRegex([]string{"plaid"}, alphaNumeric("24"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"plaid"}, utils.AlphaNumeric("24"), true),
 
 		Entropy: 3.5,
 		Keywords: []string{
@@ -22,9 +23,9 @@ func PlaidAccessID() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("plaid", secrets.NewSecret(alphaNumeric("24"))),
+		utils.GenerateSampleSecret("plaid", secrets.NewSecret(utils.AlphaNumeric("24"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func PlaidSecretKey() *config.Rule {
@@ -32,7 +33,7 @@ func PlaidSecretKey() *config.Rule {
 	r := config.Rule{
 		RuleID:      "plaid-secret-key",
 		Description: "Detected a Plaid Secret key, risking unauthorized access to financial accounts and sensitive transaction data.",
-		Regex:       generateSemiGenericRegex([]string{"plaid"}, alphaNumeric("30"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"plaid"}, utils.AlphaNumeric("30"), true),
 
 		Entropy: 3.5,
 		Keywords: []string{
@@ -42,9 +43,9 @@ func PlaidSecretKey() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("plaid", secrets.NewSecret(alphaNumeric("30"))),
+		utils.GenerateSampleSecret("plaid", secrets.NewSecret(utils.AlphaNumeric("30"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func PlaidAccessToken() *config.Rule {
@@ -52,8 +53,8 @@ func PlaidAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "plaid-api-token",
 		Description: "Discovered a Plaid API Token, potentially compromising financial data aggregation and banking services.",
-		Regex: generateSemiGenericRegex([]string{"plaid"},
-			fmt.Sprintf("access-(?:sandbox|development|production)-%s", hex8_4_4_4_12()), true),
+		Regex: utils.GenerateSemiGenericRegex([]string{"plaid"},
+			fmt.Sprintf("access-(?:sandbox|development|production)-%s", utils.Hex8_4_4_4_12()), true),
 
 		Keywords: []string{
 			"plaid",
@@ -62,7 +63,7 @@ func PlaidAccessToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("plaid", secrets.NewSecret(fmt.Sprintf("access-(?:sandbox|development|production)-%s", hex8_4_4_4_12()))),
+		utils.GenerateSampleSecret("plaid", secrets.NewSecret(fmt.Sprintf("access-(?:sandbox|development|production)-%s", utils.Hex8_4_4_4_12()))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 16 - 15
cmd/generate/config/rules/planetscale.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func PlanetScalePassword() *config.Rule {
 	r := config.Rule{
 		RuleID:      "planetscale-password",
 		Description: "Discovered a PlanetScale password, which could lead to unauthorized database operations and data breaches.",
-		Regex:       generateUniqueTokenRegex(`pscale_pw_(?i)[a-z0-9=\-_\.]{32,64}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`pscale_pw_(?i)[a-z0-9=\-_\.]{32,64}`, true),
 
 		Keywords: []string{
 			"pscale_pw_",
@@ -19,11 +20,11 @@ func PlanetScalePassword() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("planetScalePassword", "pscale_pw_"+secrets.NewSecret(alphaNumericExtended("32"))),
-		generateSampleSecret("planetScalePassword", "pscale_pw_"+secrets.NewSecret(alphaNumericExtended("43"))),
-		generateSampleSecret("planetScalePassword", "pscale_pw_"+secrets.NewSecret(alphaNumericExtended("64"))),
+		utils.GenerateSampleSecret("planetScalePassword", "pscale_pw_"+secrets.NewSecret(utils.AlphaNumericExtended("32"))),
+		utils.GenerateSampleSecret("planetScalePassword", "pscale_pw_"+secrets.NewSecret(utils.AlphaNumericExtended("43"))),
+		utils.GenerateSampleSecret("planetScalePassword", "pscale_pw_"+secrets.NewSecret(utils.AlphaNumericExtended("64"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func PlanetScaleAPIToken() *config.Rule {
@@ -31,7 +32,7 @@ func PlanetScaleAPIToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "planetscale-api-token",
 		Description: "Identified a PlanetScale API token, potentially compromising database management and operations.",
-		Regex:       generateUniqueTokenRegex(`pscale_tkn_(?i)[a-z0-9=\-_\.]{32,64}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`pscale_tkn_(?i)[a-z0-9=\-_\.]{32,64}`, true),
 
 		Keywords: []string{
 			"pscale_tkn_",
@@ -40,11 +41,11 @@ func PlanetScaleAPIToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("planetScalePassword", "pscale_tkn_"+secrets.NewSecret(alphaNumericExtended("32"))),
-		generateSampleSecret("planetScalePassword", "pscale_tkn_"+secrets.NewSecret(alphaNumericExtended("43"))),
-		generateSampleSecret("planetScalePassword", "pscale_tkn_"+secrets.NewSecret(alphaNumericExtended("64"))),
+		utils.GenerateSampleSecret("planetScalePassword", "pscale_tkn_"+secrets.NewSecret(utils.AlphaNumericExtended("32"))),
+		utils.GenerateSampleSecret("planetScalePassword", "pscale_tkn_"+secrets.NewSecret(utils.AlphaNumericExtended("43"))),
+		utils.GenerateSampleSecret("planetScalePassword", "pscale_tkn_"+secrets.NewSecret(utils.AlphaNumericExtended("64"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func PlanetScaleOAuthToken() *config.Rule {
@@ -52,7 +53,7 @@ func PlanetScaleOAuthToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "planetscale-oauth-token",
 		Description: "Found a PlanetScale OAuth token, posing a risk to database access control and sensitive data integrity.",
-		Regex:       generateUniqueTokenRegex(`pscale_oauth_(?i)[a-z0-9=\-_\.]{32,64}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`pscale_oauth_(?i)[a-z0-9=\-_\.]{32,64}`, true),
 
 		Keywords: []string{
 			"pscale_oauth_",
@@ -61,9 +62,9 @@ func PlanetScaleOAuthToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("planetScalePassword", "pscale_oauth_"+secrets.NewSecret(alphaNumericExtended("32"))),
-		generateSampleSecret("planetScalePassword", "pscale_oauth_"+secrets.NewSecret(alphaNumericExtended("43"))),
-		generateSampleSecret("planetScalePassword", "pscale_oauth_"+secrets.NewSecret(alphaNumericExtended("64"))),
+		utils.GenerateSampleSecret("planetScalePassword", "pscale_oauth_"+secrets.NewSecret(utils.AlphaNumericExtended("32"))),
+		utils.GenerateSampleSecret("planetScalePassword", "pscale_oauth_"+secrets.NewSecret(utils.AlphaNumericExtended("43"))),
+		utils.GenerateSampleSecret("planetScalePassword", "pscale_oauth_"+secrets.NewSecret(utils.AlphaNumericExtended("64"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/postman.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func PostManAPI() *config.Rule {
 	r := config.Rule{
 		RuleID:      "postman-api-token",
 		Description: "Uncovered a Postman API token, potentially compromising API testing and development workflows.",
-		Regex:       generateUniqueTokenRegex(`PMAK-(?i)[a-f0-9]{24}\-[a-f0-9]{34}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`PMAK-(?i)[a-f0-9]{24}\-[a-f0-9]{34}`, true),
 
 		Keywords: []string{
 			"PMAK-",
@@ -19,7 +20,7 @@ func PostManAPI() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("postmanAPItoken", "PMAK-"+secrets.NewSecret(hex("24"))+"-"+secrets.NewSecret(hex("34"))),
+		utils.GenerateSampleSecret("postmanAPItoken", "PMAK-"+secrets.NewSecret(utils.Hex("24"))+"-"+secrets.NewSecret(utils.Hex("34"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/prefect.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func Prefect() *config.Rule {
 	r := config.Rule{
 		RuleID:      "prefect-api-token",
 		Description: "Detected a Prefect API token, risking unauthorized access to workflow management and automation services.",
-		Regex:       generateUniqueTokenRegex(`pnu_[a-z0-9]{36}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`pnu_[a-z0-9]{36}`, true),
 
 		Keywords: []string{
 			"pnu_",
@@ -19,7 +20,7 @@ func Prefect() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("api-token", "pnu_"+secrets.NewSecret(alphaNumeric("36"))),
+		utils.GenerateSampleSecret("api-token", "pnu_"+secrets.NewSecret(utils.AlphaNumeric("36"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 2 - 1
cmd/generate/config/rules/privatekey.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/config"
@@ -27,5 +28,5 @@ abcdefghijklmnopqrstuvwxyz
 anything
 -----END PRIVATE KEY BLOCK-----`,
 	} // gitleaks:allow
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/pulumi.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func PulumiAPIToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "pulumi-api-token",
 		Description: "Found a Pulumi API token, posing a risk to infrastructure as code services and cloud resource management.",
-		Regex:       generateUniqueTokenRegex(`pul-[a-f0-9]{40}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`pul-[a-f0-9]{40}`, true),
 
 		Keywords: []string{
 			"pul-",
@@ -19,7 +20,7 @@ func PulumiAPIToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("pulumi-api-token", "pul-"+secrets.NewSecret(hex("40"))),
+		utils.GenerateSampleSecret("pulumi-api-token", "pul-"+secrets.NewSecret(utils.Hex("40"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/pypi.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
@@ -20,7 +21,7 @@ func PyPiUploadToken() *config.Rule {
 	}
 
 	// validate
-	tps := []string{"pypiToken := \"pypi-AgEIcHlwaS5vcmc" + secrets.NewSecret(hex("32")) +
-		secrets.NewSecret(hex("32")) + "\""}
-	return validate(r, tps, nil)
+	tps := []string{"pypiToken := \"pypi-AgEIcHlwaS5vcmc" + secrets.NewSecret(utils.Hex("32")) +
+		secrets.NewSecret(utils.Hex("32")) + "\""}
+	return utils.Validate(r, tps, nil)
 }

+ 6 - 5
cmd/generate/config/rules/rapidapi.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,8 +11,8 @@ func RapidAPIAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "rapidapi-access-token",
 		Description: "Uncovered a RapidAPI Access Token, which could lead to unauthorized access to various APIs and data services.",
-		Regex: generateSemiGenericRegex([]string{"rapidapi"},
-			alphaNumericExtendedShort("50"), true),
+		Regex: utils.GenerateSemiGenericRegex([]string{"rapidapi"},
+			utils.AlphaNumericExtendedShort("50"), true),
 
 		Keywords: []string{
 			"rapidapi",
@@ -20,8 +21,8 @@ func RapidAPIAccessToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("rapidapi",
-			secrets.NewSecret(alphaNumericExtendedShort("50"))),
+		utils.GenerateSampleSecret("rapidapi",
+			secrets.NewSecret(utils.AlphaNumericExtendedShort("50"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/readme.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func ReadMe() *config.Rule {
 	r := config.Rule{
 		RuleID:      "readme-api-token",
 		Description: "Detected a Readme API token, risking unauthorized documentation management and content exposure.",
-		Regex:       generateUniqueTokenRegex(`rdme_[a-z0-9]{70}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`rdme_[a-z0-9]{70}`, true),
 
 		Keywords: []string{
 			"rdme_",
@@ -19,7 +20,7 @@ func ReadMe() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("api-token", "rdme_"+secrets.NewSecret(alphaNumeric("70"))),
+		utils.GenerateSampleSecret("api-token", "rdme_"+secrets.NewSecret(utils.AlphaNumeric("70"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/rubygems.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func RubyGemsAPIToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "rubygems-api-token",
 		Description: "Identified a Rubygem API token, potentially compromising Ruby library distribution and package management.",
-		Regex:       generateUniqueTokenRegex(`rubygems_[a-f0-9]{48}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`rubygems_[a-f0-9]{48}`, true),
 
 		Keywords: []string{
 			"rubygems_",
@@ -19,7 +20,7 @@ func RubyGemsAPIToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("rubygemsAPIToken", "rubygems_"+secrets.NewSecret(hex("48"))),
+		utils.GenerateSampleSecret("rubygemsAPIToken", "rubygems_"+secrets.NewSecret(utils.Hex("48"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 0 - 154
cmd/generate/config/rules/rule.go

@@ -1,154 +0,0 @@
-package rules
-
-import (
-	"fmt"
-	"regexp"
-	"strings"
-
-	"github.com/rs/zerolog/log"
-	"github.com/zricethezav/gitleaks/v8/config"
-	"github.com/zricethezav/gitleaks/v8/detect"
-)
-
-const (
-	// case insensitive prefix
-	caseInsensitive = `(?i)`
-
-	// identifier prefix (just an ignore group)
-	identifierCaseInsensitivePrefix = `(?i:`
-	identifierCaseInsensitiveSuffix = `)`
-	identifierPrefix                = `(?:`
-	identifierSuffix                = `)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}`
-
-	// commonly used assignment operators or function call
-	operator = `(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)`
-
-	// boundaries for the secret
-	// \x60 = `
-	secretPrefixUnique = `\b(`
-	secretPrefix       = `(?:'|\"|\s|=|\x60){0,5}(`
-	secretSuffix       = `)(?:['|\"|\n|\r|\s|\x60|;]|$)`
-)
-
-func generateSemiGenericRegex(identifiers []string, secretRegex string, isCaseInsensitive bool) *regexp.Regexp {
-	var sb strings.Builder
-	// The identifiers should always be case-insensitive.
-	// This is inelegant but prevents an extraneous `(?i:)` from being added to the pattern; it could be removed.
-	if isCaseInsensitive {
-		sb.WriteString(caseInsensitive)
-		writeIdentifiers(&sb, identifiers)
-	} else {
-		sb.WriteString(identifierCaseInsensitivePrefix)
-		writeIdentifiers(&sb, identifiers)
-		sb.WriteString(identifierCaseInsensitiveSuffix)
-	}
-	sb.WriteString(operator)
-	sb.WriteString(secretPrefix)
-	sb.WriteString(secretRegex)
-	sb.WriteString(secretSuffix)
-	return regexp.MustCompile(sb.String())
-}
-
-func writeIdentifiers(sb *strings.Builder, identifiers []string) {
-	sb.WriteString(identifierPrefix)
-	sb.WriteString(strings.Join(identifiers, "|"))
-	sb.WriteString(identifierSuffix)
-}
-
-func generateUniqueTokenRegex(secretRegex string, isCaseInsensitive bool) *regexp.Regexp {
-	var sb strings.Builder
-	if isCaseInsensitive {
-		sb.WriteString(caseInsensitive)
-	}
-	sb.WriteString(secretPrefixUnique)
-	sb.WriteString(secretRegex)
-	sb.WriteString(secretSuffix)
-	return regexp.MustCompile(sb.String())
-}
-
-func generateSampleSecret(identifier string, secret string) string {
-	return fmt.Sprintf("%s_api_token = \"%s\"", identifier, secret)
-}
-
-func validate(r config.Rule, truePositives []string, falsePositives []string) *config.Rule {
-	// normalize keywords like in the config package
-	var keywords []string
-	for _, k := range r.Keywords {
-		keywords = append(keywords, strings.ToLower(k))
-	}
-	r.Keywords = keywords
-
-	rules := make(map[string]config.Rule)
-	rules[r.RuleID] = r
-	d := detect.NewDetector(config.Config{
-		Rules:    rules,
-		Keywords: keywords,
-	})
-	for _, tp := range truePositives {
-		if len(d.DetectString(tp)) != 1 {
-			log.Fatal().Msgf("Failed to validate. For rule ID [%s], true positive [%s] was not detected by regexp [%s]", r.RuleID, tp, r.Regex)
-		}
-	}
-	for _, fp := range falsePositives {
-		if len(d.DetectString(fp)) != 0 {
-			log.Fatal().Msgf("Failed to validate. For rule ID [%s], false positive [%s] was detected by regexp [%s]", r.RuleID, fp, r.Regex)
-		}
-	}
-	return &r
-}
-
-func validateWithPaths(r config.Rule, truePositives map[string]string, falsePositives map[string]string) *config.Rule {
-	var keywords []string
-	for _, k := range r.Keywords {
-		keywords = append(keywords, strings.ToLower(k))
-	}
-	r.Keywords = keywords
-
-	rules := make(map[string]config.Rule)
-	rules[r.RuleID] = r
-	d := detect.NewDetector(config.Config{
-		Rules:    rules,
-		Keywords: keywords,
-	})
-	for path, tp := range truePositives {
-		f := detect.Fragment{Raw: tp, FilePath: path}
-		if len(d.Detect(f)) != 1 {
-			log.Fatal().Msgf("Failed to validate. For rule ID [%s], true positive [%s] in %s was not detected by regexp [%s] path [%s]", r.RuleID, tp, path, r.Regex, r.Path)
-		}
-	}
-	for path, fp := range falsePositives {
-		f := detect.Fragment{Raw: fp, FilePath: path}
-		if len(d.Detect(f)) != 0 {
-			log.Fatal().Msgf("Failed to validate. For rule ID [%s], false positive [%s] in %s was detected by regexp [%s] path [%s]", r.RuleID, fp, path, r.Regex, r.Path)
-		}
-	}
-	return &r
-}
-
-func numeric(size string) string {
-	return fmt.Sprintf(`[0-9]{%s}`, size)
-}
-
-func hex(size string) string {
-	return fmt.Sprintf(`[a-f0-9]{%s}`, size)
-}
-
-func alphaNumeric(size string) string {
-	return fmt.Sprintf(`[a-z0-9]{%s}`, size)
-}
-
-func alphaNumericExtendedShort(size string) string {
-	return fmt.Sprintf(`[a-z0-9_-]{%s}`, size)
-}
-
-func alphaNumericExtended(size string) string {
-	return fmt.Sprintf(`[a-z0-9=_\-]{%s}`, size)
-}
-
-func alphaNumericExtendedLong(size string) string {
-	return fmt.Sprintf(`[a-z0-9\/=_\+\-]{%s}`, size)
-}
-
-func hex8_4_4_4_12() string {
-	return `[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}`
-}

+ 4 - 3
cmd/generate/config/rules/scalingo.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,14 +11,14 @@ func ScalingoAPIToken() *config.Rule {
 	r := config.Rule{
 		Description: "Found a Scalingo API token, posing a risk to cloud platform services and application deployment security.",
 		RuleID:      "scalingo-api-token",
-		Regex:       generateUniqueTokenRegex(`tk-us-[a-zA-Z0-9-_]{48}`, false),
+		Regex:       utils.GenerateUniqueTokenRegex(`tk-us-[a-zA-Z0-9-_]{48}`, false),
 		Keywords:    []string{"tk-us-"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("scalingo", "tk-us-"+secrets.NewSecret(alphaNumericExtendedShort("48"))),
+		utils.GenerateSampleSecret("scalingo", "tk-us-"+secrets.NewSecret(utils.AlphaNumericExtendedShort("48"))),
 		`scalingo_api_token = "tk-us-loys7ib9yrxcys_ta2sq85mjar6lgcsspkd9x61s7h5epf_-"`, // gitleaks:allow
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 7 - 6
cmd/generate/config/rules/sendbird.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func SendbirdAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "sendbird-access-token",
 		Description: "Uncovered a Sendbird Access Token, potentially risking unauthorized access to communication services and user data.",
-		Regex:       generateSemiGenericRegex([]string{"sendbird"}, hex("40"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"sendbird"}, utils.Hex("40"), true),
 
 		Keywords: []string{
 			"sendbird",
@@ -19,9 +20,9 @@ func SendbirdAccessToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("sendbird", secrets.NewSecret(hex("40"))),
+		utils.GenerateSampleSecret("sendbird", secrets.NewSecret(utils.Hex("40"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func SendbirdAccessID() *config.Rule {
@@ -29,7 +30,7 @@ func SendbirdAccessID() *config.Rule {
 	r := config.Rule{
 		RuleID:      "sendbird-access-id",
 		Description: "Discovered a Sendbird Access ID, which could compromise chat and messaging platform integrations.",
-		Regex:       generateSemiGenericRegex([]string{"sendbird"}, hex8_4_4_4_12(), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"sendbird"}, utils.Hex8_4_4_4_12(), true),
 
 		Keywords: []string{
 			"sendbird",
@@ -38,7 +39,7 @@ func SendbirdAccessID() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("sendbird", secrets.NewSecret(hex8_4_4_4_12())),
+		utils.GenerateSampleSecret("sendbird", secrets.NewSecret(utils.Hex8_4_4_4_12())),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/sendgrid.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func SendGridAPIToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "sendgrid-api-token",
 		Description: "Detected a SendGrid API token, posing a risk of unauthorized email service operations and data exposure.",
-		Regex:       generateUniqueTokenRegex(`SG\.(?i)[a-z0-9=_\-\.]{66}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`SG\.(?i)[a-z0-9=_\-\.]{66}`, true),
 
 		Keywords: []string{
 			"SG.",
@@ -19,7 +20,7 @@ func SendGridAPIToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("sengridAPIToken", "SG."+secrets.NewSecret(alphaNumericExtended("66"))),
+		utils.GenerateSampleSecret("sengridAPIToken", "SG."+secrets.NewSecret(utils.AlphaNumericExtended("66"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/sendinblue.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func SendInBlueAPIToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "sendinblue-api-token",
 		Description: "Identified a Sendinblue API token, which may compromise email marketing services and subscriber data privacy.",
-		Regex:       generateUniqueTokenRegex(`xkeysib-[a-f0-9]{64}\-(?i)[a-z0-9]{16}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`xkeysib-[a-f0-9]{64}\-(?i)[a-z0-9]{16}`, true),
 
 		Keywords: []string{
 			"xkeysib-",
@@ -19,7 +20,7 @@ func SendInBlueAPIToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("sendinblue", "xkeysib-"+secrets.NewSecret(hex("64"))+"-"+secrets.NewSecret(alphaNumeric("16"))),
+		utils.GenerateSampleSecret("sendinblue", "xkeysib-"+secrets.NewSecret(utils.Hex("64"))+"-"+secrets.NewSecret(utils.AlphaNumeric("16"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/sentry.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func SentryAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "sentry-access-token",
 		Description: "Found a Sentry Access Token, risking unauthorized access to error tracking services and sensitive application data.",
-		Regex:       generateSemiGenericRegex([]string{"sentry"}, hex("64"), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"sentry"}, utils.Hex("64"), true),
 
 		Keywords: []string{
 			"sentry",
@@ -19,7 +20,7 @@ func SentryAccessToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("sentry", secrets.NewSecret(hex("64"))),
+		utils.GenerateSampleSecret("sentry", secrets.NewSecret(utils.Hex("64"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 5 - 4
cmd/generate/config/rules/shippo.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func ShippoAPIToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "shippo-api-token",
 		Description: "Discovered a Shippo API token, potentially compromising shipping services and customer order data.",
-		Regex:       generateUniqueTokenRegex(`shippo_(live|test)_[a-f0-9]{40}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`shippo_(live|test)_[a-f0-9]{40}`, true),
 
 		Keywords: []string{
 			"shippo_",
@@ -19,8 +20,8 @@ func ShippoAPIToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("shippo", "shippo_live_"+secrets.NewSecret(hex("40"))),
-		generateSampleSecret("shippo", "shippo_test_"+secrets.NewSecret(hex("40"))),
+		utils.GenerateSampleSecret("shippo", "shippo_live_"+secrets.NewSecret(utils.Hex("40"))),
+		utils.GenerateSampleSecret("shippo", "shippo_test_"+secrets.NewSecret(utils.Hex("40"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 9 - 8
cmd/generate/config/rules/shopify.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
@@ -17,8 +18,8 @@ func ShopifySharedSecret() *config.Rule {
 	}
 
 	// validate
-	tps := []string{"shopifySecret := \"shpss_" + secrets.NewSecret(hex("32")) + "\""}
-	return validate(r, tps, nil)
+	tps := []string{"shopifySecret := \"shpss_" + secrets.NewSecret(utils.Hex("32")) + "\""}
+	return utils.Validate(r, tps, nil)
 }
 
 func ShopifyAccessToken() *config.Rule {
@@ -31,8 +32,8 @@ func ShopifyAccessToken() *config.Rule {
 	}
 
 	// validate
-	tps := []string{"shopifyToken := \"shpat_" + secrets.NewSecret(hex("32")) + "\""}
-	return validate(r, tps, nil)
+	tps := []string{"shopifyToken := \"shpat_" + secrets.NewSecret(utils.Hex("32")) + "\""}
+	return utils.Validate(r, tps, nil)
 }
 
 func ShopifyCustomAccessToken() *config.Rule {
@@ -45,8 +46,8 @@ func ShopifyCustomAccessToken() *config.Rule {
 	}
 
 	// validate
-	tps := []string{"shopifyToken := \"shpca_" + secrets.NewSecret(hex("32")) + "\""}
-	return validate(r, tps, nil)
+	tps := []string{"shopifyToken := \"shpca_" + secrets.NewSecret(utils.Hex("32")) + "\""}
+	return utils.Validate(r, tps, nil)
 }
 
 func ShopifyPrivateAppAccessToken() *config.Rule {
@@ -59,6 +60,6 @@ func ShopifyPrivateAppAccessToken() *config.Rule {
 	}
 
 	// validate
-	tps := []string{"shopifyToken := \"shppa_" + secrets.NewSecret(hex("32")) + "\""}
-	return validate(r, tps, nil)
+	tps := []string{"shopifyToken := \"shppa_" + secrets.NewSecret(utils.Hex("32")) + "\""}
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/sidekiq.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/config"
@@ -12,7 +13,7 @@ func SidekiqSecret() *config.Rule {
 		Description: "Discovered a Sidekiq Secret, which could lead to compromised background job processing and application data breaches.",
 		RuleID:      "sidekiq-secret",
 
-		Regex: generateSemiGenericRegex([]string{"BUNDLE_ENTERPRISE__CONTRIBSYS__COM", "BUNDLE_GEMS__CONTRIBSYS__COM"},
+		Regex: utils.GenerateSemiGenericRegex([]string{"BUNDLE_ENTERPRISE__CONTRIBSYS__COM", "BUNDLE_GEMS__CONTRIBSYS__COM"},
 			`[a-f0-9]{8}:[a-f0-9]{8}`, true),
 		Keywords: []string{"BUNDLE_ENTERPRISE__CONTRIBSYS__COM", "BUNDLE_GEMS__CONTRIBSYS__COM"},
 	}
@@ -28,7 +29,7 @@ func SidekiqSecret() *config.Rule {
 		"export BUNDLE_ENTERPRISE__CONTRIBSYS__COM=cafebabe:deadbeef;",
 		"export BUNDLE_ENTERPRISE__CONTRIBSYS__COM=cafebabe:deadbeef && echo 'hello world'",
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func SidekiqSensitiveUrl() *config.Rule {
@@ -55,5 +56,5 @@ func SidekiqSensitiveUrl() *config.Rule {
 		"http://cafeb4b3:d3adb33f@enterprise.contribsys.com:80",
 		"http://cafeb4b3:d3adb33f@enterprise.contribsys.com:80/path?param1=true&param2=false#heading1",
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 31 - 30
cmd/generate/config/rules/slack.go

@@ -2,6 +2,7 @@ package rules
 
 import (
 	"fmt"
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
@@ -28,7 +29,7 @@ func SlackBotToken() *config.Rule {
 		// https://github.com/jonz-secops/TokenTester/blob/978e9f3eabc7e9978769cfbba10735afa3bf627e/slack#LL44C27-L44C86
 		`"bot_token2": "xoxb-263594206564-2343594206574-FGqddMF8t08v8N7Oq4i57vs1MBS"`, // gitleaks:allow
 		`"bot_token3": "xoxb-4614724432022-5152386766518-O5WzjWGLG0wcCm2WPrjEmnys"`,   // gitleaks:allow
-		`"bot_token4": ` + fmt.Sprintf(`"xoxb-%s-%s-%s"`, secrets.NewSecret(numeric("13")), secrets.NewSecret(numeric("12")), secrets.NewSecret(alphaNumeric("24"))),
+		`"bot_token4": ` + fmt.Sprintf(`"xoxb-%s-%s-%s"`, secrets.NewSecret(utils.Numeric("13")), secrets.NewSecret(utils.Numeric("12")), secrets.NewSecret(utils.AlphaNumeric("24"))),
 	}
 	fps := []string{
 		"xoxb-xxxxxxxxx-xxxxxxxxxx-xxxxxxxxxxxx",
@@ -36,7 +37,7 @@ func SlackBotToken() *config.Rule {
 		"xoxb-12345-abcd234",
 		"xoxb-xoxb-my-bot-token",
 	}
-	return validate(r, tps, fps)
+	return utils.Validate(r, tps, fps)
 }
 
 // https://api.slack.com/authentication/token-types#user
@@ -61,7 +62,7 @@ func SlackUserToken() *config.Rule {
 		// https://github.com/evanyeung/terminal-slack/blob/b068f77808de72424d08b525d6cbf814849acd08/readme.md?plain=1#L66
 		`"user_token4": "xoxp-254112160503-252950188691-252375361712-6cbf56aada30951a9d310a5f23d032a0"`,    // gitleaks:allow
 		`"user_token5": "xoxp-4614724432022-4621207627011-5182682871568-1ddad9823e8528ad0f4944dfa3c6fc6c"`, // gitleaks:allow
-		`"user_token6": ` + fmt.Sprintf(`"xoxp-%s-%s-%s-%s"`, secrets.NewSecret(numeric("12")), secrets.NewSecret(numeric("13")), secrets.NewSecret(numeric("13")), secrets.NewSecret(alphaNumeric("32"))),
+		`"user_token6": ` + fmt.Sprintf(`"xoxp-%s-%s-%s-%s"`, secrets.NewSecret(utils.Numeric("12")), secrets.NewSecret(utils.Numeric("13")), secrets.NewSecret(utils.Numeric("13")), secrets.NewSecret(utils.AlphaNumeric("32"))),
 		// It's unclear what the `xoxe-` token means in this context, however, the format is similar to a user token.
 		`"url_private": "https:\/\/files.slack.com\/files-pri\/T04MCQMEXQ9-F04MAA1PKE3\/image.png?t=xoxe-4726837507825-4848681849303-4856614048758-e0b1f3d4cb371f92260edb0d9444d206"`,
 	}
@@ -74,7 +75,7 @@ func SlackUserToken() *config.Rule {
 		// This technically matches the pattern but is an obvious false positive.
 		// `"token5": "xoxp-000000000000-000000000000-000000000000-00000000000000000000000000000000"`, // gitleaks:allow
 	}
-	return validate(r, tps, fps)
+	return utils.Validate(r, tps, fps)
 }
 
 // Reference: https://api.slack.com/authentication/token-types#app
@@ -93,9 +94,9 @@ func SlackAppLevelToken() *config.Rule {
 		`"token1": "xapp-1-A052FGTS2DL-5171572773297-610b6a11f4b7eb819e87b767d80e6575a3634791acb9a9ead051da879eb5b55e"`, // gitleaks:allow
 		`"token2": "xapp-1-IEMF8IMY1OQ-4037076220459-85c370b433e366de369c4ef5abdf41253519266982439a75af74a3d68d543fb6"`, // gitleaks:allow
 		`"token3": "xapp-1-BM3V7LC51DA-1441525068281-86641a2582cd0903402ab523e5bcc53b8253098c31591e529b55b41974d2e82f"`, // gitleaks:allow
-		`"token4": ` + fmt.Sprintf(`"xapp-1-A%s-%s-%s"`, secrets.NewSecret(numeric("10")), secrets.NewSecret(numeric("13")), secrets.NewSecret(alphaNumeric("64"))),
+		`"token4": ` + fmt.Sprintf(`"xapp-1-A%s-%s-%s"`, secrets.NewSecret(utils.Numeric("10")), secrets.NewSecret(utils.Numeric("13")), secrets.NewSecret(utils.AlphaNumeric("64"))),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 // Reference: https://api.slack.com/authentication/config-tokens
@@ -111,16 +112,16 @@ func SlackConfigurationToken() *config.Rule {
 	tps := []string{
 		`"access_token1": "xoxe.xoxp-1-Mi0yLTM0MTQwNDE0MDE3Ni0zNjU5NDY0Njg4MTctNTE4MjA3NTQ5NjA4MC01NDEyOTYyODY5NzUxLThhMTBjZmI1ZWIzMGIwNTg0ZDdmMDI5Y2UxNzVlZWVhYzU2ZWQyZTZiODNjNDZiMGUxMzRlNmNjNDEwYmQxMjQ"`, // gitleaks:allow
 		`"access_token2": "xoxe.xoxp-1-Mi0yLTMxNzcwMjQ0MTcxMy0zNjU5NDY0Njg4MTctNTE1ODE1MjY5MTcxNC01MTU4MDI0MTgyOTc5LWRmY2YwY2U4ODhhNzY5ZGU5MTAyNDU4MDJjMGQ0ZDliMTZhMjNkMmEyYzliNjkzMDRlN2VjZTI4MWNiMzRkNGQ"`, // gitleaks:allow
-		`"access_token3": "xoxe.xoxp-1-` + secrets.NewSecret(alphaNumeric("163")) + `"`,
+		`"access_token3": "xoxe.xoxp-1-` + secrets.NewSecret(utils.AlphaNumeric("163")) + `"`,
 		`"access_token4": "xoxe.xoxb-1-Mi0yLTMxNzcwMjQ0MTcxMy0zNjU5NDY0Njg4MTctNTE1ODE1MjY5MTcxNC01MTU4MDI0MTgyOTc5LWRmY2YwY2U4ODhhNzY5ZGU5MTAyNDU4MDJjMGQ0ZDliMTZhMjNkMmEyYzliNjkzMDRlN2VjZTI4MWNiMzRkNGQ"`,
-		`"access_token5": "xoxe.xoxb-1-` + secrets.NewSecret(alphaNumeric("165")) + `"`,
+		`"access_token5": "xoxe.xoxb-1-` + secrets.NewSecret(utils.AlphaNumeric("165")) + `"`,
 	}
 	fps := []string{
 		"xoxe.xoxp-1-SlackAppConfigurationAccessTokenHere",
 		"xoxe.xoxp-1-RANDOMSTRINGHERE",
 		"xoxe.xoxp-1-initial",
 	}
-	return validate(r, tps, fps)
+	return utils.Validate(r, tps, fps)
 }
 
 // Reference: https://api.slack.com/authentication/config-tokens
@@ -136,10 +137,10 @@ func SlackConfigurationRefreshToken() *config.Rule {
 	tps := []string{
 		`"refresh_token1": "xoxe-1-My0xLTMxNzcwMjQ0MTcxMy01MTU4MTUyNjkxNzE0LTUxODE4NDI0MDY3MzYtMjA5MGFkOTFlZThkZWE2OGFlZDYwYWJjODNhYzAxYjA5ZjVmODBhYjgzN2QyNDdjOTNlOGY5NTg2YWM1OGM4Mg"`, // gitleaks:allow
 		`"refresh_token2": "xoxe-1-My0xLTM0MTQwNDE0MDE3Ni01MTgyMDc1NDk2MDgwLTU0MjQ1NjIwNzgxODEtNGJkYTZhYTUxY2M1ODk3ZTNkN2YzMTgxMDI1ZDQzNzgwNWY4NWQ0ODdhZGIzM2ViOGI0MTM0MjdlNGVmYzQ4Ng"`, // gitleaks:allow
-		`"refresh_token3": "xoxe-1-` + secrets.NewSecret(alphaNumeric("146")) + `"`,
+		`"refresh_token3": "xoxe-1-` + secrets.NewSecret(utils.AlphaNumeric("146")) + `"`,
 	}
 	fps := []string{"xoxe-1-xxx", "XOxE-RROAmw, Home and Garden, 5:24, 20120323"}
-	return validate(r, tps, fps)
+	return utils.Validate(r, tps, fps)
 }
 
 // Reference: https://api.slack.com/authentication/token-types#legacy_bot
@@ -171,10 +172,10 @@ func SlackLegacyBotToken() *config.Rule {
 		// https://github.com/logicmoo/logicmoo_workspace/blob/2e1794f596121c9949deb3bfbd30d5b027a51d3d/packs_sys/slack_prolog/prolog/slack_client_old.pl#L28
 		`"bot_token7": "xoxb-130154379991-ogFL0OFP3w6AwdJuK7wLojpK"`, // gitleaks:allow
 		// https://github.com/sbarski/serverless-chatbot/blob/7d556897486f3fd53795907b7e33252e5cc6b3a3/Lesson%203/serverless.yml#L38
-		`"bot_token8": "xoxb-159279836768-FOst5DLfEzmQgkz7cte5qiI"`,                                                             // gitleaks:allow
-		`"bot_token9": "xoxb-50014434-slacktokenx29U9X1bQ"`,                                                                     // gitleaks:allow
-		`"bot_token10": ` + fmt.Sprintf(`"xoxb-%s-%s`, secrets.NewSecret(numeric("10")), secrets.NewSecret(alphaNumeric("24"))), // gitleaks:allow
-		`"bot_token11": ` + fmt.Sprintf(`"xoxb-%s-%s`, secrets.NewSecret(numeric("12")), secrets.NewSecret(alphaNumeric("23"))), // gitleaks:allow
+		`"bot_token8": "xoxb-159279836768-FOst5DLfEzmQgkz7cte5qiI"`,                                                                         // gitleaks:allow
+		`"bot_token9": "xoxb-50014434-slacktokenx29U9X1bQ"`,                                                                                 // gitleaks:allow
+		`"bot_token10": ` + fmt.Sprintf(`"xoxb-%s-%s`, secrets.NewSecret(utils.Numeric("10")), secrets.NewSecret(utils.AlphaNumeric("24"))), // gitleaks:allow
+		`"bot_token11": ` + fmt.Sprintf(`"xoxb-%s-%s`, secrets.NewSecret(utils.Numeric("12")), secrets.NewSecret(utils.AlphaNumeric("23"))), // gitleaks:allow
 	}
 	fps := []string{
 		"xoxb-xxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx", // gitleaks:allow
@@ -182,7 +183,7 @@ func SlackLegacyBotToken() *config.Rule {
 		"xoxb-abcdef-abcdef",
 		// "xoxb-0000000000-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // gitleaks:allow
 	}
-	return validate(r, tps, fps)
+	return utils.Validate(r, tps, fps)
 }
 
 // Reference: https://api.slack.com/authentication/token-types#workspace
@@ -201,10 +202,10 @@ func SlackLegacyWorkspaceToken() *config.Rule {
 
 	tps := []string{
 		`"access_token": "xoxa-2-511111111-31111111111-3111111111111-e039d02840a0b9379c"`, // gitleaks:allow
-		`"access_token1": ` + fmt.Sprintf(`"xoxa-%s-%s`, secrets.NewSecret(numeric("1")), secrets.NewSecret(alphaNumeric("12"))),
-		`"access_token2": ` + fmt.Sprintf(`"xoxa-%s`, secrets.NewSecret(alphaNumeric("12"))),
-		`"refresh_token1": ` + fmt.Sprintf(`"xoxr-%s-%s`, secrets.NewSecret(numeric("1")), secrets.NewSecret(alphaNumeric("12"))),
-		`"refresh_token2": ` + fmt.Sprintf(`"xoxr-%s`, secrets.NewSecret(alphaNumeric("12"))),
+		`"access_token1": ` + fmt.Sprintf(`"xoxa-%s-%s`, secrets.NewSecret(utils.Numeric("1")), secrets.NewSecret(utils.AlphaNumeric("12"))),
+		`"access_token2": ` + fmt.Sprintf(`"xoxa-%s`, secrets.NewSecret(utils.AlphaNumeric("12"))),
+		`"refresh_token1": ` + fmt.Sprintf(`"xoxr-%s-%s`, secrets.NewSecret(utils.Numeric("1")), secrets.NewSecret(utils.AlphaNumeric("12"))),
+		`"refresh_token2": ` + fmt.Sprintf(`"xoxr-%s`, secrets.NewSecret(utils.AlphaNumeric("12"))),
 	}
 	fps := []string{
 		// "xoxa-faketoken",
@@ -212,7 +213,7 @@ func SlackLegacyWorkspaceToken() *config.Rule {
 		// "XOXa-nx991k",
 		"https://github.com/xoxa-nyc/xoxa-nyc.github.io/blob/master/README.md",
 	}
-	return validate(r, tps, fps)
+	return utils.Validate(r, tps, fps)
 }
 
 // References:
@@ -241,14 +242,14 @@ func SlackLegacyToken() *config.Rule {
 		`"access_token4": "xoxs-4829527689-4829527691-4814341714-d0346ec616"`, // gitleaks:allow
 		// https://github.com/ericvanderwal/general-playmaker/blob/34bd8e82e2d7b16ca9cc825d0c9d383b8378b550/Logic/setrandomseedtype.cs#LL783C15-L783C69
 		`"access_token5": "xoxs-155191149137-155868813314-338998331396-9f6d235915"`, // gitleaks:allow
-		`"access_token6": "xoxs-` + fmt.Sprintf("%s-%s-%s-%s", secrets.NewSecret(numeric("10")), secrets.NewSecret(numeric("10")), secrets.NewSecret(numeric("10")), secrets.NewSecret(hex("10"))) + `"`,
+		`"access_token6": "xoxs-` + fmt.Sprintf("%s-%s-%s-%s", secrets.NewSecret(utils.Numeric("10")), secrets.NewSecret(utils.Numeric("10")), secrets.NewSecret(utils.Numeric("10")), secrets.NewSecret(utils.Hex("10"))) + `"`,
 		`"access_token7": "xoxo-523423-234243-234233-e039d02840a0b9379c"`, // gitleaks:allow
 	}
 	fps := []string{
 		"https://indieweb.org/images/3/35/2018-250-xoxo-indieweb-1.jpg",
 		"https://lh3.googleusercontent.com/-tWXjX3LUD6w/Ua4La_N5E2I/AAAAAAAAACg/qcm19xbEYa4/s640/EXO-XOXO-teaser-exo-k-34521098-720-516.jpg",
 	}
-	return validate(r, tps, fps)
+	return utils.Validate(r, tps, fps)
 }
 
 func SlackWebHookUrl() *config.Rule {
@@ -266,16 +267,16 @@ func SlackWebHookUrl() *config.Rule {
 
 	// validate
 	tps := []string{
-		"hooks.slack.com/services/" + secrets.NewSecret(alphaNumeric("44")),
-		"http://hooks.slack.com/services/" + secrets.NewSecret(alphaNumeric("45")),
-		"https://hooks.slack.com/services/" + secrets.NewSecret(alphaNumeric("46")),
+		"hooks.slack.com/services/" + secrets.NewSecret(utils.AlphaNumeric("44")),
+		"http://hooks.slack.com/services/" + secrets.NewSecret(utils.AlphaNumeric("45")),
+		"https://hooks.slack.com/services/" + secrets.NewSecret(utils.AlphaNumeric("46")),
 		"http://hooks.slack.com/services/T024TTTTT/BBB72BBL/AZAAA9u0pA4ad666eMgbi555",   // gitleaks:allow
 		"https://hooks.slack.com/services/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", // gitleaks:allow
-		"hooks.slack.com/workflows/" + secrets.NewSecret(alphaNumeric("44")),
-		"http://hooks.slack.com/workflows/" + secrets.NewSecret(alphaNumeric("45")),
-		"https://hooks.slack.com/workflows/" + secrets.NewSecret(alphaNumeric("46")),
+		"hooks.slack.com/workflows/" + secrets.NewSecret(utils.AlphaNumeric("44")),
+		"http://hooks.slack.com/workflows/" + secrets.NewSecret(utils.AlphaNumeric("45")),
+		"https://hooks.slack.com/workflows/" + secrets.NewSecret(utils.AlphaNumeric("46")),
 		"https://hooks.slack.com/workflows/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", // gitleaks:allow
 		"http://hooks.slack.com/workflows/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",    // gitleaks:allow
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 3 - 2
cmd/generate/config/rules/snyk.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
 
@@ -19,7 +20,7 @@ func Snyk() *config.Rule {
 		Description: "Uncovered a Snyk API token, potentially compromising software vulnerability scanning and code security.",
 		RuleID:      "snyk-api-token",
 
-		Regex:    generateSemiGenericRegex(keywords, hex8_4_4_4_12(), true),
+		Regex:    utils.GenerateSemiGenericRegex(keywords, utils.Hex8_4_4_4_12(), true),
 		Keywords: keywords,
 	}
 
@@ -35,5 +36,5 @@ func Snyk() *config.Rule {
 		`SNYK_API_TOKEN = "12345678-ABCD-ABCD-ABCD-1234567890AB"`,   // gitleaks:allow
 		`SNYK_OAUTH_TOKEN = "12345678-ABCD-ABCD-ABCD-1234567890AB"`, // gitleaks:allow
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 7 - 6
cmd/generate/config/rules/square.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,17 +11,17 @@ func SquareAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "square-access-token",
 		Description: "Detected a Square Access Token, risking unauthorized payment processing and financial transaction exposure.",
-		Regex:       generateUniqueTokenRegex(`(EAAA|sq0atp-)[0-9A-Za-z\-_]{22,60}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`(EAAA|sq0atp-)[0-9A-Za-z\-_]{22,60}`, true),
 		Keywords:    []string{"sq0atp-", "EAAA"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("square", secrets.NewSecret(`sq0atp-[0-9A-Za-z\-_]{22}`)),
+		utils.GenerateSampleSecret("square", secrets.NewSecret(`sq0atp-[0-9A-Za-z\-_]{22}`)),
 		"ARG token=sq0atp-812erere3wewew45678901",                                    // gitleaks:allow
 		"ARG token=EAAAlsBxkkVgvmr7FasTFbM6VUGZ31EJ4jZKTJZySgElBDJ_wyafHuBFquFexY7E", // gitleaks:allow",
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }
 
 func SquareSecret() *config.Rule {
@@ -28,14 +29,14 @@ func SquareSecret() *config.Rule {
 	r := config.Rule{
 		RuleID:      "square-secret",
 		Description: "Square Secret",
-		Regex:       generateUniqueTokenRegex(`sq0csp-[0-9A-Za-z\\-_]{43}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`sq0csp-[0-9A-Za-z\\-_]{43}`, true),
 		Keywords:    []string{"sq0csp-"},
 	}
 
 	// validate
 	tps := []string{
-		generateSampleSecret("square", secrets.NewSecret(`sq0csp-[0-9A-Za-z\\-_]{43}`)),
+		utils.GenerateSampleSecret("square", secrets.NewSecret(`sq0csp-[0-9A-Za-z\\-_]{43}`)),
 		`value: "sq0csp-0p9h7g6f4s3s3s3-4a3ardgwa6ADRDJDDKUFYDYDYDY"`, // gitleaks:allow
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 4 - 3
cmd/generate/config/rules/squarespace.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func SquareSpaceAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "squarespace-access-token",
 		Description: "Identified a Squarespace Access Token, which may compromise website management and content control on Squarespace.",
-		Regex:       generateSemiGenericRegex([]string{"squarespace"}, hex8_4_4_4_12(), true),
+		Regex:       utils.GenerateSemiGenericRegex([]string{"squarespace"}, utils.Hex8_4_4_4_12(), true),
 
 		Keywords: []string{
 			"squarespace",
@@ -19,7 +20,7 @@ func SquareSpaceAccessToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		generateSampleSecret("squarespace", secrets.NewSecret(hex8_4_4_4_12())),
+		utils.GenerateSampleSecret("squarespace", secrets.NewSecret(utils.Hex8_4_4_4_12())),
 	}
-	return validate(r, tps, nil)
+	return utils.Validate(r, tps, nil)
 }

+ 5 - 4
cmd/generate/config/rules/stripe.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
@@ -10,7 +11,7 @@ func StripeAccessToken() *config.Rule {
 	r := config.Rule{
 		Description: "Found a Stripe Access Token, posing a risk to payment processing services and sensitive financial data.",
 		RuleID:      "stripe-access-token",
-		Regex:       generateUniqueTokenRegex(`(sk|rk)_(test|live|prod)_[0-9a-z]{10,99}`, true),
+		Regex:       utils.GenerateUniqueTokenRegex(`(sk|rk)_(test|live|prod)_[0-9a-z]{10,99}`, true),
 		Keywords: []string{
 			"sk_test",
 			"sk_live",
@@ -23,10 +24,10 @@ func StripeAccessToken() *config.Rule {
 
 	// validate
 	tps := []string{
-		"stripeToken := \"sk_test_" + secrets.NewSecret(alphaNumeric("30")) + "\"",
+		"stripeToken := \"sk_test_" + secrets.NewSecret(utils.AlphaNumeric("30")) + "\"",
 		"sk_test_51OuEMLAlTWGaDypq4P5cuDHbuKeG4tAGPYHJpEXQ7zE8mKK3jkhTFPvCxnSSK5zB5EQZrJsYdsatNmAHGgb0vSKD00GTMSWRHs", // gitleaks:allow
 		"rk_prod_51OuEMLAlTWGaDypquDn9aZigaJOsa9NR1w1BxZXs9JlYsVVkv5XDu6aLmAxwt5Tgun5WcSwQMKzQyqV16c9iD4sx00BRijuoon", // gitleaks:allow
 	}
-	fps := []string{"nonMatchingToken := \"task_test_" + secrets.NewSecret(alphaNumeric("30")) + "\""}
-	return validate(r, tps, fps)
+	fps := []string{"nonMatchingToken := \"task_test_" + secrets.NewSecret(utils.AlphaNumeric("30")) + "\""}
+	return utils.Validate(r, tps, fps)
 }

+ 8 - 7
cmd/generate/config/rules/sumologic.go

@@ -1,6 +1,7 @@
 package rules
 
 import (
+	"github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
@@ -13,7 +14,7 @@ func SumoLogicAccessID() *config.Rule {
 		RuleID:      "sumologic-access-id",
 		Description: "Discovered a SumoLogic Access ID, potentially compromising log management services and data analytics integrity.",
 		// TODO: Make 'su' case-sensitive.
-		Regex: generateSemiGenericRegex([]string{"sumo"},
+		Regex: utils.GenerateSemiGenericRegex([]string{"sumo"},
 			"su[a-zA-Z0-9]{12}", false),
 
 		Entropy: 3,
@@ -34,7 +35,7 @@ func SumoLogicAccessID() *config.Rule {
 		`sumologic_access_id = "sug5XpdpaoxtOH"`,     // gitleaks:allow
 		`export SUMOLOGIC_ACCESSID="suDbJw97o9WVo0"`, // gitleaks:allow
 		`SUMO_ACCESS_ID = "suGyI5imvADdvU"`,          // gitleaks:allow
-		generateSampleSecret("sumo", "su"+secrets.NewSecret(alphaNumeric("12"))),
+		utils.GenerateSampleSecret("sumo", "su"+secrets.NewSecret(utils.AlphaNumeric("12"))),
 	}
 	fps := []string{
 		`- (NSNumber *)sumOfProperty:(NSString *)property;`,
@@ -47,7 +48,7 @@ func SumoLogicAccessID() *config.Rule {
 		`SUMOLOGIC_ACCESSID: ${SUMOLOGIC_ACCESSID}`,
 		`export SUMOLOGIC_ACCESSID=XXXXXXXXXXXXXX`, // gitleaks:allow
 	}
-	return validate(r, tps, fps)
+	return utils.Validate(r, tps, fps)
 }
 
 func SumoLogicAccessToken() *config.Rule {
@@ -55,8 +56,8 @@ func SumoLogicAccessToken() *config.Rule {
 	r := config.Rule{
 		RuleID:      "sumologic-access-token",
 		Description: "Uncovered a SumoLogic Access Token, which could lead to unauthorized access to log data and analytics insights.",
-		Regex: generateSemiGenericRegex([]string{"sumo"},
-			alphaNumeric("64"), true),
+		Regex: utils.GenerateSemiGenericRegex([]string{"sumo"},
+			utils.AlphaNumeric("64"), true),
 
 		Entropy: 3,
 		Keywords: []string{
@@ -70,7 +71,7 @@ func SumoLogicAccessToken() *config.Rule {
 		`SUMO_ACCESS_KEY: gxq3rJQkS6qovOg9UY2Q70iH1jFZx0WBrrsiAYv4XHodogAwTKyLzvFK4neRN8Dk`,             // gitleaks:allow
 		`SUMOLOGIC_ACCESSKEY: 9RITWb3I3kAnSyUolcVJq4gwM17JRnQK8ugRaixFfxkdSl8ys17ZtEL3LotESKB7`,         // gitleaks:allow
 		`sumo_access_key = "3Kof2VffNQ0QgYIhXUPJosVlCaQKm2hfpWE6F1fT9YGY74blQBIPsrkCcf1TwKE5"`,          // gitleaks:allow
-		generateSampleSecret("sumo", secrets.NewSecret(alphaNumeric("64"))),
+		utils.GenerateSampleSecret("sumo", secrets.NewSecret(utils.AlphaNumeric("64"))),
 	}
 	fps := []string{
 		`#   SUMO_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`, // gitleaks:allow
@@ -80,5 +81,5 @@ func SumoLogicAccessToken() *config.Rule {
 		`sumo_access_key   = "<SUMOLOGIC ACCESS KEY>"`,
 		`SUMO_ACCESS_KEY: AbCeFG123`,
 	}
-	return validate(r, tps, fps)
+	return utils.Validate(r, tps, fps)
 }

Некоторые файлы не были показаны из-за большого количества измененных файлов