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

feat(slack): update token regex (#1161)

Richard Gomez 2 лет назад
Родитель
Сommit
463d24618f

+ 9 - 2
cmd/generate/config/main.go

@@ -143,8 +143,15 @@ func main() {
 	configRules = append(configRules, rules.ShopifySharedSecret())
 	configRules = append(configRules, rules.SidekiqSecret())
 	configRules = append(configRules, rules.SidekiqSensitiveUrl())
-	configRules = append(configRules, rules.SlackAccessToken())
-	configRules = append(configRules, rules.SlackWebHook())
+	configRules = append(configRules, rules.SlackBotToken())
+	configRules = append(configRules, rules.SlackUserToken())
+	configRules = append(configRules, rules.SlackAppLevelToken())
+	configRules = append(configRules, rules.SlackConfigurationToken())
+	configRules = append(configRules, rules.SlackConfigurationRefreshToken())
+	configRules = append(configRules, rules.SlackLegacyBotToken())
+	configRules = append(configRules, rules.SlackLegacyWorkspaceToken())
+	configRules = append(configRules, rules.SlackLegacyToken())
+	configRules = append(configRules, rules.SlackWebHookUrl())
 	configRules = append(configRules, rules.Snyk())
 	configRules = append(configRules, rules.StripeAccessToken())
 	configRules = append(configRules, rules.SquareAccessToken())

+ 1 - 1
cmd/generate/config/rules/rule.go

@@ -75,7 +75,7 @@ func validate(r config.Rule, truePositives []string, falsePositives []string) *c
 	}
 	for _, fp := range falsePositives {
 		if len(d.DetectString(fp)) != 0 {
-			log.Fatal().Msgf("Failed to validate (fp) [%s]", r.RuleID)
+			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

+ 243 - 13
cmd/generate/config/rules/slack.go

@@ -1,42 +1,264 @@
 package rules
 
 import (
+	"fmt"
 	"regexp"
 
 	"github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
 	"github.com/zricethezav/gitleaks/v8/config"
 )
 
-func SlackAccessToken() *config.Rule {
+// https://api.slack.com/authentication/token-types#bot
+func SlackBotToken() *config.Rule {
 	// define rule
 	r := config.Rule{
-		Description: "Slack token",
-		RuleID:      "slack-access-token",
+		Description: "Slack Bot token",
+		RuleID:      "slack-bot-token",
 		Regex: regexp.MustCompile(
-			"xox[baprs]-([0-9a-zA-Z]{10,48})"),
+			`(xoxb-[0-9]{10,13}\-[0-9]{10,13}[a-zA-Z0-9-]*)`),
 		Keywords: []string{
 			"xoxb",
+		},
+	}
+
+	// validate
+	tps := []string{
+		// https://github.com/metabase/metabase/blob/74cfb332140680425c7d37d347854160cc997ea8/frontend/src/metabase/admin/settings/slack/components/SlackForm/SlackForm.tsx#L47
+		`"bot_token1": "xoxb-781236542736-2364535789652-GkwFDQoHqzXDVsC6GzqYUypD"`, // gitleaks:allow
+		// 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"))),
+	}
+	fps := []string{
+		"xoxb-xxxxxxxxx-xxxxxxxxxx-xxxxxxxxxxxx",
+		"xoxb-xxx",
+		"xoxb-12345-abcd234",
+		"xoxb-xoxb-my-bot-token",
+	}
+	return validate(r, tps, fps)
+}
+
+// https://api.slack.com/authentication/token-types#user
+func SlackUserToken() *config.Rule {
+	// define rule
+	r := config.Rule{
+		Description: "Slack User",
+		RuleID:      "slack-user-token",
+		// The last segment seems to be consistently 32 characters. I've made it 28-34 just in case.
+		Regex:    regexp.MustCompile(`(xox[pe](?:-[0-9]{10,13}){3}-[a-zA-Z0-9-]{28,34})`),
+		Keywords: []string{"xoxp-", "xoxe-"},
+	}
+
+	// validate
+	tps := []string{
+		// https://github.com/jonz-secops/TokenTester/blob/978e9f3eabc7e9978769cfbba10735afa3bf627e/slack#L25
+		`"user_token1": "xoxp-41684372915-1320496754-45609968301-e708ba56e1517a99f6b5fb07349476ef"`, // gitleaks:allow
+		// https://github.com/praetorian-inc/noseyparker/blob/16e0e5768fd14ea54f6c9a058566184d88343bb4/crates/noseyparker/data/default/rules/slack.yml#L29
+		`"user_token2": "xoxp-283316862324-298911817009-298923149681-44f585044dace54f5701618e97cd1c0b"`, // gitleaks:allow
+		// https://github.com/CloudBoost/cloudboost/blob/7ba2ed17099fa85e6fc652302822601283c6fa13/user-service/services/mailService.js#LL248C17-L248C92
+		`"user_token3": "xoxp-11873098179-111402824422-234336993777-b96c9fb3b69f82ebb79d12f280779de1"`, // gitleaks:allow
+		// 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"))),
+		// 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"`,
+	}
+	fps := []string{
+		`https://docs.google.com/document/d/1W7KCxOxP-1Fy5EyF2lbJGE2WuKmu5v0suYqoHas1jRM`,
+		`"token1": "xoxp-1234567890"`, // gitleaks:allow
+		`"token2": "xoxp-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"`, // gitleaks:allow
+		`"token3": "xoxp-1234-1234-1234-4ddbc191d40ee098cbaae6f3523ada2d"`,                    // gitleaks:allow
+		`"token4": "xoxp-572370529330-573807301142-572331691188-####################"`,        // gitleaks:allow
+		// This technically matches the pattern but is an obvious false positive.
+		// `"token5": "xoxp-000000000000-000000000000-000000000000-00000000000000000000000000000000"`, // gitleaks:allow
+	}
+	return validate(r, tps, fps)
+}
+
+// Reference: https://api.slack.com/authentication/token-types#app
+func SlackAppLevelToken() *config.Rule {
+	// define rule
+	r := config.Rule{
+		Description: "Slack App-level token",
+		RuleID:      "slack-app-token",
+		// This regex is based on a limited number of examples and may not be 100% accurate.
+		Regex:    regexp.MustCompile(`(?i)(xapp-\d-[A-Z0-9]+-\d+-[a-z0-9]+)`),
+		Keywords: []string{"xapp"},
+	}
+
+	tps := []string{
+		// https://github.com/jonz-secops/TokenTester/blob/978e9f3eabc7e9978769cfbba10735afa3bf627e/slack#L17
+		`"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"))),
+	}
+	return validate(r, tps, nil)
+}
+
+// Reference: https://api.slack.com/authentication/config-tokens
+func SlackConfigurationToken() *config.Rule {
+	// define rule
+	r := config.Rule{
+		Description: "Slack Configuration access token",
+		RuleID:      "slack-config-access-token",
+		Regex:       regexp.MustCompile(`(?i)(xoxe.xox[bp]-\d-[A-Z0-9]{163,166})`),
+		Keywords:    []string{"xoxe.xoxb-", "xoxe.xoxp-"},
+	}
+
+	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_token4": "xoxe.xoxb-1-Mi0yLTMxNzcwMjQ0MTcxMy0zNjU5NDY0Njg4MTctNTE1ODE1MjY5MTcxNC01MTU4MDI0MTgyOTc5LWRmY2YwY2U4ODhhNzY5ZGU5MTAyNDU4MDJjMGQ0ZDliMTZhMjNkMmEyYzliNjkzMDRlN2VjZTI4MWNiMzRkNGQ"`,
+		`"access_token5": "xoxe.xoxb-1-` + secrets.NewSecret(alphaNumeric("165")) + `"`,
+	}
+	fps := []string{
+		"xoxe.xoxp-1-SlackAppConfigurationAccessTokenHere",
+		"xoxe.xoxp-1-RANDOMSTRINGHERE",
+		"xoxe.xoxp-1-initial",
+	}
+	return validate(r, tps, fps)
+}
+
+// Reference: https://api.slack.com/authentication/config-tokens
+func SlackConfigurationRefreshToken() *config.Rule {
+	// define rule
+	r := config.Rule{
+		Description: "Slack Configuration refresh token",
+		RuleID:      "slack-config-refresh-token",
+		Regex:       regexp.MustCompile(`(?i)(xoxe-\d-[A-Z0-9]{146})`),
+		Keywords:    []string{"xoxe-"},
+	}
+
+	tps := []string{
+		`"refresh_token1": "xoxe-1-My0xLTMxNzcwMjQ0MTcxMy01MTU4MTUyNjkxNzE0LTUxODE4NDI0MDY3MzYtMjA5MGFkOTFlZThkZWE2OGFlZDYwYWJjODNhYzAxYjA5ZjVmODBhYjgzN2QyNDdjOTNlOGY5NTg2YWM1OGM4Mg"`, // gitleaks:allow
+		`"refresh_token2": "xoxe-1-My0xLTM0MTQwNDE0MDE3Ni01MTgyMDc1NDk2MDgwLTU0MjQ1NjIwNzgxODEtNGJkYTZhYTUxY2M1ODk3ZTNkN2YzMTgxMDI1ZDQzNzgwNWY4NWQ0ODdhZGIzM2ViOGI0MTM0MjdlNGVmYzQ4Ng"`, // gitleaks:allow
+		`"refresh_token3": "xoxe-1-` + secrets.NewSecret(alphaNumeric("146")) + `"`,
+	}
+	fps := []string{"xoxe-1-xxx", "XOxE-RROAmw, Home and Garden, 5:24, 20120323"}
+	return validate(r, tps, fps)
+}
+
+// Reference: https://api.slack.com/authentication/token-types#legacy_bot
+func SlackLegacyBotToken() *config.Rule {
+	r := config.Rule{
+		Description: "Slack Legacy bot token",
+		RuleID:      "slack-legacy-bot-token",
+		// This rule is based off the limited information I could find and may not be 100% accurate.
+		Regex: regexp.MustCompile(
+			`(xoxb-[0-9]{8,14}\-[a-zA-Z0-9]{18,26})`),
+		Keywords: []string{
+			"xoxb",
+		},
+	}
+
+	tps := []string{
+		// https://github.com/jonz-secops/TokenTester/blob/978e9f3eabc7e9978769cfbba10735afa3bf627e/slack#LL42C38-L42C80
+		`"bot_token1": "xoxb-263594206564-FGqddMF8t08v8N7Oq4i57vs1"`, // gitleaks:allow
+		// https://heejune.me/2018/08/01/crashdump-analysis-automation-using-slackbot-python-cdb-from-windows/
+		`"bot_token2": "xoxb-282029623751-BVtmnS3BQitmjZvjpQL7PSGP"`, // gitleaks:allow
+		// https://github.com/praetorian-inc/noseyparker/blob/16e0e5768fd14ea54f6c9a058566184d88343bb4/crates/noseyparker/data/default/rules/slack.yml#L15
+		`"bot_token3": "xoxb-47834520726-N3otsrwj8Cf99cs8GhiRZsX1"`, // gitleaks:allow
+		// https://github.com/pulumi/examples/blob/32d9047c19c2a9380c04e57a764321c25eef45b0/aws-js-sqs-slack/README.md?plain=1#L39
+		`"bot_token4": "xoxb-123456789012-Xw937qtWSXJss1lFaKe"`, // gitleaks:allow
+		// https://github.com/ilyasProgrammer/Odoo-eBay-Amazon/blob/a9c4a8a7548b19027bc0fd904f8ae9249248a293/custom_logging/models.py#LL9C24-L9C66
+		`"bot_token5": "xoxb-312554961652-uSmliU84rFhnUSBq9YdKh6lS"`, // gitleaks:allow
+		// https://github.com/jay-johnson/sci-pype/blob/6bff42ea4eb32d35b9f223db312e4cd0d3911100/src/pycore.py#L37
+		`"bot_token6": "xoxb-51351043345-Lzwmto5IMVb8UK36MghZYMEi"`, // gitleaks:allow
+		// 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
+	}
+	fps := []string{
+		"xoxb-xxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx", // gitleaks:allow
+		"xoxb-Slack_BOT_TOKEN",
+		"xoxb-abcdef-abcdef",
+		// "xoxb-0000000000-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // gitleaks:allow
+	}
+	return validate(r, tps, fps)
+}
+
+// Reference: https://api.slack.com/authentication/token-types#workspace
+func SlackLegacyWorkspaceToken() *config.Rule {
+	r := config.Rule{
+		Description: "Slack Legacy Workspace token",
+		RuleID:      "slack-legacy-workspace-token",
+		// This is by far the least confident pattern.
+		Regex: regexp.MustCompile(
+			`(xox[ar]-(?:\d-)?[0-9a-zA-Z]{8,48})`),
+		Keywords: []string{
 			"xoxa",
-			"xoxp",
 			"xoxr",
-			"xoxs",
 		},
 	}
 
+	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"))),
+	}
+	fps := []string{
+		// "xoxa-faketoken",
+		// "xoxa-access-token-string",
+		// "XOXa-nx991k",
+		"https://github.com/xoxa-nyc/xoxa-nyc.github.io/blob/master/README.md",
+	}
+	return validate(r, tps, fps)
+}
+
+// References:
+// - https://api.slack.com/authentication/token-types#legacy
+// - https://api.slack.com/changelog/2016-05-19-authorship-changing-for-older-tokens
+// - https://github.com/jonz-secops/TokenTester/blob/978e9f3eabc7e9978769cfbba10735afa3bf627e/slack#L29
+// - https://gist.github.com/thesubtlety/a1c460d53df0837c5817c478b9f10588#file-local-slack-jack-py-L32
+func SlackLegacyToken() *config.Rule {
+	// define rule
+	r := config.Rule{
+		Description: "Slack Legacy token",
+		RuleID:      "slack-legacy-token",
+		Regex:       regexp.MustCompile(`(xox[os]-\d+-\d+-\d+-[a-fA-F\d]+)`),
+		Keywords:    []string{"xoxo", "xoxs"},
+	}
+
 	// validate
 	tps := []string{
-		"\"slackToken\": \"xoxb-" + secrets.NewSecret(alphaNumeric("30")) + "\"",
+		// https://github.com/GGStudy-DDUp/https-github.com-aldaor-HackerOneReports/blob/637e9261b63a7292a3a7ddf4bf13729c224d84df/PrivilegeEscalation/47940.txt#L23
+		`"access_token1": "xoxs-3206092076-3204538285-3743137121-836b042620"`, // gitleaks:allow
+		// https://github.com/jonz-secops/TokenTester/blob/978e9f3eabc7e9978769cfbba10735afa3bf627e/slack#L28
+		`"access_token2": "xoxs-416843729158-132049654-5609968301-e708ba56e1"`, // gitleaks:allow
+		// https://github.com/clr2of8/SlackExtract/blob/18d151152ff5a45b293d4b7193aa6d08f9ab1bfd/README.md?plain=1#L32
+		`"access_token3": "xoxs-420083410720-421837374423-440811613314-977844f625b707d5b0b268206dbc92cbc85feef3e71b08e44815a8e6e7657190"`, // gitleaks:allow
+		// https://github.com/zeroc00I/AllVideoPocsFromHackerOne/blob/95ae92f65ccef11c2c6acdaabfb7cc9b2b0eb4c6/jsonReports/61312.json#LL1C17-L1C17
+		`"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_token7": "xoxo-523423-234243-234233-e039d02840a0b9379c"`, // gitleaks:allow
 	}
-	return validate(r, tps, nil)
+	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)
 }
 
-func SlackWebHook() *config.Rule {
+func SlackWebHookUrl() *config.Rule {
 	// define rule
 	r := config.Rule{
 		Description: "Slack Webhook",
-		RuleID:      "slack-web-hook",
+		RuleID:      "slack-webhook-url",
+		// If this generates too many false-positives we should define an allowlist (e.g., "xxxx", "00000").
 		Regex: regexp.MustCompile(
-			`https:\/\/hooks.slack.com\/(services|workflows)\/[A-Za-z0-9+\/]{44,46}`),
+			`(https?:\/\/)?hooks.slack.com\/(services|workflows)\/[A-Za-z0-9+\/]{43,46}`),
 		Keywords: []string{
 			"hooks.slack.com",
 		},
@@ -44,8 +266,16 @@ func SlackWebHook() *config.Rule {
 
 	// validate
 	tps := []string{
-		"https://hooks.slack.com/services/" + secrets.NewSecret(alphaNumeric("44")),  // gitleaks:allow
-		"https://hooks.slack.com/workflows/" + secrets.NewSecret(alphaNumeric("44")), // gitleaks:allow
+		"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")),
+		"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")),
+		"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)
 }

