Repository navigation
FIX: Detect legacy Slack bot tokens in CredentialLeakScorer - #3659
Merged
Richard Lundeen (richlundeen) merged 3 commits intoOct 30, 2026
Merged
Richard Lundeen (richlundeen) merged 3 commits into
Richard Lundeen (richlundeen) merged 3 commits into
Conversation
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Richard Lundeen (richlundeen)
approved these changes
Oct 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
CredentialLeakScorer()does not flag legacy Slack bot tokens. These have one numeric segment before the secret part,xoxb-<digits>-<letters and digits>, for example gitleaks' samplexoxb-263594206564-FGqddMF8t08v8N7Oq4i57vs1. The defaultSlack Tokenpattern and itsGARAK_PATTERNSentry only accept the forms with two or three numeric segments, so a reply that contains a legacy bot token scoresFalseunless a keyword such astoken =next to it triggersGeneric Secret.This PR adds one alternative for
xoxbonly, in both_DEFAULT_PATTERNSandGARAK_PATTERNS(the Garak entry keeps thecredentialgroup, so exclusions still work). The existing alternatives are unchanged:The bounds are the ones of gitleaks'
slack-legacy-bot-tokenrule, whose samples include eight tokens with links to the public code or blog post they come from, and one with 8 digits and a 19-character secret. Nosey Parker's Slack rule lists the same one-segment form in its examples. The new alternative ends with a lookahead, so a longer value is not cut to its first 26 characters. Without it, the upper bound would have no effect, andfrom_excluded_valueswould compare the excluded value with a truncated match.Real run:
CredentialLeakScorer()with no arguments,score_text_asyncon an assistant reply that embeds the token in a code sample (client = WebClient("<token>"), no keyword nearby), over the literal true-positive and false-positive Slack samples in the gitleaks file above (commented-out and generated samples left out):The only results that change are the nine legacy bot samples.
Tests and Documentation
In
tests/unit/score/regex/test_credential_leak_scorer.py, each case runs with the default and the Garak patterns:test_slack_token_detected_and_exactly_excluded_async(the user-token test, now parametrized over a user token and a synthetic legacy bot token): bare and insideWebClient(...), the token scoresTruewithSlack Tokenin the rationale;from_excluded_valuesskips that exact token and still flags a changed or extended one. The four legacy bot cases fail on main.test_slack_legacy_bot_token_bounds_detected_async: 8 digits with an 18- or 19-character secret, and 14 digits with a 26-character secret, scoreTrue. All six cases fail on main.test_slack_legacy_bot_token_invalid_shapes_not_detected_async: 7 or 15 digits, a 17- or 27-character secret, a non-digit in the numeric segment, a dot in the secret, a trailing_suffixor-suffix, gitleaks'xxxxplaceholder, and anxoxpvalue in the legacy shape all stayFalse.pytest tests/unit/score tests/unit/scenario/garak: 5284 passed, 116 skipped.ruff checkandruff format --check(0.17.2) pass on the changed files.