+ 62 - 6
config/gitleaks.toml

@@ -2609,17 +2609,73 @@ keywords = [
 ]
 
 [[rules]]
-description = "Slack token"
-id = "slack-access-token"
-regex = '''xox[baprs]-([0-9a-zA-Z]{10,48})'''
+description = "Slack App-level token"
+id = "slack-app-token"
+regex = '''(?i)(xapp-\d-[A-Z0-9]+-\d+-[a-z0-9]+)'''
 keywords = [
-    "xoxb","xoxa","xoxp","xoxr","xoxs",
+    "xapp",
+]
+
+[[rules]]
+description = "Slack Bot token"
+id = "slack-bot-token"
+regex = '''(xoxb-[0-9]{10,13}\-[0-9]{10,13}[a-zA-Z0-9-]*)'''
+keywords = [
+    "xoxb",
+]
+
+[[rules]]
+description = "Slack Configuration access token"
+id = "slack-config-access-token"
+regex = '''(?i)(xoxe.xox[bp]-\d-[A-Z0-9]{163,166})'''
+keywords = [
+    "xoxe.xoxb-","xoxe.xoxp-",
+]
+
+[[rules]]
+description = "Slack Configuration refresh token"
+id = "slack-config-refresh-token"
+regex = '''(?i)(xoxe-\d-[A-Z0-9]{146})'''
+keywords = [
+    "xoxe-",
+]
+
+[[rules]]
+description = "Slack Legacy bot token"
+id = "slack-legacy-bot-token"
+regex = '''(xoxb-[0-9]{8,14}\-[a-zA-Z0-9]{18,26})'''
+keywords = [
+    "xoxb",
+]
+
+[[rules]]
+description = "Slack Legacy token"
+id = "slack-legacy-token"
+regex = '''(xox[os]-\d+-\d+-\d+-[a-fA-F\d]+)'''
+keywords = [
+    "xoxo","xoxs",
+]
+
+[[rules]]
+description = "Slack Legacy Workspace token"
+id = "slack-legacy-workspace-token"
+regex = '''(xox[ar]-(?:\d-)?[0-9a-zA-Z]{8,48})'''
+keywords = [
+    "xoxa","xoxr",
+]
+
+[[rules]]
+description = "Slack User"
+id = "slack-user-token"
+regex = '''(xox[pe](?:-[0-9]{10,13}){3}-[a-zA-Z0-9-]{28,34})'''
+keywords = [
+    "xoxp-","xoxe-",
 ]
 
 [[rules]]
 description = "Slack Webhook"
-id = "slack-web-hook"
-regex = '''https:\/\/hooks.slack.com\/(services|workflows)\/[A-Za-z0-9+\/]{44,46}'''
+id = "slack-webhook-url"
+regex = '''(https?:\/\/)?hooks.slack.com\/(services|workflows)\/[A-Za-z0-9+\/]{43,46}'''
 keywords = [
     "hooks.slack.com",
 ]