From 48b3ccf279fbe2cb84a620eb2966002a66d3234e Mon Sep 17 00:00:00 2001
From: wehub-resource-sync
Date: Mon, 13 Jul 2026 12:12:29 +0800
Subject: [PATCH] chore: import upstream snapshot with attribution
---
.github/CODEOWNERS | 8 +
.github/FUNDING.yml | 3 +
.github/ISSUE_TEMPLATE/bug_report.md | 37 +
.github/ISSUE_TEMPLATE/feature_request.md | 22 +
.github/ISSUE_TEMPLATE/maintenance.md | 16 +
.github/PULL_REQUEST_TEMPLATE.md | 8 +
.github/dependabot.yml | 17 +
.github/workflows/gitleaks.yml | 17 +
.github/workflows/release.yml | 57 +
.github/workflows/test.yml | 37 +
.gitignore | 24 +
.gitleaksignore | 944 +++++
.golangci.yaml | 86 +
.goreleaser.yml | 31 +
.pre-commit-hooks.yaml | 17 +
CONTRIBUTING.md | 102 +
Dockerfile | 13 +
LICENSE | 21 +
Makefile | 37 +
README.md | 630 ++++
README.wehub.md | 7 +
SECURITY.md | 19 +
USERS.md | 26 +
cmd/detect.go | 136 +
cmd/diagnostics.go | 239 ++
cmd/directory.go | 74 +
cmd/generate/config/base/config.go | 121 +
cmd/generate/config/base/config_test.go | 203 ++
cmd/generate/config/main.go | 301 ++
cmd/generate/config/rules/1password.go | 81 +
cmd/generate/config/rules/adafruit.go | 21 +
cmd/generate/config/rules/adobe.go | 39 +
cmd/generate/config/rules/age.go | 21 +
cmd/generate/config/rules/airtable.go | 37 +
cmd/generate/config/rules/algolia.go | 21 +
cmd/generate/config/rules/alibaba.go | 40 +
cmd/generate/config/rules/anthropic.go | 69 +
cmd/generate/config/rules/artifactory.go | 58 +
cmd/generate/config/rules/asana.go | 36 +
cmd/generate/config/rules/atlassian.go | 36 +
cmd/generate/config/rules/authress.go | 31 +
cmd/generate/config/rules/aws.go | 109 +
cmd/generate/config/rules/azure.go | 65 +
cmd/generate/config/rules/beamer.go | 25 +
cmd/generate/config/rules/bitbucket.go | 36 +
cmd/generate/config/rules/bittrex.go | 36 +
cmd/generate/config/rules/clickhouse.go | 30 +
cmd/generate/config/rules/clojars.go | 23 +
cmd/generate/config/rules/cloudflare.go | 81 +
cmd/generate/config/rules/codecov.go | 23 +
cmd/generate/config/rules/cohere.go | 32 +
cmd/generate/config/rules/coinbase.go | 24 +
cmd/generate/config/rules/config.tmpl | 75 +
cmd/generate/config/rules/confluent.go | 40 +
cmd/generate/config/rules/contentful.go | 22 +
cmd/generate/config/rules/curl.go | 201 ++
cmd/generate/config/rules/databricks.go | 26 +
cmd/generate/config/rules/datadog.go | 24 +
.../config/rules/definednetworking.go | 28 +
cmd/generate/config/rules/digitalocean.go | 46 +
cmd/generate/config/rules/discord.go | 61 +
cmd/generate/config/rules/doppler.go | 26 +
cmd/generate/config/rules/droneci.go | 24 +
cmd/generate/config/rules/dropbox.go | 48 +
cmd/generate/config/rules/duffel.go | 23 +
cmd/generate/config/rules/dynatrace.go | 23 +
cmd/generate/config/rules/easypost.go | 55 +
cmd/generate/config/rules/etsy.go | 34 +
cmd/generate/config/rules/facebook.go | 78 +
cmd/generate/config/rules/fastly.go | 22 +
cmd/generate/config/rules/finicity.go | 37 +
cmd/generate/config/rules/finnhub.go | 24 +
cmd/generate/config/rules/flickr.go | 24 +
cmd/generate/config/rules/flutterwave.go | 53 +
cmd/generate/config/rules/flyio.go | 57 +
cmd/generate/config/rules/frameio.go | 22 +
cmd/generate/config/rules/freemius.go | 47 +
cmd/generate/config/rules/freshbooks.go | 24 +
cmd/generate/config/rules/gcp.go | 90 +
cmd/generate/config/rules/generic.go | 299 ++
cmd/generate/config/rules/github.go | 111 +
cmd/generate/config/rules/gitlab.go | 222 ++
cmd/generate/config/rules/gitter.go | 25 +
cmd/generate/config/rules/gocardless.go | 25 +
cmd/generate/config/rules/grafana.go | 80 +
cmd/generate/config/rules/harness.go | 25 +
cmd/generate/config/rules/hashicorp.go | 58 +
cmd/generate/config/rules/hashicorp_vault.go | 67 +
cmd/generate/config/rules/heroku.go | 45 +
cmd/generate/config/rules/hubspot.go | 26 +
cmd/generate/config/rules/huggingface.go | 116 +
cmd/generate/config/rules/infracost.go | 42 +
cmd/generate/config/rules/intercom.go | 22 +
cmd/generate/config/rules/intra42.go | 31 +
cmd/generate/config/rules/jfrog.go | 64 +
cmd/generate/config/rules/jwt.go | 194 +
cmd/generate/config/rules/kraken.go | 25 +
cmd/generate/config/rules/kubernetes.go | 463 +++
cmd/generate/config/rules/kucoin.go | 41 +
cmd/generate/config/rules/launchdarkly.go | 24 +
cmd/generate/config/rules/linear.go | 38 +
cmd/generate/config/rules/linkedin.go | 47 +
cmd/generate/config/rules/lob.go | 43 +
cmd/generate/config/rules/looker.go | 35 +
cmd/generate/config/rules/mailchimp.go | 32 +
cmd/generate/config/rules/mailgun.go | 58 +
cmd/generate/config/rules/mapbox.go | 22 +
cmd/generate/config/rules/mattermost.go | 24 +
cmd/generate/config/rules/maxmind.go | 21 +
cmd/generate/config/rules/meraki.go | 29 +
cmd/generate/config/rules/messagebird.go | 50 +
cmd/generate/config/rules/netlify.go | 25 +
cmd/generate/config/rules/newrelic.go | 93 +
cmd/generate/config/rules/notion.go | 39 +
cmd/generate/config/rules/npm.go | 24 +
cmd/generate/config/rules/nuget.go | 48 +
cmd/generate/config/rules/nytimes.go | 28 +
cmd/generate/config/rules/octopusdeploy.go | 32 +
cmd/generate/config/rules/okta.go | 34 +
cmd/generate/config/rules/openai.go | 37 +
cmd/generate/config/rules/openshift.go | 37 +
cmd/generate/config/rules/perplexity.go | 27 +
cmd/generate/config/rules/plaid.go | 61 +
cmd/generate/config/rules/planetscale.go | 64 +
cmd/generate/config/rules/postman.go | 24 +
cmd/generate/config/rules/prefect.go | 27 +
cmd/generate/config/rules/privateai.go | 31 +
cmd/generate/config/rules/privatekey.go | 61 +
cmd/generate/config/rules/pulumi.go | 27 +
cmd/generate/config/rules/pypi.go | 25 +
cmd/generate/config/rules/rapidapi.go | 25 +
cmd/generate/config/rules/readme.go | 28 +
cmd/generate/config/rules/rubygems.go | 24 +
cmd/generate/config/rules/scalingo.go | 25 +
cmd/generate/config/rules/sendbird.go | 41 +
cmd/generate/config/rules/sendgrid.go | 24 +
cmd/generate/config/rules/sendinblue.go | 24 +
cmd/generate/config/rules/sentry.go | 98 +
cmd/generate/config/rules/settlemint.go | 70 +
cmd/generate/config/rules/shippo.go | 25 +
cmd/generate/config/rules/shopify.go | 68 +
cmd/generate/config/rules/sidekiq.go | 62 +
cmd/generate/config/rules/slack.go | 296 ++
cmd/generate/config/rules/snyk.go | 32 +
cmd/generate/config/rules/sonar.go | 31 +
cmd/generate/config/rules/sourcegraph.go | 34 +
cmd/generate/config/rules/square.go | 47 +
cmd/generate/config/rules/squarespace.go | 24 +
cmd/generate/config/rules/stopwords.go | 1491 ++++++++
cmd/generate/config/rules/stripe.go | 35 +
cmd/generate/config/rules/sumologic.go | 75 +
cmd/generate/config/rules/teams.go | 29 +
cmd/generate/config/rules/telegram.go | 79 +
cmd/generate/config/rules/travisci.go | 24 +
cmd/generate/config/rules/trello.go | 24 +
cmd/generate/config/rules/twilio.go | 23 +
cmd/generate/config/rules/twitch.go | 23 +
cmd/generate/config/rules/twitter.go | 78 +
cmd/generate/config/rules/typeform.go | 24 +
cmd/generate/config/rules/yandex.go | 60 +
cmd/generate/config/rules/zendesk.go | 23 +
cmd/generate/config/utils/generate.go | 162 +
cmd/generate/config/utils/generate_test.go | 235 ++
cmd/generate/config/utils/patterns.go | 37 +
cmd/generate/config/utils/validate.go | 97 +
cmd/generate/secrets/regen.go | 15 +
cmd/git.go | 96 +
cmd/protect.go | 66 +
cmd/root.go | 548 +++
cmd/scm/scm.go | 52 +
cmd/stdin.go | 54 +
cmd/version.go | 22 +
config/allowlist.go | 179 +
config/allowlist_test.go | 380 ++
config/config.go | 492 +++
config/config_test.go | 672 ++++
config/gitleaks.toml | 3209 +++++++++++++++++
config/rule.go | 107 +
config/utils.go | 40 +
detect/baseline.go | 81 +
detect/baseline_test.go | 232 ++
detect/codec/ascii.go | 34 +
detect/codec/base64.go | 39 +
detect/codec/decoder.go | 105 +
detect/codec/decoder_test.go | 144 +
detect/codec/encodings.go | 161 +
detect/codec/hex.go | 60 +
detect/codec/percent.go | 34 +
detect/codec/segment.go | 173 +
detect/codec/start_end.go | 57 +
detect/codec/unicode.go | 261 ++
detect/detect.go | 900 +++++
detect/detect_test.go | 2773 ++++++++++++++
detect/files.go | 92 +
detect/git.go | 35 +
detect/location.go | 80 +
detect/location_test.go | 57 +
detect/reader.go | 108 +
detect/reader_test.go | 163 +
detect/utils.go | 263 ++
detect/utils_test.go | 214 ++
go.mod | 84 +
go.sum | 423 +++
logging/log.go | 50 +
main.go | 24 +
regexp/stdlib_regex.go | 15 +
regexp/wasilibs_regex.go | 15 +
report/constants.go | 4 +
report/csv.go | 78 +
report/csv_test.go | 77 +
report/finding.go | 126 +
report/finding_test.go | 84 +
report/json.go | 17 +
report/json_test.go | 77 +
report/junit.go | 107 +
report/junit_test.go | 92 +
report/report.go | 16 +
report/report_test.go | 49 +
report/sarif.go | 217 ++
report/sarif_test.go | 86 +
report/template.go | 53 +
report/template_test.go | 147 +
report_templates/README.md | 25 +
report_templates/basic.tmpl | 760 ++++
report_templates/leet.tmpl | 847 +++++
report_templates/myspace.tmpl | 800 ++++
report_templates/w98.tmpl | 723 ++++
report_templates/wxp.tmpl | 760 ++++
scripts/pre-commit.py | 27 +
scripts/profile.sh | 80 +
sources/common.go | 125 +
sources/common_test.go | 72 +
sources/file.go | 264 ++
sources/files.go | 191 +
sources/fragment.go | 28 +
sources/git.go | 530 +++
sources/git_test.go | 158 +
sources/source.go | 16 +
testdata/archives/files.7z | Bin 0 -> 559 bytes
testdata/archives/files.tar | Bin 0 -> 10240 bytes
testdata/archives/files.tar.xz | Bin 0 -> 572 bytes
testdata/archives/files.tar.zst | Bin 0 -> 501 bytes
testdata/archives/files.zip | Bin 0 -> 1315 bytes
testdata/archives/files/.env.prod | 6 +
testdata/archives/files/.gitleaksignore | 1 +
testdata/archives/files/api.go | 24 +
testdata/archives/files/main.go | 24 +
testdata/archives/files/main.go.gz | Bin 0 -> 209 bytes
testdata/archives/files/main.go.xz | Bin 0 -> 264 bytes
testdata/archives/files/main.go.zst | Bin 0 -> 201 bytes
testdata/archives/nested.tar.gz | Bin 0 -> 3675 bytes
testdata/baseline/baseline.csv | 2 +
testdata/baseline/baseline.json | 40 +
testdata/baseline/baseline.sarif | 6 +
testdata/config/archives.toml | 21 +
testdata/config/composite.toml | 14 +
testdata/config/encoded.toml | 126 +
testdata/config/generic.toml | 10 +
testdata/config/generic_with_py_path.toml | 35 +
.../invalid/allowlist_global_empty.toml | 2 +
.../invalid/allowlist_global_old_and_new.toml | 4 +
.../invalid/allowlist_global_regextarget.toml | 3 +
.../allowlist_global_target_rule_id.toml | 7 +
.../config/invalid/allowlist_rule_empty.toml | 4 +
.../invalid/allowlist_rule_old_and_new.toml | 7 +
.../invalid/allowlist_rule_regextarget.toml | 6 +
.../config/invalid/extend_invalid_base.toml | 10 +
.../config/invalid/extend_invalid_ruleid.toml | 7 +
.../invalid/rule_bad_entropy_group.toml | 8 +
testdata/config/invalid/rule_missing_id.toml | 7 +
.../config/invalid/rule_no_regex_or_path.toml | 5 +
testdata/config/simple.toml | 227 ++
.../valid/allowlist_global_multiple.toml | 10 +
.../valid/allowlist_global_old_compat.toml | 2 +
.../config/valid/allowlist_global_regex.toml | 2 +
.../valid/allowlist_global_target_rules.toml | 20 +
.../config/valid/allowlist_rule_commit.toml | 9 +
.../valid/allowlist_rule_extend_default.toml | 11 +
.../valid/allowlist_rule_old_compat.toml | 5 +
.../config/valid/allowlist_rule_path.toml | 9 +
.../config/valid/allowlist_rule_regex.toml | 9 +
testdata/config/valid/extend.toml | 8 +
testdata/config/valid/extend_base_1.toml | 10 +
testdata/config/valid/extend_base_2.toml | 10 +
testdata/config/valid/extend_base_3.toml | 9 +
...ule_including_keywords_with_attribute.toml | 8 +
testdata/config/valid/extend_disabled.toml | 11 +
.../config/valid/extend_disabled_base.toml | 11 +
.../valid/extend_rule_allowlist_and.toml | 14 +
.../valid/extend_rule_allowlist_base.toml | 11 +
.../valid/extend_rule_allowlist_or.toml | 13 +
.../valid/extend_rule_keywords_base.toml | 12 +
testdata/config/valid/extend_rule_new.toml | 8 +
.../valid/extend_rule_no_regexpath.toml | 8 +
.../extend_rule_override_description.toml | 8 +
.../valid/extend_rule_override_entropy.toml | 8 +
.../valid/extend_rule_override_keywords.toml | 8 +
.../valid/extend_rule_override_path.toml | 8 +
.../valid/extend_rule_override_regex.toml | 8 +
.../extend_rule_override_secret_group.toml | 9 +
.../valid/extend_rule_override_tags.toml | 8 +
testdata/config/valid/rule_entropy_group.toml | 6 +
testdata/config/valid/rule_path_only.toml | 4 +
.../rule_regex_escaped_character_group.toml | 5 +
testdata/expected/git/small-branch-foo.txt | 17 +
testdata/expected/git/small.txt | 67 +
testdata/expected/report/csv_simple.csv | 2 +
testdata/expected/report/empty.json | 1 +
testdata/expected/report/json_simple.json | 22 +
testdata/expected/report/junit_empty.xml | 4 +
testdata/expected/report/junit_simple.xml | 11 +
testdata/expected/report/sarif_simple.sarif | 69 +
.../expected/report/template_jsonextra.json | 23 +
testdata/expected/report/template_markdown.md | 3 +
testdata/gitleaksignore/.windowspaths | 4 +
testdata/report/jsonextra.tmpl | 25 +
testdata/report/markdown.tmpl | 5 +
testdata/repos/archives/.gitleaksignore | 0
testdata/repos/archives/README.md | 10 +
testdata/repos/archives/dotGit/HEAD | 1 +
testdata/repos/archives/dotGit/ORIG_HEAD | 1 +
testdata/repos/archives/dotGit/config | 13 +
testdata/repos/archives/dotGit/description | 1 +
testdata/repos/archives/dotGit/index | Bin 0 -> 297 bytes
testdata/repos/archives/dotGit/info/exclude | 6 +
testdata/repos/archives/dotGit/info/refs | 1 +
.../archives/dotGit/objects/info/commit-graph | Bin 0 -> 1472 bytes
.../repos/archives/dotGit/objects/info/packs | 2 +
...774732f0e985d717a26e126e6574d089375b0d.idx | Bin 0 -> 1576 bytes
...74732f0e985d717a26e126e6574d089375b0d.pack | Bin 0 -> 7889 bytes
...774732f0e985d717a26e126e6574d089375b0d.rev | Bin 0 -> 124 bytes
testdata/repos/archives/dotGit/packed-refs | 2 +
testdata/repos/archives/dotGit/refs/.gitkeep | 0
testdata/repos/archives/main.go.zst | Bin 0 -> 201 bytes
testdata/repos/nogit/.env.prod | 6 +
testdata/repos/nogit/.gitleaksignore | 1 +
testdata/repos/nogit/api.go | 24 +
testdata/repos/nogit/main.go | 24 +
testdata/repos/small/.gitleaksignore | 3 +
testdata/repos/small/README.md | 2 +
testdata/repos/small/api/api.go | 7 +
testdata/repos/small/api/ignoreCommit.go | 24 +
testdata/repos/small/api/ignoreGlobal.go | 24 +
testdata/repos/small/dotGit/COMMIT_EDITMSG | 1 +
testdata/repos/small/dotGit/FETCH_HEAD | 1 +
testdata/repos/small/dotGit/HEAD | 1 +
testdata/repos/small/dotGit/ORIG_HEAD | 1 +
testdata/repos/small/dotGit/config | 13 +
testdata/repos/small/dotGit/description | 1 +
testdata/repos/small/dotGit/index | Bin 0 -> 493 bytes
testdata/repos/small/dotGit/info/exclude | 6 +
testdata/repos/small/dotGit/logs/HEAD | 17 +
.../small/dotGit/logs/refs/heads/api-pkg | 1 +
.../repos/small/dotGit/logs/refs/heads/foo | 3 +
.../repos/small/dotGit/logs/refs/heads/main | 6 +
.../dotGit/logs/refs/heads/remove-secrets | 3 +
.../dotGit/logs/refs/remotes/origin/HEAD | 1 +
.../dotGit/logs/refs/remotes/origin/api-pkg | 1 +
.../small/dotGit/logs/refs/remotes/origin/foo | 1 +
.../dotGit/logs/refs/remotes/origin/main | 1 +
.../02/d85657604c34e7b7fbb324a0c6c8b13c2c3760 | 1 +
.../15/2888a42422b2ff5868b8d003d626120a9cb738 | Bin 0 -> 86 bytes
.../2e/1db472eeba53f06c4026ae4566ea022e36598e | Bin 0 -> 618 bytes
.../32/bfaec6697c1a693f71b183d3389ad2547bbb3c | Bin 0 -> 155 bytes
.../49/1504d5a31946ce75e22554cc34203d8e5ff3ca | Bin 0 -> 175 bytes
.../4f/77f1b3cc39d4b17e4cf4ba0a38f5daed9875b4 | Bin 0 -> 173 bytes
.../53/cd7a3c6eb4937f413e3c25e4a9f39289afa69e | Bin 0 -> 176 bytes
.../5c/547e4215d9594c3935bdfefdf4f500016a4112 | Bin 0 -> 51 bytes
.../78/9ba677976d5db481de55c799d67acbf8e3f16a | Bin 0 -> 51 bytes
.../8d/c20a62e189d3446cfb6ec328dbd379d64feb20 | Bin 0 -> 82 bytes
.../90/6335481df9a4b48906c90318b4fac76b67fe73 | 3 +
.../98/1ab8417104c91bb9a4657f5d436c760c0aff50 | Bin 0 -> 65 bytes
.../9a/932e37eaa9fb64b09e47e5e859c9b2c8cb47ad | Bin 0 -> 196 bytes
.../a1/22b33c6bad3ee54724f52f2caad385ab1982ab | Bin 0 -> 163 bytes
.../a5/caae6d742e49a33982f1fdc608ce861ea59be5 | Bin 0 -> 134 bytes
.../a9/aa0c942dcef669a94f207a77426106b25efd1a | Bin 0 -> 143 bytes
.../ac/bef43fdb053ec01e8e16697536d47853460cbc | Bin 0 -> 202 bytes
.../bc/f47ef84f29bb7ed6e653d61fccd30d0ecce886 | Bin 0 -> 116 bytes
.../ca/da78a9bf157ec05573f19e682d211f811c2e2d | 1 +
.../d8/32479114dc6be7207edc7c37ce91dd11b93161 | Bin 0 -> 80 bytes
.../da/2622b4d97e32c5801511244b809144b6b3ea78 | Bin 0 -> 51 bytes
.../da/eb160a13200a3422e73296a6892784a113e0d6 | Bin 0 -> 155 bytes
.../df/7eaa59fc89b3e7258167605db2e582f1a78e6f | Bin 0 -> 99 bytes
.../e5/c0849a65c586eab87dcfc31fec74f0fd7c62cb | Bin 0 -> 143 bytes
.../f1/b58b97808f8e744f6a23c693859df5b5968901 | Bin 0 -> 176 bytes
.../fa/468655086f149d41a8e7db14ed054bebec7687 | Bin 0 -> 116 bytes
...dc2976b84768d0829c75cc8d8fc4d849be62cd.idx | Bin 0 -> 1324 bytes
...c2976b84768d0829c75cc8d8fc4d849be62cd.pack | Bin 0 -> 2116 bytes
testdata/repos/small/dotGit/packed-refs | 2 +
.../repos/small/dotGit/refs/heads/api-pkg | 1 +
testdata/repos/small/dotGit/refs/heads/foo | 1 +
testdata/repos/small/dotGit/refs/heads/main | 1 +
.../small/dotGit/refs/heads/remove-secrets | 1 +
.../small/dotGit/refs/remotes/origin/HEAD | 1 +
.../small/dotGit/refs/remotes/origin/api-pkg | 1 +
.../small/dotGit/refs/remotes/origin/foo | 1 +
.../small/dotGit/refs/remotes/origin/main | 1 +
testdata/repos/small/main.go | 27 +
testdata/repos/staged/.gitleaksignore | 1 +
testdata/repos/staged/README.md | 2 +
testdata/repos/staged/api/api.go | 10 +
testdata/repos/staged/dotGit/COMMIT_EDITMSG | 1 +
testdata/repos/staged/dotGit/FETCH_HEAD | 1 +
testdata/repos/staged/dotGit/HEAD | 1 +
testdata/repos/staged/dotGit/ORIG_HEAD | 1 +
testdata/repos/staged/dotGit/config | 13 +
testdata/repos/staged/dotGit/description | 1 +
testdata/repos/staged/dotGit/index | Bin 0 -> 359 bytes
testdata/repos/staged/dotGit/info/exclude | 6 +
testdata/repos/staged/dotGit/logs/HEAD | 14 +
.../staged/dotGit/logs/refs/heads/api-pkg | 1 +
.../repos/staged/dotGit/logs/refs/heads/foo | 3 +
.../repos/staged/dotGit/logs/refs/heads/main | 3 +
.../dotGit/logs/refs/heads/remove-secrets | 3 +
.../dotGit/logs/refs/remotes/origin/HEAD | 1 +
.../dotGit/logs/refs/remotes/origin/api-pkg | 1 +
.../dotGit/logs/refs/remotes/origin/foo | 1 +
.../dotGit/logs/refs/remotes/origin/main | 1 +
.../02/d85657604c34e7b7fbb324a0c6c8b13c2c3760 | 1 +
.../15/2888a42422b2ff5868b8d003d626120a9cb738 | Bin 0 -> 86 bytes
.../2e/1db472eeba53f06c4026ae4566ea022e36598e | Bin 0 -> 618 bytes
.../46/18d7e4512b6b0b1dab85cf846d9f43474ec8be | Bin 0 -> 44 bytes
.../49/1504d5a31946ce75e22554cc34203d8e5ff3ca | Bin 0 -> 175 bytes
.../5c/547e4215d9594c3935bdfefdf4f500016a4112 | Bin 0 -> 51 bytes
.../65/83d6db4a57bbeda62d50fc91649036d499418d | Bin 0 -> 116 bytes
.../66/bc70d0c0bfbb6468b3f90c3f1e9f2ddba02b43 | Bin 0 -> 155 bytes
.../78/9ba677976d5db481de55c799d67acbf8e3f16a | Bin 0 -> 51 bytes
.../90/6335481df9a4b48906c90318b4fac76b67fe73 | 3 +
.../9a/932e37eaa9fb64b09e47e5e859c9b2c8cb47ad | Bin 0 -> 196 bytes
.../a1/22b33c6bad3ee54724f52f2caad385ab1982ab | Bin 0 -> 163 bytes
.../a5/caae6d742e49a33982f1fdc608ce861ea59be5 | Bin 0 -> 134 bytes
.../a9/aa0c942dcef669a94f207a77426106b25efd1a | Bin 0 -> 143 bytes
.../b1/6d768dd595a59f947abe087901183d219d7e54 | Bin 0 -> 182 bytes
.../bc/f47ef84f29bb7ed6e653d61fccd30d0ecce886 | Bin 0 -> 116 bytes
.../bf/3f24164d7256b4021575cbdb2f97b98e6f057e | 2 +
.../d8/32479114dc6be7207edc7c37ce91dd11b93161 | Bin 0 -> 80 bytes
.../da/2622b4d97e32c5801511244b809144b6b3ea78 | Bin 0 -> 51 bytes
.../e5/c0849a65c586eab87dcfc31fec74f0fd7c62cb | Bin 0 -> 143 bytes
.../f1/b58b97808f8e744f6a23c693859df5b5968901 | Bin 0 -> 176 bytes
...dc2976b84768d0829c75cc8d8fc4d849be62cd.idx | Bin 0 -> 1324 bytes
...c2976b84768d0829c75cc8d8fc4d849be62cd.pack | Bin 0 -> 2116 bytes
testdata/repos/staged/dotGit/packed-refs | 2 +
.../repos/staged/dotGit/refs/heads/api-pkg | 1 +
testdata/repos/staged/dotGit/refs/heads/foo | 1 +
testdata/repos/staged/dotGit/refs/heads/main | 1 +
.../staged/dotGit/refs/heads/remove-secrets | 1 +
.../staged/dotGit/refs/remotes/origin/HEAD | 1 +
.../staged/dotGit/refs/remotes/origin/api-pkg | 1 +
.../staged/dotGit/refs/remotes/origin/foo | 1 +
.../staged/dotGit/refs/remotes/origin/main | 1 +
testdata/repos/staged/main.go | 27 +
.../file_symlink/symlinked_id_ed25519 | 1 +
.../repos/symlinks/source_file/id_ed25519 | 7 +
version/version.go | 5 +
454 files changed, 32865 insertions(+)
create mode 100644 .github/CODEOWNERS
create mode 100644 .github/FUNDING.yml
create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md
create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md
create mode 100644 .github/ISSUE_TEMPLATE/maintenance.md
create mode 100644 .github/PULL_REQUEST_TEMPLATE.md
create mode 100644 .github/dependabot.yml
create mode 100644 .github/workflows/gitleaks.yml
create mode 100644 .github/workflows/release.yml
create mode 100644 .github/workflows/test.yml
create mode 100644 .gitignore
create mode 100644 .gitleaksignore
create mode 100644 .golangci.yaml
create mode 100644 .goreleaser.yml
create mode 100644 .pre-commit-hooks.yaml
create mode 100644 CONTRIBUTING.md
create mode 100644 Dockerfile
create mode 100644 LICENSE
create mode 100644 Makefile
create mode 100644 README.md
create mode 100644 README.wehub.md
create mode 100644 SECURITY.md
create mode 100644 USERS.md
create mode 100644 cmd/detect.go
create mode 100644 cmd/diagnostics.go
create mode 100644 cmd/directory.go
create mode 100644 cmd/generate/config/base/config.go
create mode 100644 cmd/generate/config/base/config_test.go
create mode 100644 cmd/generate/config/main.go
create mode 100644 cmd/generate/config/rules/1password.go
create mode 100644 cmd/generate/config/rules/adafruit.go
create mode 100644 cmd/generate/config/rules/adobe.go
create mode 100644 cmd/generate/config/rules/age.go
create mode 100644 cmd/generate/config/rules/airtable.go
create mode 100644 cmd/generate/config/rules/algolia.go
create mode 100644 cmd/generate/config/rules/alibaba.go
create mode 100644 cmd/generate/config/rules/anthropic.go
create mode 100644 cmd/generate/config/rules/artifactory.go
create mode 100644 cmd/generate/config/rules/asana.go
create mode 100644 cmd/generate/config/rules/atlassian.go
create mode 100644 cmd/generate/config/rules/authress.go
create mode 100644 cmd/generate/config/rules/aws.go
create mode 100644 cmd/generate/config/rules/azure.go
create mode 100644 cmd/generate/config/rules/beamer.go
create mode 100644 cmd/generate/config/rules/bitbucket.go
create mode 100644 cmd/generate/config/rules/bittrex.go
create mode 100644 cmd/generate/config/rules/clickhouse.go
create mode 100644 cmd/generate/config/rules/clojars.go
create mode 100644 cmd/generate/config/rules/cloudflare.go
create mode 100644 cmd/generate/config/rules/codecov.go
create mode 100644 cmd/generate/config/rules/cohere.go
create mode 100644 cmd/generate/config/rules/coinbase.go
create mode 100644 cmd/generate/config/rules/config.tmpl
create mode 100644 cmd/generate/config/rules/confluent.go
create mode 100644 cmd/generate/config/rules/contentful.go
create mode 100644 cmd/generate/config/rules/curl.go
create mode 100644 cmd/generate/config/rules/databricks.go
create mode 100644 cmd/generate/config/rules/datadog.go
create mode 100644 cmd/generate/config/rules/definednetworking.go
create mode 100644 cmd/generate/config/rules/digitalocean.go
create mode 100644 cmd/generate/config/rules/discord.go
create mode 100644 cmd/generate/config/rules/doppler.go
create mode 100644 cmd/generate/config/rules/droneci.go
create mode 100644 cmd/generate/config/rules/dropbox.go
create mode 100644 cmd/generate/config/rules/duffel.go
create mode 100644 cmd/generate/config/rules/dynatrace.go
create mode 100644 cmd/generate/config/rules/easypost.go
create mode 100644 cmd/generate/config/rules/etsy.go
create mode 100644 cmd/generate/config/rules/facebook.go
create mode 100644 cmd/generate/config/rules/fastly.go
create mode 100644 cmd/generate/config/rules/finicity.go
create mode 100644 cmd/generate/config/rules/finnhub.go
create mode 100644 cmd/generate/config/rules/flickr.go
create mode 100644 cmd/generate/config/rules/flutterwave.go
create mode 100644 cmd/generate/config/rules/flyio.go
create mode 100644 cmd/generate/config/rules/frameio.go
create mode 100644 cmd/generate/config/rules/freemius.go
create mode 100644 cmd/generate/config/rules/freshbooks.go
create mode 100644 cmd/generate/config/rules/gcp.go
create mode 100644 cmd/generate/config/rules/generic.go
create mode 100644 cmd/generate/config/rules/github.go
create mode 100644 cmd/generate/config/rules/gitlab.go
create mode 100644 cmd/generate/config/rules/gitter.go
create mode 100644 cmd/generate/config/rules/gocardless.go
create mode 100644 cmd/generate/config/rules/grafana.go
create mode 100644 cmd/generate/config/rules/harness.go
create mode 100644 cmd/generate/config/rules/hashicorp.go
create mode 100644 cmd/generate/config/rules/hashicorp_vault.go
create mode 100644 cmd/generate/config/rules/heroku.go
create mode 100644 cmd/generate/config/rules/hubspot.go
create mode 100644 cmd/generate/config/rules/huggingface.go
create mode 100644 cmd/generate/config/rules/infracost.go
create mode 100644 cmd/generate/config/rules/intercom.go
create mode 100644 cmd/generate/config/rules/intra42.go
create mode 100644 cmd/generate/config/rules/jfrog.go
create mode 100644 cmd/generate/config/rules/jwt.go
create mode 100644 cmd/generate/config/rules/kraken.go
create mode 100644 cmd/generate/config/rules/kubernetes.go
create mode 100644 cmd/generate/config/rules/kucoin.go
create mode 100644 cmd/generate/config/rules/launchdarkly.go
create mode 100644 cmd/generate/config/rules/linear.go
create mode 100644 cmd/generate/config/rules/linkedin.go
create mode 100644 cmd/generate/config/rules/lob.go
create mode 100644 cmd/generate/config/rules/looker.go
create mode 100644 cmd/generate/config/rules/mailchimp.go
create mode 100644 cmd/generate/config/rules/mailgun.go
create mode 100644 cmd/generate/config/rules/mapbox.go
create mode 100644 cmd/generate/config/rules/mattermost.go
create mode 100644 cmd/generate/config/rules/maxmind.go
create mode 100644 cmd/generate/config/rules/meraki.go
create mode 100644 cmd/generate/config/rules/messagebird.go
create mode 100644 cmd/generate/config/rules/netlify.go
create mode 100644 cmd/generate/config/rules/newrelic.go
create mode 100644 cmd/generate/config/rules/notion.go
create mode 100644 cmd/generate/config/rules/npm.go
create mode 100644 cmd/generate/config/rules/nuget.go
create mode 100644 cmd/generate/config/rules/nytimes.go
create mode 100644 cmd/generate/config/rules/octopusdeploy.go
create mode 100644 cmd/generate/config/rules/okta.go
create mode 100644 cmd/generate/config/rules/openai.go
create mode 100644 cmd/generate/config/rules/openshift.go
create mode 100644 cmd/generate/config/rules/perplexity.go
create mode 100644 cmd/generate/config/rules/plaid.go
create mode 100644 cmd/generate/config/rules/planetscale.go
create mode 100644 cmd/generate/config/rules/postman.go
create mode 100644 cmd/generate/config/rules/prefect.go
create mode 100644 cmd/generate/config/rules/privateai.go
create mode 100644 cmd/generate/config/rules/privatekey.go
create mode 100644 cmd/generate/config/rules/pulumi.go
create mode 100644 cmd/generate/config/rules/pypi.go
create mode 100644 cmd/generate/config/rules/rapidapi.go
create mode 100644 cmd/generate/config/rules/readme.go
create mode 100644 cmd/generate/config/rules/rubygems.go
create mode 100644 cmd/generate/config/rules/scalingo.go
create mode 100644 cmd/generate/config/rules/sendbird.go
create mode 100644 cmd/generate/config/rules/sendgrid.go
create mode 100644 cmd/generate/config/rules/sendinblue.go
create mode 100644 cmd/generate/config/rules/sentry.go
create mode 100644 cmd/generate/config/rules/settlemint.go
create mode 100644 cmd/generate/config/rules/shippo.go
create mode 100644 cmd/generate/config/rules/shopify.go
create mode 100644 cmd/generate/config/rules/sidekiq.go
create mode 100644 cmd/generate/config/rules/slack.go
create mode 100644 cmd/generate/config/rules/snyk.go
create mode 100644 cmd/generate/config/rules/sonar.go
create mode 100644 cmd/generate/config/rules/sourcegraph.go
create mode 100644 cmd/generate/config/rules/square.go
create mode 100644 cmd/generate/config/rules/squarespace.go
create mode 100644 cmd/generate/config/rules/stopwords.go
create mode 100644 cmd/generate/config/rules/stripe.go
create mode 100644 cmd/generate/config/rules/sumologic.go
create mode 100644 cmd/generate/config/rules/teams.go
create mode 100644 cmd/generate/config/rules/telegram.go
create mode 100644 cmd/generate/config/rules/travisci.go
create mode 100644 cmd/generate/config/rules/trello.go
create mode 100644 cmd/generate/config/rules/twilio.go
create mode 100644 cmd/generate/config/rules/twitch.go
create mode 100644 cmd/generate/config/rules/twitter.go
create mode 100644 cmd/generate/config/rules/typeform.go
create mode 100644 cmd/generate/config/rules/yandex.go
create mode 100644 cmd/generate/config/rules/zendesk.go
create mode 100644 cmd/generate/config/utils/generate.go
create mode 100644 cmd/generate/config/utils/generate_test.go
create mode 100644 cmd/generate/config/utils/patterns.go
create mode 100644 cmd/generate/config/utils/validate.go
create mode 100644 cmd/generate/secrets/regen.go
create mode 100644 cmd/git.go
create mode 100644 cmd/protect.go
create mode 100644 cmd/root.go
create mode 100644 cmd/scm/scm.go
create mode 100644 cmd/stdin.go
create mode 100644 cmd/version.go
create mode 100644 config/allowlist.go
create mode 100644 config/allowlist_test.go
create mode 100644 config/config.go
create mode 100644 config/config_test.go
create mode 100644 config/gitleaks.toml
create mode 100644 config/rule.go
create mode 100644 config/utils.go
create mode 100644 detect/baseline.go
create mode 100644 detect/baseline_test.go
create mode 100644 detect/codec/ascii.go
create mode 100644 detect/codec/base64.go
create mode 100644 detect/codec/decoder.go
create mode 100644 detect/codec/decoder_test.go
create mode 100644 detect/codec/encodings.go
create mode 100644 detect/codec/hex.go
create mode 100644 detect/codec/percent.go
create mode 100644 detect/codec/segment.go
create mode 100644 detect/codec/start_end.go
create mode 100644 detect/codec/unicode.go
create mode 100644 detect/detect.go
create mode 100644 detect/detect_test.go
create mode 100644 detect/files.go
create mode 100644 detect/git.go
create mode 100644 detect/location.go
create mode 100644 detect/location_test.go
create mode 100644 detect/reader.go
create mode 100644 detect/reader_test.go
create mode 100644 detect/utils.go
create mode 100644 detect/utils_test.go
create mode 100644 go.mod
create mode 100644 go.sum
create mode 100644 logging/log.go
create mode 100644 main.go
create mode 100644 regexp/stdlib_regex.go
create mode 100644 regexp/wasilibs_regex.go
create mode 100644 report/constants.go
create mode 100644 report/csv.go
create mode 100644 report/csv_test.go
create mode 100644 report/finding.go
create mode 100644 report/finding_test.go
create mode 100644 report/json.go
create mode 100644 report/json_test.go
create mode 100644 report/junit.go
create mode 100644 report/junit_test.go
create mode 100644 report/report.go
create mode 100644 report/report_test.go
create mode 100644 report/sarif.go
create mode 100644 report/sarif_test.go
create mode 100644 report/template.go
create mode 100644 report/template_test.go
create mode 100644 report_templates/README.md
create mode 100644 report_templates/basic.tmpl
create mode 100644 report_templates/leet.tmpl
create mode 100644 report_templates/myspace.tmpl
create mode 100644 report_templates/w98.tmpl
create mode 100644 report_templates/wxp.tmpl
create mode 100644 scripts/pre-commit.py
create mode 100755 scripts/profile.sh
create mode 100644 sources/common.go
create mode 100644 sources/common_test.go
create mode 100644 sources/file.go
create mode 100644 sources/files.go
create mode 100644 sources/fragment.go
create mode 100644 sources/git.go
create mode 100644 sources/git_test.go
create mode 100644 sources/source.go
create mode 100644 testdata/archives/files.7z
create mode 100644 testdata/archives/files.tar
create mode 100644 testdata/archives/files.tar.xz
create mode 100644 testdata/archives/files.tar.zst
create mode 100644 testdata/archives/files.zip
create mode 100644 testdata/archives/files/.env.prod
create mode 100644 testdata/archives/files/.gitleaksignore
create mode 100644 testdata/archives/files/api.go
create mode 100644 testdata/archives/files/main.go
create mode 100644 testdata/archives/files/main.go.gz
create mode 100644 testdata/archives/files/main.go.xz
create mode 100644 testdata/archives/files/main.go.zst
create mode 100644 testdata/archives/nested.tar.gz
create mode 100644 testdata/baseline/baseline.csv
create mode 100644 testdata/baseline/baseline.json
create mode 100644 testdata/baseline/baseline.sarif
create mode 100644 testdata/config/archives.toml
create mode 100644 testdata/config/composite.toml
create mode 100644 testdata/config/encoded.toml
create mode 100644 testdata/config/generic.toml
create mode 100644 testdata/config/generic_with_py_path.toml
create mode 100644 testdata/config/invalid/allowlist_global_empty.toml
create mode 100644 testdata/config/invalid/allowlist_global_old_and_new.toml
create mode 100644 testdata/config/invalid/allowlist_global_regextarget.toml
create mode 100644 testdata/config/invalid/allowlist_global_target_rule_id.toml
create mode 100644 testdata/config/invalid/allowlist_rule_empty.toml
create mode 100644 testdata/config/invalid/allowlist_rule_old_and_new.toml
create mode 100644 testdata/config/invalid/allowlist_rule_regextarget.toml
create mode 100644 testdata/config/invalid/extend_invalid_base.toml
create mode 100644 testdata/config/invalid/extend_invalid_ruleid.toml
create mode 100755 testdata/config/invalid/rule_bad_entropy_group.toml
create mode 100755 testdata/config/invalid/rule_missing_id.toml
create mode 100755 testdata/config/invalid/rule_no_regex_or_path.toml
create mode 100644 testdata/config/simple.toml
create mode 100644 testdata/config/valid/allowlist_global_multiple.toml
create mode 100644 testdata/config/valid/allowlist_global_old_compat.toml
create mode 100644 testdata/config/valid/allowlist_global_regex.toml
create mode 100644 testdata/config/valid/allowlist_global_target_rules.toml
create mode 100644 testdata/config/valid/allowlist_rule_commit.toml
create mode 100644 testdata/config/valid/allowlist_rule_extend_default.toml
create mode 100644 testdata/config/valid/allowlist_rule_old_compat.toml
create mode 100644 testdata/config/valid/allowlist_rule_path.toml
create mode 100644 testdata/config/valid/allowlist_rule_regex.toml
create mode 100644 testdata/config/valid/extend.toml
create mode 100644 testdata/config/valid/extend_base_1.toml
create mode 100644 testdata/config/valid/extend_base_2.toml
create mode 100644 testdata/config/valid/extend_base_3.toml
create mode 100644 testdata/config/valid/extend_base_rule_including_keywords_with_attribute.toml
create mode 100644 testdata/config/valid/extend_disabled.toml
create mode 100644 testdata/config/valid/extend_disabled_base.toml
create mode 100644 testdata/config/valid/extend_rule_allowlist_and.toml
create mode 100644 testdata/config/valid/extend_rule_allowlist_base.toml
create mode 100644 testdata/config/valid/extend_rule_allowlist_or.toml
create mode 100644 testdata/config/valid/extend_rule_keywords_base.toml
create mode 100644 testdata/config/valid/extend_rule_new.toml
create mode 100644 testdata/config/valid/extend_rule_no_regexpath.toml
create mode 100644 testdata/config/valid/extend_rule_override_description.toml
create mode 100644 testdata/config/valid/extend_rule_override_entropy.toml
create mode 100644 testdata/config/valid/extend_rule_override_keywords.toml
create mode 100644 testdata/config/valid/extend_rule_override_path.toml
create mode 100644 testdata/config/valid/extend_rule_override_regex.toml
create mode 100644 testdata/config/valid/extend_rule_override_secret_group.toml
create mode 100644 testdata/config/valid/extend_rule_override_tags.toml
create mode 100755 testdata/config/valid/rule_entropy_group.toml
create mode 100644 testdata/config/valid/rule_path_only.toml
create mode 100644 testdata/config/valid/rule_regex_escaped_character_group.toml
create mode 100644 testdata/expected/git/small-branch-foo.txt
create mode 100644 testdata/expected/git/small.txt
create mode 100644 testdata/expected/report/csv_simple.csv
create mode 100644 testdata/expected/report/empty.json
create mode 100644 testdata/expected/report/json_simple.json
create mode 100644 testdata/expected/report/junit_empty.xml
create mode 100644 testdata/expected/report/junit_simple.xml
create mode 100644 testdata/expected/report/sarif_simple.sarif
create mode 100644 testdata/expected/report/template_jsonextra.json
create mode 100644 testdata/expected/report/template_markdown.md
create mode 100644 testdata/gitleaksignore/.windowspaths
create mode 100644 testdata/report/jsonextra.tmpl
create mode 100644 testdata/report/markdown.tmpl
create mode 100644 testdata/repos/archives/.gitleaksignore
create mode 100644 testdata/repos/archives/README.md
create mode 100644 testdata/repos/archives/dotGit/HEAD
create mode 100644 testdata/repos/archives/dotGit/ORIG_HEAD
create mode 100644 testdata/repos/archives/dotGit/config
create mode 100644 testdata/repos/archives/dotGit/description
create mode 100644 testdata/repos/archives/dotGit/index
create mode 100644 testdata/repos/archives/dotGit/info/exclude
create mode 100644 testdata/repos/archives/dotGit/info/refs
create mode 100644 testdata/repos/archives/dotGit/objects/info/commit-graph
create mode 100644 testdata/repos/archives/dotGit/objects/info/packs
create mode 100644 testdata/repos/archives/dotGit/objects/pack/pack-9d774732f0e985d717a26e126e6574d089375b0d.idx
create mode 100644 testdata/repos/archives/dotGit/objects/pack/pack-9d774732f0e985d717a26e126e6574d089375b0d.pack
create mode 100644 testdata/repos/archives/dotGit/objects/pack/pack-9d774732f0e985d717a26e126e6574d089375b0d.rev
create mode 100644 testdata/repos/archives/dotGit/packed-refs
create mode 100644 testdata/repos/archives/dotGit/refs/.gitkeep
create mode 100644 testdata/repos/archives/main.go.zst
create mode 100644 testdata/repos/nogit/.env.prod
create mode 100644 testdata/repos/nogit/.gitleaksignore
create mode 100644 testdata/repos/nogit/api.go
create mode 100644 testdata/repos/nogit/main.go
create mode 100644 testdata/repos/small/.gitleaksignore
create mode 100644 testdata/repos/small/README.md
create mode 100644 testdata/repos/small/api/api.go
create mode 100644 testdata/repos/small/api/ignoreCommit.go
create mode 100644 testdata/repos/small/api/ignoreGlobal.go
create mode 100644 testdata/repos/small/dotGit/COMMIT_EDITMSG
create mode 100644 testdata/repos/small/dotGit/FETCH_HEAD
create mode 100644 testdata/repos/small/dotGit/HEAD
create mode 100644 testdata/repos/small/dotGit/ORIG_HEAD
create mode 100644 testdata/repos/small/dotGit/config
create mode 100644 testdata/repos/small/dotGit/description
create mode 100644 testdata/repos/small/dotGit/index
create mode 100644 testdata/repos/small/dotGit/info/exclude
create mode 100644 testdata/repos/small/dotGit/logs/HEAD
create mode 100644 testdata/repos/small/dotGit/logs/refs/heads/api-pkg
create mode 100644 testdata/repos/small/dotGit/logs/refs/heads/foo
create mode 100644 testdata/repos/small/dotGit/logs/refs/heads/main
create mode 100644 testdata/repos/small/dotGit/logs/refs/heads/remove-secrets
create mode 100644 testdata/repos/small/dotGit/logs/refs/remotes/origin/HEAD
create mode 100644 testdata/repos/small/dotGit/logs/refs/remotes/origin/api-pkg
create mode 100644 testdata/repos/small/dotGit/logs/refs/remotes/origin/foo
create mode 100644 testdata/repos/small/dotGit/logs/refs/remotes/origin/main
create mode 100644 testdata/repos/small/dotGit/objects/02/d85657604c34e7b7fbb324a0c6c8b13c2c3760
create mode 100644 testdata/repos/small/dotGit/objects/15/2888a42422b2ff5868b8d003d626120a9cb738
create mode 100644 testdata/repos/small/dotGit/objects/2e/1db472eeba53f06c4026ae4566ea022e36598e
create mode 100644 testdata/repos/small/dotGit/objects/32/bfaec6697c1a693f71b183d3389ad2547bbb3c
create mode 100644 testdata/repos/small/dotGit/objects/49/1504d5a31946ce75e22554cc34203d8e5ff3ca
create mode 100644 testdata/repos/small/dotGit/objects/4f/77f1b3cc39d4b17e4cf4ba0a38f5daed9875b4
create mode 100644 testdata/repos/small/dotGit/objects/53/cd7a3c6eb4937f413e3c25e4a9f39289afa69e
create mode 100644 testdata/repos/small/dotGit/objects/5c/547e4215d9594c3935bdfefdf4f500016a4112
create mode 100644 testdata/repos/small/dotGit/objects/78/9ba677976d5db481de55c799d67acbf8e3f16a
create mode 100644 testdata/repos/small/dotGit/objects/8d/c20a62e189d3446cfb6ec328dbd379d64feb20
create mode 100644 testdata/repos/small/dotGit/objects/90/6335481df9a4b48906c90318b4fac76b67fe73
create mode 100644 testdata/repos/small/dotGit/objects/98/1ab8417104c91bb9a4657f5d436c760c0aff50
create mode 100644 testdata/repos/small/dotGit/objects/9a/932e37eaa9fb64b09e47e5e859c9b2c8cb47ad
create mode 100644 testdata/repos/small/dotGit/objects/a1/22b33c6bad3ee54724f52f2caad385ab1982ab
create mode 100644 testdata/repos/small/dotGit/objects/a5/caae6d742e49a33982f1fdc608ce861ea59be5
create mode 100644 testdata/repos/small/dotGit/objects/a9/aa0c942dcef669a94f207a77426106b25efd1a
create mode 100644 testdata/repos/small/dotGit/objects/ac/bef43fdb053ec01e8e16697536d47853460cbc
create mode 100644 testdata/repos/small/dotGit/objects/bc/f47ef84f29bb7ed6e653d61fccd30d0ecce886
create mode 100644 testdata/repos/small/dotGit/objects/ca/da78a9bf157ec05573f19e682d211f811c2e2d
create mode 100644 testdata/repos/small/dotGit/objects/d8/32479114dc6be7207edc7c37ce91dd11b93161
create mode 100644 testdata/repos/small/dotGit/objects/da/2622b4d97e32c5801511244b809144b6b3ea78
create mode 100644 testdata/repos/small/dotGit/objects/da/eb160a13200a3422e73296a6892784a113e0d6
create mode 100644 testdata/repos/small/dotGit/objects/df/7eaa59fc89b3e7258167605db2e582f1a78e6f
create mode 100644 testdata/repos/small/dotGit/objects/e5/c0849a65c586eab87dcfc31fec74f0fd7c62cb
create mode 100644 testdata/repos/small/dotGit/objects/f1/b58b97808f8e744f6a23c693859df5b5968901
create mode 100644 testdata/repos/small/dotGit/objects/fa/468655086f149d41a8e7db14ed054bebec7687
create mode 100644 testdata/repos/small/dotGit/objects/pack/pack-2cdc2976b84768d0829c75cc8d8fc4d849be62cd.idx
create mode 100644 testdata/repos/small/dotGit/objects/pack/pack-2cdc2976b84768d0829c75cc8d8fc4d849be62cd.pack
create mode 100644 testdata/repos/small/dotGit/packed-refs
create mode 100644 testdata/repos/small/dotGit/refs/heads/api-pkg
create mode 100644 testdata/repos/small/dotGit/refs/heads/foo
create mode 100644 testdata/repos/small/dotGit/refs/heads/main
create mode 100644 testdata/repos/small/dotGit/refs/heads/remove-secrets
create mode 100644 testdata/repos/small/dotGit/refs/remotes/origin/HEAD
create mode 100644 testdata/repos/small/dotGit/refs/remotes/origin/api-pkg
create mode 100644 testdata/repos/small/dotGit/refs/remotes/origin/foo
create mode 100644 testdata/repos/small/dotGit/refs/remotes/origin/main
create mode 100644 testdata/repos/small/main.go
create mode 100644 testdata/repos/staged/.gitleaksignore
create mode 100644 testdata/repos/staged/README.md
create mode 100644 testdata/repos/staged/api/api.go
create mode 100644 testdata/repos/staged/dotGit/COMMIT_EDITMSG
create mode 100644 testdata/repos/staged/dotGit/FETCH_HEAD
create mode 100644 testdata/repos/staged/dotGit/HEAD
create mode 100644 testdata/repos/staged/dotGit/ORIG_HEAD
create mode 100644 testdata/repos/staged/dotGit/config
create mode 100644 testdata/repos/staged/dotGit/description
create mode 100644 testdata/repos/staged/dotGit/index
create mode 100644 testdata/repos/staged/dotGit/info/exclude
create mode 100644 testdata/repos/staged/dotGit/logs/HEAD
create mode 100644 testdata/repos/staged/dotGit/logs/refs/heads/api-pkg
create mode 100644 testdata/repos/staged/dotGit/logs/refs/heads/foo
create mode 100644 testdata/repos/staged/dotGit/logs/refs/heads/main
create mode 100644 testdata/repos/staged/dotGit/logs/refs/heads/remove-secrets
create mode 100644 testdata/repos/staged/dotGit/logs/refs/remotes/origin/HEAD
create mode 100644 testdata/repos/staged/dotGit/logs/refs/remotes/origin/api-pkg
create mode 100644 testdata/repos/staged/dotGit/logs/refs/remotes/origin/foo
create mode 100644 testdata/repos/staged/dotGit/logs/refs/remotes/origin/main
create mode 100644 testdata/repos/staged/dotGit/objects/02/d85657604c34e7b7fbb324a0c6c8b13c2c3760
create mode 100644 testdata/repos/staged/dotGit/objects/15/2888a42422b2ff5868b8d003d626120a9cb738
create mode 100644 testdata/repos/staged/dotGit/objects/2e/1db472eeba53f06c4026ae4566ea022e36598e
create mode 100644 testdata/repos/staged/dotGit/objects/46/18d7e4512b6b0b1dab85cf846d9f43474ec8be
create mode 100644 testdata/repos/staged/dotGit/objects/49/1504d5a31946ce75e22554cc34203d8e5ff3ca
create mode 100644 testdata/repos/staged/dotGit/objects/5c/547e4215d9594c3935bdfefdf4f500016a4112
create mode 100644 testdata/repos/staged/dotGit/objects/65/83d6db4a57bbeda62d50fc91649036d499418d
create mode 100644 testdata/repos/staged/dotGit/objects/66/bc70d0c0bfbb6468b3f90c3f1e9f2ddba02b43
create mode 100644 testdata/repos/staged/dotGit/objects/78/9ba677976d5db481de55c799d67acbf8e3f16a
create mode 100644 testdata/repos/staged/dotGit/objects/90/6335481df9a4b48906c90318b4fac76b67fe73
create mode 100644 testdata/repos/staged/dotGit/objects/9a/932e37eaa9fb64b09e47e5e859c9b2c8cb47ad
create mode 100644 testdata/repos/staged/dotGit/objects/a1/22b33c6bad3ee54724f52f2caad385ab1982ab
create mode 100644 testdata/repos/staged/dotGit/objects/a5/caae6d742e49a33982f1fdc608ce861ea59be5
create mode 100644 testdata/repos/staged/dotGit/objects/a9/aa0c942dcef669a94f207a77426106b25efd1a
create mode 100644 testdata/repos/staged/dotGit/objects/b1/6d768dd595a59f947abe087901183d219d7e54
create mode 100644 testdata/repos/staged/dotGit/objects/bc/f47ef84f29bb7ed6e653d61fccd30d0ecce886
create mode 100644 testdata/repos/staged/dotGit/objects/bf/3f24164d7256b4021575cbdb2f97b98e6f057e
create mode 100644 testdata/repos/staged/dotGit/objects/d8/32479114dc6be7207edc7c37ce91dd11b93161
create mode 100644 testdata/repos/staged/dotGit/objects/da/2622b4d97e32c5801511244b809144b6b3ea78
create mode 100644 testdata/repos/staged/dotGit/objects/e5/c0849a65c586eab87dcfc31fec74f0fd7c62cb
create mode 100644 testdata/repos/staged/dotGit/objects/f1/b58b97808f8e744f6a23c693859df5b5968901
create mode 100644 testdata/repos/staged/dotGit/objects/pack/pack-2cdc2976b84768d0829c75cc8d8fc4d849be62cd.idx
create mode 100644 testdata/repos/staged/dotGit/objects/pack/pack-2cdc2976b84768d0829c75cc8d8fc4d849be62cd.pack
create mode 100644 testdata/repos/staged/dotGit/packed-refs
create mode 100644 testdata/repos/staged/dotGit/refs/heads/api-pkg
create mode 100644 testdata/repos/staged/dotGit/refs/heads/foo
create mode 100644 testdata/repos/staged/dotGit/refs/heads/main
create mode 100644 testdata/repos/staged/dotGit/refs/heads/remove-secrets
create mode 100644 testdata/repos/staged/dotGit/refs/remotes/origin/HEAD
create mode 100644 testdata/repos/staged/dotGit/refs/remotes/origin/api-pkg
create mode 100644 testdata/repos/staged/dotGit/refs/remotes/origin/foo
create mode 100644 testdata/repos/staged/dotGit/refs/remotes/origin/main
create mode 100644 testdata/repos/staged/main.go
create mode 120000 testdata/repos/symlinks/file_symlink/symlinked_id_ed25519
create mode 100644 testdata/repos/symlinks/source_file/id_ed25519
create mode 100644 version/version.go
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 0000000..57c60df
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1,8 @@
+# Default — every PR requires at least one org member review.
+* @bryanbeverly @dustin-decker @dxa4481 @zricethezav
+
+# Release-critical paths
+/.github/ @bryanbeverly @dustin-decker @dxa4481 @zricethezav
+/.goreleaser.yml @bryanbeverly @dustin-decker @dxa4481 @zricethezav
+/go.mod @bryanbeverly @dustin-decker @dxa4481 @zricethezav
+/go.sum @bryanbeverly @dustin-decker @dxa4481 @zricethezav
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000..c9e8d91
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,3 @@
+# These are supported funding model platforms
+
+github: [zricethezav]
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..6e45ca8
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,37 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: bug
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior:
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Basic Info (please complete the following information):**
+ - OS:
+ - Gitleaks Version:
+
+**Additional context**
+Add any other context about the problem here.
+
+cc @zricethezav
+
+
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000..023f401
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,22 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: enhancement
+assignees: ''
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
+
+cc @zricethezav
diff --git a/.github/ISSUE_TEMPLATE/maintenance.md b/.github/ISSUE_TEMPLATE/maintenance.md
new file mode 100644
index 0000000..7f42bb9
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/maintenance.md
@@ -0,0 +1,16 @@
+---
+name: Maintenance request
+about: Suggest an idea for this project
+title: ''
+labels: enhancement
+assignees: ''
+
+---
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
+
+cc @zricethezav
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..11500c5
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,8 @@
+### Description:
+Explain the purpose of the PR.
+
+### Checklist:
+
+* [ ] Does your PR pass tests?
+* [ ] Have you written new tests for your changes?
+* [ ] Have you lint your code locally prior to submission?
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..71bdfa7
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,17 @@
+version: 2
+updates:
+ - package-ecosystem: "gomod"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ open-pull-requests-limit: 10
+
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ open-pull-requests-limit: 5
+ groups:
+ actions:
+ patterns:
+ - "*"
diff --git a/.github/workflows/gitleaks.yml b/.github/workflows/gitleaks.yml
new file mode 100644
index 0000000..18d9c48
--- /dev/null
+++ b/.github/workflows/gitleaks.yml
@@ -0,0 +1,17 @@
+name: gitleaks
+on:
+ push:
+ workflow_dispatch:
+jobs:
+ scan:
+ name: gitleaks
+ runs-on: ubuntu-latest
+ if: ${{ github.repository == 'gitleaks/gitleaks' }}
+ steps:
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
+ with:
+ fetch-depth: 0
+ - uses: gitleaks/gitleaks-action@e0c47f4f8be36e29cdc102c57e68cb5cbf0e8d1e # v3
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE}}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..1ad5c31
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,57 @@
+name: Create and publish a Docker image
+
+on:
+ release:
+ types: [published]
+
+env:
+ REGISTRY: ghcr.io
+ IMAGE_NAME: ${{ github.repository }}
+
+jobs:
+ build-and-push-image:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
+
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
+
+ - name: Set up Docker Buildx
+ id: buildx
+ uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
+
+ - name: Log in to Docker Hub
+ uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
+ with:
+ username: ${{ github.actor }}
+ password: ${{ secrets.DOCKER_PASSWORD }}
+
+ - name: Log in to the Container registry
+ uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Extract metadata (tags, labels) for Docker
+ id: meta
+ uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
+ with:
+ images: |
+ zricethezav/gitleaks
+ ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
+
+ - name: Build and push Docker image
+ uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
+ with:
+ platforms: linux/amd64,linux/arm64
+ context: .
+ push: true
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: ${{ steps.meta.outputs.labels }}
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 0000000..73c33ca
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,37 @@
+name: Test
+
+on:
+ push:
+ branches:
+ - "*"
+ pull_request:
+ branches:
+ - "*"
+
+jobs:
+ test:
+ strategy:
+ matrix:
+ platform: [ ubuntu-latest, windows-latest ]
+ runs-on: ${{ matrix.platform }}
+ steps:
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
+
+ - name: Set up Go
+ uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
+ with:
+ go-version: 1.25
+
+ - name: Build
+ run: go build ./...
+
+ - name: Set up gotestsum
+ run: |
+ go install gotest.tools/gotestsum@latest
+
+ - name: Test
+ run: |
+ gotestsum --raw-command -- go test -json ./... --race
+
+ - name: Validate Config
+ run: go generate ./... && git diff --exit-code
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2b4ef2a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,24 @@
+# Binaries for programs and plugins
+*.exe
+*.exe~
+*.dll
+*.so
+*.dylib
+*.DS_STORE
+*.idea
+*.got
+gitleaks
+build
+profile
+
+# configs
+.gitleaks.toml
+cmd/generate/config/gitleaks.toml
+
+# test results
+testdata/expected/report/*.got.*
+
+# Test binary
+*.out
+
+dist/
diff --git a/.gitleaksignore b/.gitleaksignore
new file mode 100644
index 0000000..f38a99f
--- /dev/null
+++ b/.gitleaksignore
@@ -0,0 +1,944 @@
+418edf165dbb63d6f46993ae8f8818ffd87ea582:cmd/generate/config/rules/jwt.go:jwt:17
+418edf165dbb63d6f46993ae8f8818ffd87ea582:cmd/generate/config/rules/jwt.go:jwt:19
+525d9792b1e3670b4630b8fcc385ca22e8544f9b:cmd/generate/config/rules/sidekiq.go:sidekiq-sensitive-url:46
+525d9792b1e3670b4630b8fcc385ca22e8544f9b:cmd/generate/config/rules/sidekiq.go:sidekiq-sensitive-url:48
+525d9792b1e3670b4630b8fcc385ca22e8544f9b:cmd/generate/config/rules/sidekiq.go:sidekiq-sensitive-url:50
+525d9792b1e3670b4630b8fcc385ca22e8544f9b:cmd/generate/config/rules/sidekiq.go:sidekiq-sensitive-url:52
+525d9792b1e3670b4630b8fcc385ca22e8544f9b:cmd/generate/config/rules/sidekiq.go:sidekiq-sensitive-url:54
+525d9792b1e3670b4630b8fcc385ca22e8544f9b:cmd/generate/config/rules/sidekiq.go:sidekiq-sensitive-url:55
+525d9792b1e3670b4630b8fcc385ca22e8544f9b:cmd/generate/config/rules/sidekiq.go:sidekiq-sensitive-url:56
+525d9792b1e3670b4630b8fcc385ca22e8544f9b:cmd/generate/config/rules/sidekiq.go:sidekiq-sensitive-url:57
+525d9792b1e3670b4630b8fcc385ca22e8544f9b:cmd/generate/config/rules/sidekiq.go:sidekiq-secret:22
+525d9792b1e3670b4630b8fcc385ca22e8544f9b:cmd/generate/config/rules/sidekiq.go:sidekiq-secret:23
+525d9792b1e3670b4630b8fcc385ca22e8544f9b:cmd/generate/config/rules/sidekiq.go:sidekiq-secret:24
+525d9792b1e3670b4630b8fcc385ca22e8544f9b:cmd/generate/config/rules/sidekiq.go:sidekiq-secret:28
+525d9792b1e3670b4630b8fcc385ca22e8544f9b:cmd/generate/config/rules/sidekiq.go:sidekiq-secret:29
+525d9792b1e3670b4630b8fcc385ca22e8544f9b:detect/detect_test.go:sidekiq-sensitive-url:164
+525d9792b1e3670b4630b8fcc385ca22e8544f9b:detect/detect_test.go:sidekiq-sensitive-url:170
+525d9792b1e3670b4630b8fcc385ca22e8544f9b:detect/detect_test.go:sidekiq-secret:120
+525d9792b1e3670b4630b8fcc385ca22e8544f9b:detect/detect_test.go:sidekiq-secret:126
+525d9792b1e3670b4630b8fcc385ca22e8544f9b:detect/detect_test.go:sidekiq-secret:142
+31650f01e76858ce7a0490943426e84a0824bbc8:config/config_test.go:aws-access-token:31
+5ed010c944ccc715cb9245abafd4e97d98d75e9f:config/config_test.go:aws-access-token:31
+ad7509e3b47331ce9586743ace635422843b695b:cmd/generate/config/rules/privatekey.go:private-key:22
+717cf1b10be1625875199eca8cdf48883348985f:README.md:aws-access-token:23
+3474c58c9e25fe2b1cee855a35bd1bf8a8c0fae8:cmd/generate/config/rules/generic.go:clojars-api-token:38
+a42b32bdf11b6f4ea5c32ec76a1731b4b0c5e52a:cmd/generate/config/rules/generic.go:generic-api-key:40
+a42b32bdf11b6f4ea5c32ec76a1731b4b0c5e52a:cmd/generate/config/rules/generic.go:generic-api-key:41
+3e5e63956ea770be734dcb7642cf515910154fb5:detect/detect_test.go:aws-access-token:50
+3e5e63956ea770be734dcb7642cf515910154fb5:detect/detect_test.go:aws-access-token:60
+3e5e63956ea770be734dcb7642cf515910154fb5:detect/detect_test.go:aws-access-token:61
+6e72472b6019d29eaa4b76b39700cd2418741f0c:detect/detect_test.go:pypi-upload-token:29
+6e72472b6019d29eaa4b76b39700cd2418741f0c:detect/detect_test.go:aws-access-token:51
+6e72472b6019d29eaa4b76b39700cd2418741f0c:detect/detect_test.go:aws-access-token:73
+6e72472b6019d29eaa4b76b39700cd2418741f0c:detect/detect_test.go:aws-access-token:81
+6e72472b6019d29eaa4b76b39700cd2418741f0c:detect/detect_test.go:aws-access-token:89
+33082a996774ba4c8ad4ba26fd219d77497eb960:README.md:sidekiq-secret:43
+6e72472b6019d29eaa4b76b39700cd2418741f0c:detect/detect_test.go:discord-api-token:98
+57d2d345b6b6ea220be9d99792b21a75359555c0:detect/detect_test.go:aws-access-token:235
+57d2d345b6b6ea220be9d99792b21a75359555c0:detect/detect_test.go:aws-access-token:236
+57d2d345b6b6ea220be9d99792b21a75359555c0:detect/detect_test.go:aws-access-token:253
+57d2d345b6b6ea220be9d99792b21a75359555c0:detect/detect_test.go:aws-access-token:254
+57d2d345b6b6ea220be9d99792b21a75359555c0:detect/detect_test.go:aws-access-token:278
+57d2d345b6b6ea220be9d99792b21a75359555c0:detect/detect_test.go:aws-access-token:279
+57d2d345b6b6ea220be9d99792b21a75359555c0:detect/detect_test.go:aws-access-token:343
+57d2d345b6b6ea220be9d99792b21a75359555c0:detect/detect_test.go:aws-access-token:344
+57d2d345b6b6ea220be9d99792b21a75359555c0:detect/detect_test.go:aws-access-token:362
+57d2d345b6b6ea220be9d99792b21a75359555c0:detect/detect_test.go:aws-access-token:363
+c9bc6b46087e700a42eb3492cf2053b7da4a6d9e:detect/detect_test.go:pypi-upload-token:27
+c9bc6b46087e700a42eb3492cf2053b7da4a6d9e:detect/detect_test.go:aws-access-token:49
+c9bc6b46087e700a42eb3492cf2053b7da4a6d9e:detect/detect_test.go:aws-access-token:71
+c9bc6b46087e700a42eb3492cf2053b7da4a6d9e:detect/detect_test.go:aws-access-token:79
+c9bc6b46087e700a42eb3492cf2053b7da4a6d9e:detect/detect_test.go:aws-access-token:87
+6e72472b6019d29eaa4b76b39700cd2418741f0c:detect/detect_test.go:discord-api-token:120
+c9bc6b46087e700a42eb3492cf2053b7da4a6d9e:detect/detect_test.go:discord-api-token:96
+6e72472b6019d29eaa4b76b39700cd2418741f0c:detect/detect_test.go:discord-api-token:128
+c9bc6b46087e700a42eb3492cf2053b7da4a6d9e:detect/detect_test.go:discord-api-token:118
+6e72472b6019d29eaa4b76b39700cd2418741f0c:detect/detect_test.go:discord-api-token:150
+c9bc6b46087e700a42eb3492cf2053b7da4a6d9e:detect/detect_test.go:discord-api-token:126
+6e72472b6019d29eaa4b76b39700cd2418741f0c:detect/detect_test.go:discord-api-token:166
+6e72472b6019d29eaa4b76b39700cd2418741f0c:detect/detect_test.go:aws-access-token:175
+6e72472b6019d29eaa4b76b39700cd2418741f0c:detect/detect_test.go:aws-access-token:183
+6e72472b6019d29eaa4b76b39700cd2418741f0c:detect/detect_test.go:aws-access-token:238
+6e72472b6019d29eaa4b76b39700cd2418741f0c:detect/detect_test.go:aws-access-token:239
+6e72472b6019d29eaa4b76b39700cd2418741f0c:detect/detect_test.go:aws-access-token:256
+6e72472b6019d29eaa4b76b39700cd2418741f0c:detect/detect_test.go:aws-access-token:257
+6e72472b6019d29eaa4b76b39700cd2418741f0c:detect/detect_test.go:aws-access-token:281
+6e72472b6019d29eaa4b76b39700cd2418741f0c:detect/detect_test.go:aws-access-token:282
+6e72472b6019d29eaa4b76b39700cd2418741f0c:detect/detect_test.go:aws-access-token:356
+6e72472b6019d29eaa4b76b39700cd2418741f0c:detect/detect_test.go:aws-access-token:357
+6e72472b6019d29eaa4b76b39700cd2418741f0c:detect/detect_test.go:aws-access-token:375
+6e72472b6019d29eaa4b76b39700cd2418741f0c:detect/detect_test.go:aws-access-token:376
+c9bc6b46087e700a42eb3492cf2053b7da4a6d9e:detect/detect_test.go:discord-api-token:148
+17b5540fb16bd9816d2a3a83f65cedf5918eaf70:detect/detect_test.go:pypi-upload-token:27
+17b5540fb16bd9816d2a3a83f65cedf5918eaf70:detect/detect_test.go:pypi-upload-token:32
+17b5540fb16bd9816d2a3a83f65cedf5918eaf70:detect/detect_test.go:pypi-upload-token:33
+c9bc6b46087e700a42eb3492cf2053b7da4a6d9e:detect/detect_test.go:discord-api-token:164
+c9bc6b46087e700a42eb3492cf2053b7da4a6d9e:detect/detect_test.go:aws-access-token:173
+c9bc6b46087e700a42eb3492cf2053b7da4a6d9e:detect/detect_test.go:aws-access-token:181
+ce42947cae32cda8d5d8813c1a8ce82eb06f018e:detect/git_test.go:aws-access-token:43
+ce42947cae32cda8d5d8813c1a8ce82eb06f018e:detect/git_test.go:aws-access-token:60
+ce42947cae32cda8d5d8813c1a8ce82eb06f018e:detect/git_test.go:aws-access-token:85
+b8141713e89f5acec500c7a62415f0f1cb7234dc:README.md:discord-client-secret:273
+98d5648f6e54ea84ca915c73fff88ad3bc5809e0:README.md:aws-access-token:130
+b8141713e89f5acec500c7a62415f0f1cb7234dc:README.md:discord-client-secret:289
+98d5648f6e54ea84ca915c73fff88ad3bc5809e0:README.md:discord-client-secret:251
+98d5648f6e54ea84ca915c73fff88ad3bc5809e0:README.md:discord-client-secret:267
+98d5648f6e54ea84ca915c73fff88ad3bc5809e0:detect/detect_test.go:aws-access-token:33
+98d5648f6e54ea84ca915c73fff88ad3bc5809e0:detect/files_test.go:aws-access-token:32
+98d5648f6e54ea84ca915c73fff88ad3bc5809e0:detect/files_test.go:aws-access-token:50
+98d5648f6e54ea84ca915c73fff88ad3bc5809e0:config/config_test.go:generic-api-key:133
+80d29764a0bc0f269607d3eb7b2774a0f31e5da3:detect/detect_test.go:aws-access-token:123
+80d29764a0bc0f269607d3eb7b2774a0f31e5da3:testdata/config/allow_global_aws_re.toml:aws-access-token:8
+4acd7a3c8d20b7116a32f9bbade6a3cf15f741e4:detect/detect_test.go:aws-access-token:117
+f0b8d26c9988af725132c100dda5051586a3026e:README.md:discord-client-secret:225
+98d5648f6e54ea84ca915c73fff88ad3bc5809e0:config/config_test.go:generic-api-key:144
+93f292c3dfa2649ef91f8925b623e79546fa992e:README.md:aws-access-token:121
+93f292c3dfa2649ef91f8925b623e79546fa992e:README.md:aws-access-token:122
+93f292c3dfa2649ef91f8925b623e79546fa992e:README.md:aws-access-token:157
+93f292c3dfa2649ef91f8925b623e79546fa992e:config/config_test.go:aws-access-token:31
+93f292c3dfa2649ef91f8925b623e79546fa992e:detect/files_test.go:aws-access-token:32
+93f292c3dfa2649ef91f8925b623e79546fa992e:detect/files_test.go:aws-access-token:33
+93f292c3dfa2649ef91f8925b623e79546fa992e:detect/files_test.go:aws-access-token:50
+93f292c3dfa2649ef91f8925b623e79546fa992e:detect/files_test.go:aws-access-token:51
+93f292c3dfa2649ef91f8925b623e79546fa992e:detect/git_test.go:aws-access-token:42
+93f292c3dfa2649ef91f8925b623e79546fa992e:detect/git_test.go:aws-access-token:44
+93f292c3dfa2649ef91f8925b623e79546fa992e:detect/git_test.go:aws-access-token:58
+93f292c3dfa2649ef91f8925b623e79546fa992e:detect/git_test.go:aws-access-token:60
+93f292c3dfa2649ef91f8925b623e79546fa992e:detect/git_test.go:aws-access-token:82
+93f292c3dfa2649ef91f8925b623e79546fa992e:detect/git_test.go:aws-access-token:83
+93f292c3dfa2649ef91f8925b623e79546fa992e:config/config_test.go:generic-api-key:133
+93f292c3dfa2649ef91f8925b623e79546fa992e:testdata/config/allow_aws_re.toml:aws-access-token:9
+93f292c3dfa2649ef91f8925b623e79546fa992e:config/config_test.go:generic-api-key:144
+93f292c3dfa2649ef91f8925b623e79546fa992e:testdata/expected/git/small-branch-foo.txt:aws-access-token:15
+93f292c3dfa2649ef91f8925b623e79546fa992e:testdata/repos/nogit/main.go:aws-access-token:20
+93f292c3dfa2649ef91f8925b623e79546fa992e:testdata/expected/git/small.txt:aws-access-token:15
+93f292c3dfa2649ef91f8925b623e79546fa992e:testdata/expected/git/small.txt:aws-access-token:44
+3a3e13c3b5f85b0116cf2a0cd92529baf22d0ac9:testdata/repos/with_square_and_google/env:generic-api-key:3
+6adc045580c3911a7a936be7b977979a5519aa29:scan/unstaged_test.go:aws-access-token:38
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/basic/results_208ae46.json:aws-access-token:3
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/basic/results_208ae46.json:aws-access-token:5
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/basic/results_ae8db4a2_208ae46.json:aws-access-token:3
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/basic/results_ae8db4a2_208ae46.json:aws-access-token:5
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/basic/results.json:aws-access-token:3
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/basic/results.json:aws-access-token:5
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/basic/results.json:aws-access-token:20
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/basic/results.json:aws-access-token:22
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/basic/results_depth_1.json:aws-access-token:3
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/basic/results_depth_1.json:aws-access-token:5
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/basic/results_files_at_208ae46.json:aws-access-token:3
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/basic/results_files_at_208ae46.json:aws-access-token:5
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/basic/results_files_at_208ae46.json:aws-access-token:20
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/basic/results_files_at_208ae46.json:aws-access-token:22
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/basic/results_no_git.json:aws-access-token:3
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/basic/results_no_git.json:aws-access-token:5
+93f292c3dfa2649ef91f8925b623e79546fa992e:detect/detect_test.go:aws-access-token:26
+93f292c3dfa2649ef91f8925b623e79546fa992e:detect/detect_test.go:aws-access-token:31
+93f292c3dfa2649ef91f8925b623e79546fa992e:detect/detect_test.go:aws-access-token:40
+93f292c3dfa2649ef91f8925b623e79546fa992e:detect/detect_test.go:aws-access-token:46
+93f292c3dfa2649ef91f8925b623e79546fa992e:detect/detect_test.go:aws-access-token:52
+93f292c3dfa2649ef91f8925b623e79546fa992e:detect/detect_test.go:discord-api-token:59
+93f292c3dfa2649ef91f8925b623e79546fa992e:detect/detect_test.go:discord-api-token:74
+93f292c3dfa2649ef91f8925b623e79546fa992e:detect/detect_test.go:discord-api-token:80
+93f292c3dfa2649ef91f8925b623e79546fa992e:detect/detect_test.go:discord-api-token:95
+93f292c3dfa2649ef91f8925b623e79546fa992e:detect/detect_test.go:discord-api-token:109
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/basic/results_no_git.json:aws-access-token:20
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/basic/results_no_git.json:aws-access-token:22
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/basic/results_unstaged.json:aws-access-token:3
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/repos/basic/secrets.py:generic-api-key:5
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/repos/basic/secrets.py:generic-api-key:6
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/repos/basic/secrets.py:aws-access-token:9
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/repos/basic/secrets.py:aws-access-token:13
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/with_config/results.json:aws-access-token:3
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/with_config/results.json:aws-access-token:5
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/with_config/results.json:aws-access-token:54
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/with_config/results.json:aws-access-token:56
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/with_config/results.json:generic-api-key:20
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/with_config/results.json:generic-api-key:22
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/with_config/results.json:generic-api-key:37
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/with_config/results.json:generic-api-key:39
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/with_config/results_e7c0aff3.json:generic-api-key:3
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/with_config/results_e7c0aff3.json:generic-api-key:5
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/with_config/results_e7c0aff3.json:generic-api-key:20
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/with_config/results_e7c0aff3.json:generic-api-key:22
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/with_config/results_e7c0aff3.json:aws-access-token:37
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/with_config/results_e7c0aff3.json:aws-access-token:39
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/with_config/results_ae8db4a_e7c0aff.json:aws-access-token:37
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/with_config/results_ae8db4a_e7c0aff.json:aws-access-token:39
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/with_config/results_ae8db4a_e7c0aff.json:generic-api-key:3
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/with_config/results_ae8db4a_e7c0aff.json:generic-api-key:5
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/with_config/results_ae8db4a_e7c0aff.json:generic-api-key:20
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/expect/with_config/results_ae8db4a_e7c0aff.json:generic-api-key:22
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/repos/with_config/secrets.py:generic-api-key:5
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/repos/with_config/secrets.py:generic-api-key:6
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/repos/with_config/secrets.py:aws-access-token:9
+6adc045580c3911a7a936be7b977979a5519aa29:testdata/repos/with_config/secrets.py:aws-access-token:13
+45c898c5ea56ee503a048c1bac1404cf63855edc:test_data/test_repos/test_dir_2/env:generic-api-key:1
+45c898c5ea56ee503a048c1bac1404cf63855edc:test_data/test_repos/test_dir_2/env:generic-api-key:3
+45c898c5ea56ee503a048c1bac1404cf63855edc:test_data/test_dir_one_google_leak_and_square_leak.json:generic-api-key:3
+45c898c5ea56ee503a048c1bac1404cf63855edc:test_data/test_dir_one_google_leak_and_square_leak.json:generic-api-key:20
+65f42020afcc65de3b7dfe5a797b9f6396345250:test_data/test_local_owner_aws_leak.json:aws-access-token:35
+65f42020afcc65de3b7dfe5a797b9f6396345250:test_data/test_local_owner_aws_leak.json:aws-access-token:37
+65f42020afcc65de3b7dfe5a797b9f6396345250:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:259
+65f42020afcc65de3b7dfe5a797b9f6396345250:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:261
+65f42020afcc65de3b7dfe5a797b9f6396345250:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:339
+65f42020afcc65de3b7dfe5a797b9f6396345250:test_data/test_local_owner_aws_leak.json:aws-access-token:51
+65f42020afcc65de3b7dfe5a797b9f6396345250:test_data/test_local_owner_aws_leak.json:aws-access-token:83
+65f42020afcc65de3b7dfe5a797b9f6396345250:test_data/test_local_owner_aws_leak.json:aws-access-token:85
+65f42020afcc65de3b7dfe5a797b9f6396345250:test_data/test_local_owner_aws_leak.json:aws-access-token:131
+65f42020afcc65de3b7dfe5a797b9f6396345250:test_data/test_local_owner_aws_leak.json:aws-access-token:133
+65f42020afcc65de3b7dfe5a797b9f6396345250:test_data/test_local_owner_aws_leak.json:aws-access-token:147
+65f42020afcc65de3b7dfe5a797b9f6396345250:test_data/test_local_owner_aws_leak.json:aws-access-token:149
+65f42020afcc65de3b7dfe5a797b9f6396345250:test_data/test_local_owner_aws_leak.json:aws-access-token:179
+65f42020afcc65de3b7dfe5a797b9f6396345250:test_data/test_local_owner_aws_leak.json:aws-access-token:227
+65f42020afcc65de3b7dfe5a797b9f6396345250:test_data/test_local_owner_aws_leak.json:aws-access-token:229
+65f42020afcc65de3b7dfe5a797b9f6396345250:test_data/test_local_owner_aws_leak.json:aws-access-token:323
+65f42020afcc65de3b7dfe5a797b9f6396345250:test_data/test_local_owner_aws_leak.json:aws-access-token:355
+65f42020afcc65de3b7dfe5a797b9f6396345250:test_data/test_local_owner_aws_leak.json:aws-access-token:357
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_file1_aws_leak.json:aws-access-token:3
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_file1_aws_leak.json:aws-access-token:5
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_dir1_aws_leak.json:aws-access-token:3
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_dir1_aws_leak.json:aws-access-token:5
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_dir1_aws_leak.json:aws-access-token:17
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_dir1_aws_leak.json:aws-access-token:19
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_repos/test_dir_1/server.test.py:aws-access-token:5
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_repos/test_dir_1/server.test2.py:aws-access-token:5
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak.json:aws-access-token:99
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak.json:aws-access-token:101
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak.json:aws-access-token:115
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak.json:aws-access-token:117
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak.json:aws-access-token:131
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak.json:aws-access-token:133
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak.json:aws-access-token:147
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak.json:aws-access-token:149
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak.json:aws-access-token:163
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak.json:aws-access-token:165
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak.json:aws-access-token:179
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak.json:aws-access-token:181
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak.json:aws-access-token:195
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak.json:aws-access-token:197
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak.json:aws-access-token:211
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak.json:aws-access-token:213
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:83
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:85
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:99
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:101
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:115
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:117
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:131
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:133
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:147
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:149
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:163
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:165
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:179
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak.json:aws-access-token:259
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak.json:aws-access-token:261
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:181
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:195
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:197
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak.json:aws-access-token:339
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak.json:aws-access-token:341
+2acc34dfdfb0e7f1141eadd940ea933c645e0f86:test_data/test_local_repo_three_leaks_with_report_groups.json:aws-access-token:3
+2acc34dfdfb0e7f1141eadd940ea933c645e0f86:test_data/test_local_repo_three_leaks_with_report_groups.json:aws-access-token:5
+2acc34dfdfb0e7f1141eadd940ea933c645e0f86:test_data/test_local_repo_three_leaks_with_report_groups.json:aws-access-token:18
+2acc34dfdfb0e7f1141eadd940ea933c645e0f86:test_data/test_local_repo_three_leaks_with_report_groups.json:aws-access-token:20
+2acc34dfdfb0e7f1141eadd940ea933c645e0f86:test_data/test_local_repo_three_leaks_with_report_groups.json:aws-access-token:33
+2acc34dfdfb0e7f1141eadd940ea933c645e0f86:test_data/test_local_repo_three_leaks_with_report_groups.json:aws-access-token:35
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:259
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:261
+ad505754fc6283523ef8dfa88ecb6559e0268ec3:test_data/test_local_repo_two_leaks_commit_to_from.json:aws-access-token:3
+ad505754fc6283523ef8dfa88ecb6559e0268ec3:test_data/test_local_repo_two_leaks_commit_to_from.json:aws-access-token:5
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:323
+c50906373cc38206f3d41c57e2c413ce400e61e7:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:325
+ad505754fc6283523ef8dfa88ecb6559e0268ec3:test_data/test_local_repo_two_leaks_commit_range.json:aws-access-token:18
+ad505754fc6283523ef8dfa88ecb6559e0268ec3:test_data/test_local_repo_two_leaks_commit_range.json:aws-access-token:20
+fae366a404357fa6c6611756a11e61546ebec4e0:examples/simple_regex_and_allowlist_config.toml:aws-access-token:12
+ad505754fc6283523ef8dfa88ecb6559e0268ec3:test_data/test_local_repo_two_leaks_file_commit_range.json:aws-access-token:3
+ad505754fc6283523ef8dfa88ecb6559e0268ec3:test_data/test_local_repo_two_leaks_file_commit_range.json:aws-access-token:5
+ad505754fc6283523ef8dfa88ecb6559e0268ec3:test_data/test_local_repo_two_leaks_file_commit_range.json:aws-access-token:18
+ad505754fc6283523ef8dfa88ecb6559e0268ec3:test_data/test_local_repo_two_leaks_file_commit_range.json:aws-access-token:20
+fae366a404357fa6c6611756a11e61546ebec4e0:test_data/test_configs/aws_key_aws_allowlisted.toml:aws-access-token:7
+fae366a404357fa6c6611756a11e61546ebec4e0:test_data/test_local_owner_aws_leak.json:aws-access-token:185
+fae366a404357fa6c6611756a11e61546ebec4e0:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:95
+fae366a404357fa6c6611756a11e61546ebec4e0:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:185
+fae366a404357fa6c6611756a11e61546ebec4e0:test_data/test_local_repo_nine_aws_leak.json:aws-access-token:3
+fae366a404357fa6c6611756a11e61546ebec4e0:test_data/test_local_repo_nine_aws_leak.json:aws-access-token:5
+eabc7b5c12cb89b4a828b7aaef00fdfa694a7e0a:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:78
+eabc7b5c12cb89b4a828b7aaef00fdfa694a7e0a:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:80
+eabc7b5c12cb89b4a828b7aaef00fdfa694a7e0a:test_data/test_local_owner_aws_leak.json:aws-access-token:138
+eabc7b5c12cb89b4a828b7aaef00fdfa694a7e0a:test_data/test_local_owner_aws_leak.json:aws-access-token:140
+eabc7b5c12cb89b4a828b7aaef00fdfa694a7e0a:test_data/test_local_owner_aws_leak.json:aws-access-token:153
+eabc7b5c12cb89b4a828b7aaef00fdfa694a7e0a:test_data/test_local_owner_aws_leak.json:aws-access-token:155
+eabc7b5c12cb89b4a828b7aaef00fdfa694a7e0a:test_data/test_local_owner_aws_leak.json:aws-access-token:168
+eabc7b5c12cb89b4a828b7aaef00fdfa694a7e0a:test_data/test_local_owner_aws_leak.json:aws-access-token:170
+eabc7b5c12cb89b4a828b7aaef00fdfa694a7e0a:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:138
+eabc7b5c12cb89b4a828b7aaef00fdfa694a7e0a:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:140
+eabc7b5c12cb89b4a828b7aaef00fdfa694a7e0a:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:153
+eabc7b5c12cb89b4a828b7aaef00fdfa694a7e0a:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:155
+eabc7b5c12cb89b4a828b7aaef00fdfa694a7e0a:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:168
+eabc7b5c12cb89b4a828b7aaef00fdfa694a7e0a:test_data/test_local_owner_aws_leak_allowlist_repo.json:aws-access-token:170
+eabc7b5c12cb89b4a828b7aaef00fdfa694a7e0a:test_data/test_local_repo_eight.json:aws-access-token:3
+eabc7b5c12cb89b4a828b7aaef00fdfa694a7e0a:test_data/test_local_repo_eight.json:aws-access-token:5
+eabc7b5c12cb89b4a828b7aaef00fdfa694a7e0a:test_data/test_local_repo_eight.json:aws-access-token:18
+eabc7b5c12cb89b4a828b7aaef00fdfa694a7e0a:test_data/test_local_repo_eight.json:aws-access-token:20
+eabc7b5c12cb89b4a828b7aaef00fdfa694a7e0a:test_data/test_local_repo_eight.json:aws-access-token:33
+eabc7b5c12cb89b4a828b7aaef00fdfa694a7e0a:test_data/test_local_repo_eight.json:aws-access-token:35
+eabc7b5c12cb89b4a828b7aaef00fdfa694a7e0a:test_data/test_repos/test_repo_8/dummy.txt:aws-access-token:2
+eabc7b5c12cb89b4a828b7aaef00fdfa694a7e0a:test_data/test_repos/test_repo_8/dummy.txt:aws-access-token:6
+6ca7a11d8846af2a3d26f71c4a9083eb0b3deeee:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:48
+6ca7a11d8846af2a3d26f71c4a9083eb0b3deeee:test_data/test_local_owner_aws_leak.json:aws-access-token:48
+6ca7a11d8846af2a3d26f71c4a9083eb0b3deeee:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:33
+6ca7a11d8846af2a3d26f71c4a9083eb0b3deeee:test_data/test_local_owner_aws_leak.json:aws-access-token:93
+6ca7a11d8846af2a3d26f71c4a9083eb0b3deeee:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:78
+6ca7a11d8846af2a3d26f71c4a9083eb0b3deeee:test_data/test_local_repo_two_leaks_commit_from.json:aws-access-token:18
+6ca7a11d8846af2a3d26f71c4a9083eb0b3deeee:test_data/test_local_repo_three_leaks.json:aws-access-token:48
+6ca7a11d8846af2a3d26f71c4a9083eb0b3deeee:test_data/test_local_repo_two_leaks_deletion.json:aws-access-token:78
+6ca7a11d8846af2a3d26f71c4a9083eb0b3deeee:test_data/test_local_repo_two_leaks.json:aws-access-token:33
+bdc688dd5351adf1cf5cbf734dfd104ea6bab92b:test_data/test_local_repo_two_whitelist_commits.json:aws-access-token:3
+bdc688dd5351adf1cf5cbf734dfd104ea6bab92b:test_data/test_local_repo_two_whitelist_commits.json:aws-access-token:4
+bdc688dd5351adf1cf5cbf734dfd104ea6bab92b:test_data/test_local_repo_two_whitelist_commits.json:aws-access-token:16
+bdc688dd5351adf1cf5cbf734dfd104ea6bab92b:test_data/test_local_repo_two_whitelist_commits.json:aws-access-token:17
+e0f6399d5ccadd44544cdfe5f630de57fced1473:test_data/test_local_repo_six_leaks_since_date.json:aws-access-token:3
+e0f6399d5ccadd44544cdfe5f630de57fced1473:test_data/test_local_repo_six_leaks_since_date.json:aws-access-token:4
+e0f6399d5ccadd44544cdfe5f630de57fced1473:test_data/test_local_repo_six_leaks_until_date.json:aws-access-token:3
+e0f6399d5ccadd44544cdfe5f630de57fced1473:test_data/test_local_repo_six_leaks_until_date.json:aws-access-token:4
+0d7c18cb39c60efb62a6c7b351f95d46ebe1f63e:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:172
+0d7c18cb39c60efb62a6c7b351f95d46ebe1f63e:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:173
+e0f6399d5ccadd44544cdfe5f630de57fced1473:test_data/test_local_repo_four_leaks_commit_timerange.json:aws-access-token:3
+e0f6399d5ccadd44544cdfe5f630de57fced1473:test_data/test_local_repo_four_leaks_commit_timerange.json:aws-access-token:4
+e0f6399d5ccadd44544cdfe5f630de57fced1473:test_data/test_local_repo_four_leaks_commit_timerange.json:aws-access-token:16
+e0f6399d5ccadd44544cdfe5f630de57fced1473:test_data/test_local_repo_four_leaks_commit_timerange.json:aws-access-token:17
+e0f6399d5ccadd44544cdfe5f630de57fced1473:test_data/test_local_repo_four_leaks_commit_timerange.json:aws-access-token:29
+e0f6399d5ccadd44544cdfe5f630de57fced1473:test_data/test_local_repo_four_leaks_commit_timerange.json:aws-access-token:30
+e0f6399d5ccadd44544cdfe5f630de57fced1473:test_data/test_local_repo_four_leaks_commit_timerange.json:aws-access-token:42
+e0f6399d5ccadd44544cdfe5f630de57fced1473:test_data/test_local_repo_four_leaks_commit_timerange.json:aws-access-token:43
+e0f6399d5ccadd44544cdfe5f630de57fced1473:test_data/test_local_repo_four_leaks_commit_timerange.json:aws-access-token:55
+e0f6399d5ccadd44544cdfe5f630de57fced1473:test_data/test_local_repo_four_leaks_commit_timerange.json:aws-access-token:56
+cfbb600fcb286e1323e2e4d24144eeca163ad396:test_data/test_local_repo_two_leaks_deletion.json:aws-access-token:3
+cfbb600fcb286e1323e2e4d24144eeca163ad396:test_data/test_local_repo_two_leaks_deletion.json:aws-access-token:4
+cfbb600fcb286e1323e2e4d24144eeca163ad396:test_data/test_local_repo_two_leaks_deletion.json:aws-access-token:16
+cfbb600fcb286e1323e2e4d24144eeca163ad396:test_data/test_local_repo_two_leaks_deletion.json:aws-access-token:17
+cfbb600fcb286e1323e2e4d24144eeca163ad396:test_data/test_local_repo_two_leaks_deletion.json:aws-access-token:29
+cfbb600fcb286e1323e2e4d24144eeca163ad396:test_data/test_local_repo_two_leaks_deletion.json:aws-access-token:30
+cfbb600fcb286e1323e2e4d24144eeca163ad396:test_data/test_local_repo_two_leaks_deletion.json:aws-access-token:42
+cfbb600fcb286e1323e2e4d24144eeca163ad396:test_data/test_local_repo_two_leaks_deletion.json:aws-access-token:43
+cfbb600fcb286e1323e2e4d24144eeca163ad396:test_data/test_local_repo_two_leaks_deletion.json:aws-access-token:55
+cfbb600fcb286e1323e2e4d24144eeca163ad396:test_data/test_local_repo_two_leaks_deletion.json:aws-access-token:56
+cfbb600fcb286e1323e2e4d24144eeca163ad396:test_data/test_local_repo_two_leaks_deletion.json:aws-access-token:68
+cfbb600fcb286e1323e2e4d24144eeca163ad396:test_data/test_local_repo_two_leaks_deletion.json:aws-access-token:69
+212232f80a22c4c698dd2864006f398ea1f15107:test_data/test_local_repo_seven_aws_leak_uncommitted.json:aws-access-token:3
+212232f80a22c4c698dd2864006f398ea1f15107:test_data/test_local_repo_seven_aws_leak_uncommitted.json:aws-access-token:4
+212232f80a22c4c698dd2864006f398ea1f15107:test_data/test_repos/test_repo_7/file:aws-access-token:5
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:16
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:17
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:55
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:56
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:16
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:17
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:94
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:95
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:55
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:56
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:134
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:160
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:94
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:95
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:133
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:134
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:172
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:173
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:3
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:4
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:16
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:17
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:29
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:30
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:42
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:43
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:55
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:56
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:68
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:69
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:81
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:82
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:94
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:95
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:107
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:108
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:120
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:121
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:133
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:134
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:146
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:147
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:159
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:160
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:172
+473d0d55a71097894c5c6b9a2968ad478d2e6edf:test_data/test_local_owner_aws_leak_whitelist_repo.json:aws-access-token:173
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:185
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:186
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_five_files_at_commit.json:aws-access-token:29
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_five_files_at_commit.json:aws-access-token:30
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_five_files_at_commit.json:aws-access-token:42
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_five_files_at_commit.json:aws-access-token:43
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:224
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:225
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:211
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:212
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:263
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:264
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:237
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:238
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_one_aws_leak.json:aws-access-token:16
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_one_aws_leak.json:aws-access-token:17
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_one_aws_leak_commit.json:aws-access-token:16
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:276
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:277
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_one_aws_leak_commit.json:aws-access-token:17
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:316
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:342
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks.json:aws-access-token:16
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks.json:aws-access-token:17
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks.json:aws-access-token:55
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks.json:aws-access-token:56
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks.json:aws-access-token:95
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks.json:aws-access-token:121
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_five_files_at_latest_commit.json:aws-access-token:3
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_five_files_at_latest_commit.json:aws-access-token:4
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_five_files_at_latest_commit.json:aws-access-token:16
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_five_files_at_latest_commit.json:aws-access-token:17
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_five_files_at_latest_commit.json:aws-access-token:29
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_five_files_at_latest_commit.json:aws-access-token:30
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_five_files_at_latest_commit.json:aws-access-token:42
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_five_files_at_latest_commit.json:aws-access-token:43
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_one_aws_leak_uncommitted.json:aws-access-token:16
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_one_aws_leak_uncommitted.json:aws-access-token:17
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks_commit_from.json:aws-access-token:17
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks_commit_from.json:aws-access-token:43
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks_commit_range.json:aws-access-token:17
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks_commit_range.json:aws-access-token:43
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks.json:aws-access-token:146
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks.json:aws-access-token:147
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:380
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:381
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:406
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:407
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:445
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_owner_aws_leak.json:aws-access-token:446
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks_commit_to.json:aws-access-token:16
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks_commit_to.json:aws-access-token:17
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks_commit_from.json:aws-access-token:68
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks_commit_from.json:aws-access-token:69
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks_commit_to.json:aws-access-token:55
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks_commit_to.json:aws-access-token:56
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks.json:aws-access-token:172
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks.json:aws-access-token:173
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks_commit_range.json:aws-access-token:68
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks_commit_range.json:aws-access-token:69
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks_commit_to.json:aws-access-token:95
+94cae90d1eb208410073669de54a21fb65f23742:test_data/test_local_owner_aws_leak.json:aws-access-token:120
+94cae90d1eb208410073669de54a21fb65f23742:test_data/test_local_owner_aws_leak.json:aws-access-token:121
+94cae90d1eb208410073669de54a21fb65f23742:test_data/test_local_repo_two_leaks.json:aws-access-token:107
+94cae90d1eb208410073669de54a21fb65f23742:test_data/test_local_repo_two_leaks.json:aws-access-token:108
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks_commit_from.json:aws-access-token:94
+c6f15b768e19613228b232a712f53a39cc5120a3:test_data/test_local_repo_two_leaks_commit_from.json:aws-access-token:95
+94cae90d1eb208410073669de54a21fb65f23742:test_data/test_local_repo_three_leaks.json:aws-access-token:81
+94cae90d1eb208410073669de54a21fb65f23742:test_data/test_local_repo_three_leaks.json:aws-access-token:82
+c4b07f5113bf39019374579a64d83959236295e4:audit/util.go:aws-access-token:66
+94cae90d1eb208410073669de54a21fb65f23742:test_data/test_local_repo_two_leaks_commit_from.json:aws-access-token:55
+94cae90d1eb208410073669de54a21fb65f23742:test_data/test_local_repo_two_leaks_commit_from.json:aws-access-token:56
+94cae90d1eb208410073669de54a21fb65f23742:test_data/test_local_repo_two_leaks_commit_range.json:aws-access-token:55
+94cae90d1eb208410073669de54a21fb65f23742:test_data/test_local_repo_two_leaks_commit_range.json:aws-access-token:56
+c4b07f5113bf39019374579a64d83959236295e4:test_data/test_local_owner_aws_leak.json:aws-access-token:276
+c4b07f5113bf39019374579a64d83959236295e4:test_data/test_local_owner_aws_leak.json:aws-access-token:277
+c4b07f5113bf39019374579a64d83959236295e4:test_data/test_local_repo_one_aws_leak_and_file_leak.json:aws-access-token:16
+c4b07f5113bf39019374579a64d83959236295e4:test_data/test_local_repo_one_aws_leak_and_file_leak.json:aws-access-token:17
+c4b07f5113bf39019374579a64d83959236295e4:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:146
+c4b07f5113bf39019374579a64d83959236295e4:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:147
+c4b07f5113bf39019374579a64d83959236295e4:test_data/test_local_repo_six.json:aws-access-token:31
+c4b07f5113bf39019374579a64d83959236295e4:test_data/test_local_repo_six.json:aws-access-token:33
+c4b07f5113bf39019374579a64d83959236295e4:test_data/test_local_repo_six_filepath.json:aws-access-token:3
+c4b07f5113bf39019374579a64d83959236295e4:test_data/test_local_repo_six_filepath.json:aws-access-token:4
+c4b07f5113bf39019374579a64d83959236295e4:test_data/test_local_repo_six_path_globally_whitelisted.json:aws-access-token:3
+c4b07f5113bf39019374579a64d83959236295e4:test_data/test_local_repo_six_path_globally_whitelisted.json:aws-access-token:4
+c4b07f5113bf39019374579a64d83959236295e4:test_data/test_repos/test_repo_6/server.test.py:aws-access-token:5
+10745be661121f2e6577170419cf8ce3308ae311:test_data/test_local_repo_two_leaks_commit_to.json:aws-access-token:55
+10745be661121f2e6577170419cf8ce3308ae311:test_data/test_local_repo_two_leaks_commit_to.json:aws-access-token:56
+10745be661121f2e6577170419cf8ce3308ae311:test_data/test_local_repo_two_leaks_commit_to.json:aws-access-token:68
+10745be661121f2e6577170419cf8ce3308ae311:test_data/test_local_repo_two_leaks_commit_to.json:aws-access-token:69
+c4b07f5113bf39019374579a64d83959236295e4:test_data/test_repos/test_repo_6/config/application.properties:aws-access-token:3
+d13e0fdfde8f5c6261c9e893461f32861e21e8f5:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:133
+d13e0fdfde8f5c6261c9e893461f32861e21e8f5:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:134
+d13e0fdfde8f5c6261c9e893461f32861e21e8f5:test_data/test_local_owner_aws_leak.json:aws-access-token:250
+d13e0fdfde8f5c6261c9e893461f32861e21e8f5:test_data/test_local_owner_aws_leak.json:aws-access-token:251
+d13e0fdfde8f5c6261c9e893461f32861e21e8f5:test_data/test_local_owner_aws_leak.json:aws-access-token:263
+d13e0fdfde8f5c6261c9e893461f32861e21e8f5:test_data/test_local_owner_aws_leak.json:aws-access-token:264
+d13e0fdfde8f5c6261c9e893461f32861e21e8f5:test_data/test_local_repo_five_files_at_commit.json:aws-access-token:3
+d13e0fdfde8f5c6261c9e893461f32861e21e8f5:test_data/test_local_repo_five_files_at_commit.json:aws-access-token:4
+d13e0fdfde8f5c6261c9e893461f32861e21e8f5:test_data/test_local_repo_five_files_at_commit.json:aws-access-token:16
+d13e0fdfde8f5c6261c9e893461f32861e21e8f5:test_data/test_local_repo_five_files_at_commit.json:aws-access-token:17
+2474c39311296b4d48c284b1ce82e0c270854bde:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:3
+2474c39311296b4d48c284b1ce82e0c270854bde:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:4
+2474c39311296b4d48c284b1ce82e0c270854bde:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:16
+2474c39311296b4d48c284b1ce82e0c270854bde:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:17
+2474c39311296b4d48c284b1ce82e0c270854bde:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:42
+2474c39311296b4d48c284b1ce82e0c270854bde:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:43
+2474c39311296b4d48c284b1ce82e0c270854bde:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:68
+2474c39311296b4d48c284b1ce82e0c270854bde:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:69
+2474c39311296b4d48c284b1ce82e0c270854bde:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:94
+2474c39311296b4d48c284b1ce82e0c270854bde:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:95
+d13e0fdfde8f5c6261c9e893461f32861e21e8f5:test_data/test_repos/test_repo_5/secrets.py:aws-access-token:1
+d13e0fdfde8f5c6261c9e893461f32861e21e8f5:test_data/test_repos/test_repo_5/secrets.py:aws-access-token:4
+a0f72a4e3595ddb382a77804d2674d54b2b0e880:test_data/test_local_repo_two_leaks_commit_range.json:aws-access-token:3
+a0f72a4e3595ddb382a77804d2674d54b2b0e880:test_data/test_local_repo_two_leaks_commit_range.json:aws-access-token:4
+a0f72a4e3595ddb382a77804d2674d54b2b0e880:test_data/test_local_repo_two_leaks_commit_range.json:aws-access-token:16
+a0f72a4e3595ddb382a77804d2674d54b2b0e880:test_data/test_local_repo_two_leaks_commit_range.json:aws-access-token:17
+a0f72a4e3595ddb382a77804d2674d54b2b0e880:test_data/test_local_repo_two_leaks_commit_range.json:aws-access-token:29
+a0f72a4e3595ddb382a77804d2674d54b2b0e880:test_data/test_local_repo_two_leaks_commit_range.json:aws-access-token:30
+a0f72a4e3595ddb382a77804d2674d54b2b0e880:test_data/test_local_repo_two_leaks_commit_range.json:aws-access-token:42
+a0f72a4e3595ddb382a77804d2674d54b2b0e880:test_data/test_local_repo_two_leaks_commit_range.json:aws-access-token:43
+a0f72a4e3595ddb382a77804d2674d54b2b0e880:test_data/test_local_repo_two_leaks_commit_to.json:aws-access-token:3
+a0f72a4e3595ddb382a77804d2674d54b2b0e880:test_data/test_local_repo_two_leaks_commit_to.json:aws-access-token:4
+a0f72a4e3595ddb382a77804d2674d54b2b0e880:test_data/test_local_repo_two_leaks_commit_to.json:aws-access-token:29
+a0f72a4e3595ddb382a77804d2674d54b2b0e880:test_data/test_local_repo_two_leaks_commit_to.json:aws-access-token:30
+a0f72a4e3595ddb382a77804d2674d54b2b0e880:test_data/test_local_repo_two_leaks_commit_from.json:aws-access-token:3
+a0f72a4e3595ddb382a77804d2674d54b2b0e880:test_data/test_local_repo_two_leaks_commit_from.json:aws-access-token:4
+a0f72a4e3595ddb382a77804d2674d54b2b0e880:test_data/test_local_repo_two_leaks_commit_from.json:aws-access-token:16
+a0f72a4e3595ddb382a77804d2674d54b2b0e880:test_data/test_local_repo_two_leaks_commit_from.json:aws-access-token:17
+a0f72a4e3595ddb382a77804d2674d54b2b0e880:test_data/test_local_repo_two_leaks_commit_from.json:aws-access-token:29
+a0f72a4e3595ddb382a77804d2674d54b2b0e880:test_data/test_local_repo_two_leaks_commit_from.json:aws-access-token:30
+a0f72a4e3595ddb382a77804d2674d54b2b0e880:test_data/test_local_repo_two_leaks_commit_from.json:aws-access-token:42
+a0f72a4e3595ddb382a77804d2674d54b2b0e880:test_data/test_local_repo_two_leaks_commit_from.json:aws-access-token:43
+a0f72a4e3595ddb382a77804d2674d54b2b0e880:test_data/test_local_repo_two_leaks_commit_from.json:aws-access-token:55
+a0f72a4e3595ddb382a77804d2674d54b2b0e880:test_data/test_local_repo_two_leaks_commit_from.json:aws-access-token:56
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_repo_two_leaks.json:aws-access-token:68
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_repo_two_leaks.json:aws-access-token:69
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_owner_aws_leak.json:aws-access-token:81
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_owner_aws_leak.json:aws-access-token:82
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_owner_aws_leak.json:aws-access-token:107
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_owner_aws_leak.json:aws-access-token:108
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_repo_two_leaks.json:aws-access-token:94
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_repo_two_leaks.json:aws-access-token:95
+6e1c41b536a514e1d17768eb42ebf5d87e61247d:examples/simple_regex_and_whitelist_config.toml:aws-access-token:4
+6e1c41b536a514e1d17768eb42ebf5d87e61247d:examples/simple_regex_and_whitelist_config.toml:aws-access-token:12
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_owner_aws_leak.json:aws-access-token:211
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_owner_aws_leak.json:aws-access-token:212
+275232f8c8f3ae4936667602a06a46caa156580b:audit/util.go:aws-access-token:90
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_owner_aws_leak.json:aws-access-token:237
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_owner_aws_leak.json:aws-access-token:238
+275232f8c8f3ae4936667602a06a46caa156580b:test_data/test_configs/aws_key_aws_whitelisted.toml:aws-access-token:6
+275232f8c8f3ae4936667602a06a46caa156580b:test_data/test_regex_whitelist.json.got:aws-access-token:3
+275232f8c8f3ae4936667602a06a46caa156580b:test_data/test_regex_whitelist.json.got:aws-access-token:4
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_owner_aws_leak.json:aws-access-token:315
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_owner_aws_leak.json:aws-access-token:316
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_owner_aws_leak.json:aws-access-token:341
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_owner_aws_leak.json:aws-access-token:342
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_owner_aws_leak.json:aws-access-token:445
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_owner_aws_leak.json:aws-access-token:446
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_owner_aws_leak.json:aws-access-token:471
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_owner_aws_leak.json:aws-access-token:472
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_owner_aws_leak.json:aws-access-token:549
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_owner_aws_leak.json:aws-access-token:550
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_owner_aws_leak.json:aws-access-token:575
+4d04ea079fc4e7f46c9f751fccde8f18c33b9e13:test_data/test_local_owner_aws_leak.json:aws-access-token:576
+e446ba073804cf714316c5dc00d0ac41917b31f7:test_data/test_regex_entropy.json:aws-access-token:3
+e446ba073804cf714316c5dc00d0ac41917b31f7:test_data/test_regex_entropy.json:aws-access-token:4
+2ccd40677db07877be4a5919a16f6a180fc2a7e4:test_data/test_local_owner_aws_leak.json:aws-access-token:241
+2ccd40677db07877be4a5919a16f6a180fc2a7e4:test_data/test_local_owner_aws_leak.json:aws-access-token:242
+2ccd40677db07877be4a5919a16f6a180fc2a7e4:test_data/test_local_owner_aws_leak.json:aws-access-token:255
+2ccd40677db07877be4a5919a16f6a180fc2a7e4:test_data/test_local_owner_aws_leak.json:aws-access-token:256
+2ccd40677db07877be4a5919a16f6a180fc2a7e4:test_data/test_local_owner_aws_leak.json:aws-access-token:269
+2ccd40677db07877be4a5919a16f6a180fc2a7e4:test_data/test_local_owner_aws_leak.json:aws-access-token:270
+2ccd40677db07877be4a5919a16f6a180fc2a7e4:test_data/test_local_owner_aws_leak.json:aws-access-token:283
+2ccd40677db07877be4a5919a16f6a180fc2a7e4:test_data/test_local_owner_aws_leak.json:aws-access-token:284
+2ccd40677db07877be4a5919a16f6a180fc2a7e4:test_data/test_local_owner_aws_leak.json:aws-access-token:297
+2ccd40677db07877be4a5919a16f6a180fc2a7e4:test_data/test_local_owner_aws_leak.json:aws-access-token:298
+2ccd40677db07877be4a5919a16f6a180fc2a7e4:test_data/test_local_owner_aws_leak.json:aws-access-token:311
+2ccd40677db07877be4a5919a16f6a180fc2a7e4:test_data/test_local_owner_aws_leak.json:aws-access-token:312
+2ccd40677db07877be4a5919a16f6a180fc2a7e4:test_data/test_local_owner_aws_leak.json:aws-access-token:325
+2ccd40677db07877be4a5919a16f6a180fc2a7e4:test_data/test_local_owner_aws_leak.json:aws-access-token:326
+2ccd40677db07877be4a5919a16f6a180fc2a7e4:test_data/test_local_owner_aws_leak.json:aws-access-token:339
+2ccd40677db07877be4a5919a16f6a180fc2a7e4:test_data/test_local_owner_aws_leak.json:aws-access-token:340
+2ccd40677db07877be4a5919a16f6a180fc2a7e4:test_data/test_local_owner_aws_leak.json:aws-access-token:353
+2ccd40677db07877be4a5919a16f6a180fc2a7e4:test_data/test_local_owner_aws_leak.json:aws-access-token:354
+2ccd40677db07877be4a5919a16f6a180fc2a7e4:test_data/test_local_owner_aws_leak.json:aws-access-token:367
+2ccd40677db07877be4a5919a16f6a180fc2a7e4:test_data/test_local_owner_aws_leak.json:aws-access-token:368
+b55d88dc151f7022901cda41a03d43e0e508f2b7:audit/audit_test.go:aws-access-token:207
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_entropy.json:aws-access-token:3
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_one_aws_leak.json:aws-access-token:3
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_one_aws_leak.json:aws-access-token:4
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_one_aws_leak_and_file_leak.json:aws-access-token:17
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_one_aws_leak_and_file_leak.json:aws-access-token:18
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_one_aws_leak_commit.json:aws-access-token:3
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_one_aws_leak_commit.json:aws-access-token:4
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_one_aws_leak_uncommitted.json:aws-access-token:3
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_one_aws_leak_uncommitted.json:aws-access-token:4
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_three_leaks.json:aws-access-token:3
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_three_leaks.json:aws-access-token:4
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_three_leaks.json:aws-access-token:17
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_three_leaks.json:aws-access-token:18
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_three_leaks.json:aws-access-token:31
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_three_leaks.json:aws-access-token:32
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_three_leaks.json:aws-access-token:45
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_three_leaks.json:aws-access-token:46
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_three_leaks.json:aws-access-token:59
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_three_leaks.json:aws-access-token:60
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_three_leaks.json:aws-access-token:73
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_three_leaks.json:aws-access-token:74
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_three_leaks.json:aws-access-token:87
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_three_leaks.json:aws-access-token:88
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_three_leaks.json:aws-access-token:101
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_three_leaks.json:aws-access-token:102
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_repos/test_repo_1/server.test.py:aws-access-token:5
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_two_leaks.json:aws-access-token:3
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_two_leaks.json:aws-access-token:4
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_two_leaks.json:aws-access-token:17
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_two_leaks.json:aws-access-token:18
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_two_leaks.json:aws-access-token:31
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_two_leaks.json:aws-access-token:32
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_two_leaks.json:aws-access-token:45
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_two_leaks.json:aws-access-token:46
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_two_leaks.json:aws-access-token:59
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_two_leaks.json:aws-access-token:60
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_two_leaks.json:aws-access-token:73
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_repo_two_leaks.json:aws-access-token:74
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:3
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:4
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:17
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:18
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:31
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:32
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:45
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:46
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:59
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:60
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:73
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:74
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:87
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:88
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:101
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:102
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:115
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:116
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:129
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:130
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:143
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:144
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:157
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:158
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:171
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:172
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:185
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:186
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:199
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:200
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:213
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:214
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:227
+b55d88dc151f7022901cda41a03d43e0e508f2b7:test_data/test_local_owner_aws_leak.json:aws-access-token:228
+7bd55e33b504f76fc2aec27f4f479a5fb2606480:src/constants.go:private-key:32
+e79ffc6ae8f66931d687407e07bc0632fb262091:src/constants.go:private-key:23
+2b995fda446e03b7660c327fec41265f03199c71:config.go:private-key:28
+1f80d14f3f069118a2e578d83bbc8440495fc906:main.go:private-key:118
+fe977ea8577b739c34a0071ba34e98cf6b6fad38:checks_test.go:aws-access-token:52
+4b4fa00b69a9a2e5f7619b1ff1dd6d160f588aec:README.md:aws-access-token:25
+4b4fa00b69a9a2e5f7619b1ff1dd6d160f588aec:README.md:aws-access-token:27
+2186f2299990290e4e19cf3b28906e2ec369d01e:main.go:private-key:44
+9f694531b203663588c68c82dbbfb34d4f71863f:main.go:private-key:44
+1e250f1a14eab6f457d61f5d7650b47c6ff43334:checks_test.go:aws-access-token:19
+1e250f1a14eab6f457d61f5d7650b47c6ff43334:config.yml:private-key:2
+bc26e979c5911cf647c1bede0b3700ebaaa454c8:checks_test.go:aws-access-token:36
+8f352bd840f028b481dc725b77d2f4904b77913b:checks_test.go:aws-access-token:34
+ec2fc9d6cb0954fb3b57201cf6133c48d8ca0d29:checks_test.go:aws-access-token:37
+06c9e824d5985c8e8789321ae70de7ace3b093dc:main.go:aws-access-token:15
+6d801ed61cf4d75d176cbf9062ec6ad706c9d1eb:detect/detect_test.go:private-key:567
+6d801ed61cf4d75d176cbf9062ec6ad706c9d1eb:testdata/repos/symlinks/source_file/id_ed25519:private-key:1
+acce01f2338434a78f6a4a06a097b0fd23280484:README.md:aws-access-token:218
+README.md:aws-access-token:204
+README.md:aws-access-token:205
+README.md:aws-access-token:244
+cmd/generate/config/rules/privatekey.go:private-key:19
+cmd/generate/config/rules/generic.go:clojars-api-token:43
+cmd/generate/config/rules/generic.go:generic-api-key:45
+cmd/generate/config/rules/generic.go:generic-api-key:46
+cmd/generate/config/rules/sidekiq.go:sidekiq-secret:22
+cmd/generate/config/rules/sidekiq.go:sidekiq-secret:23
+cmd/generate/config/rules/sidekiq.go:sidekiq-secret:24
+cmd/generate/config/rules/sidekiq.go:sidekiq-secret:28
+cmd/generate/config/rules/sidekiq.go:sidekiq-secret:29
+cmd/generate/config/rules/sidekiq.go:sidekiq-sensitive-url:46
+cmd/generate/config/rules/sidekiq.go:sidekiq-sensitive-url:48
+cmd/generate/config/rules/sidekiq.go:sidekiq-sensitive-url:50
+cmd/generate/config/rules/sidekiq.go:sidekiq-sensitive-url:52
+cmd/generate/config/rules/sidekiq.go:sidekiq-sensitive-url:54
+cmd/generate/config/rules/sidekiq.go:sidekiq-sensitive-url:55
+cmd/generate/config/rules/sidekiq.go:sidekiq-sensitive-url:56
+cmd/generate/config/rules/sidekiq.go:sidekiq-sensitive-url:57
+config/config_test.go:aws-access-token:31
+detect/detect_test.go:sidekiq-secret:120
+detect/detect_test.go:sidekiq-secret:126
+detect/detect_test.go:sidekiq-secret:142
+detect/detect_test.go:aws-access-token:50
+detect/detect_test.go:aws-access-token:60
+detect/detect_test.go:aws-access-token:61
+detect/detect_test.go:aws-access-token:98
+detect/detect_test.go:aws-access-token:104
+detect/detect_test.go:aws-access-token:105
+detect/detect_test.go:aws-access-token:186
+detect/detect_test.go:aws-access-token:194
+detect/detect_test.go:aws-access-token:202
+detect/detect_test.go:aws-access-token:288
+detect/detect_test.go:aws-access-token:296
+detect/detect_test.go:aws-access-token:359
+detect/detect_test.go:aws-access-token:360
+detect/detect_test.go:aws-access-token:378
+detect/detect_test.go:aws-access-token:379
+detect/detect_test.go:aws-access-token:404
+detect/detect_test.go:aws-access-token:405
+detect/detect_test.go:aws-access-token:480
+detect/detect_test.go:aws-access-token:481
+detect/detect_test.go:aws-access-token:499
+detect/detect_test.go:aws-access-token:500
+detect/detect_test.go:sidekiq-sensitive-url:164
+detect/detect_test.go:sidekiq-sensitive-url:170
+detect/detect_test.go:pypi-upload-token:76
+detect/detect_test.go:pypi-upload-token:82
+detect/detect_test.go:pypi-upload-token:83
+detect/detect_test.go:discord-api-token:211
+detect/detect_test.go:discord-api-token:233
+detect/detect_test.go:discord-api-token:241
+detect/detect_test.go:discord-api-token:263
+detect/detect_test.go:discord-api-token:279
+testdata/config/allow_aws_re.toml:aws-access-token:9
+testdata/config/allow_global_aws_re.toml:aws-access-token:8
+testdata/expected/git/small-branch-foo.txt:aws-access-token:15
+testdata/expected/git/small.txt:aws-access-token:15
+testdata/expected/git/small.txt:aws-access-token:44
+testdata/repos/nogit/main.go:aws-access-token:20
+testdata/repos/nogit/api.go:aws-access-token:20
+testdata/repos/small/api/ignoreCommit.go:aws-access-token:20
+testdata/repos/small/api/ignoreGlobal.go:aws-access-token:20
+3df8c3deb7bc1e34210bdbce114f1c6165bc6ac8:detect/detect_test.go:aws-access-token:513
+3df8c3deb7bc1e34210bdbce114f1c6165bc6ac8:detect/detect_test.go:aws-access-token:492
+3df8c3deb7bc1e34210bdbce114f1c6165bc6ac8:detect/detect_test.go:aws-access-token:414
+3df8c3deb7bc1e34210bdbce114f1c6165bc6ac8:detect/detect_test.go:aws-access-token:388
+3df8c3deb7bc1e34210bdbce114f1c6165bc6ac8:detect/detect_test.go:aws-access-token:366
+3df8c3deb7bc1e34210bdbce114f1c6165bc6ac8:detect/detect_test.go:discord-api-token:255
+3df8c3deb7bc1e34210bdbce114f1c6165bc6ac8:detect/detect_test.go:discord-api-token:224
+3df8c3deb7bc1e34210bdbce114f1c6165bc6ac8:detect/detect_test.go:sidekiq-sensitive-url:177
+3df8c3deb7bc1e34210bdbce114f1c6165bc6ac8:detect/detect_test.go:sidekiq-secret:154
+3df8c3deb7bc1e34210bdbce114f1c6165bc6ac8:detect/detect_test.go:sidekiq-secret:130
+3df8c3deb7bc1e34210bdbce114f1c6165bc6ac8:detect/detect_test.go:aws-access-token:107
+3df8c3deb7bc1e34210bdbce114f1c6165bc6ac8:detect/detect_test.go:pypi-upload-token:84
+3df8c3deb7bc1e34210bdbce114f1c6165bc6ac8:detect/detect_test.go:aws-access-token:62
+96eed6aa0f507fe0c21bb46bec32637dc4cb1a9f:detect/detect_test.go:aws-access-token:62
+96eed6aa0f507fe0c21bb46bec32637dc4cb1a9f:detect/detect_test.go:pypi-upload-token:84
+96eed6aa0f507fe0c21bb46bec32637dc4cb1a9f:detect/detect_test.go:aws-access-token:107
+96eed6aa0f507fe0c21bb46bec32637dc4cb1a9f:detect/detect_test.go:sidekiq-secret:130
+96eed6aa0f507fe0c21bb46bec32637dc4cb1a9f:detect/detect_test.go:sidekiq-secret:154
+96eed6aa0f507fe0c21bb46bec32637dc4cb1a9f:detect/detect_test.go:sidekiq-sensitive-url:177
+96eed6aa0f507fe0c21bb46bec32637dc4cb1a9f:detect/detect_test.go:discord-api-token:224
+96eed6aa0f507fe0c21bb46bec32637dc4cb1a9f:detect/detect_test.go:discord-api-token:255
+96eed6aa0f507fe0c21bb46bec32637dc4cb1a9f:detect/detect_test.go:aws-access-token:366
+96eed6aa0f507fe0c21bb46bec32637dc4cb1a9f:detect/detect_test.go:aws-access-token:388
+96eed6aa0f507fe0c21bb46bec32637dc4cb1a9f:detect/detect_test.go:aws-access-token:414
+96eed6aa0f507fe0c21bb46bec32637dc4cb1a9f:detect/detect_test.go:aws-access-token:492
+96eed6aa0f507fe0c21bb46bec32637dc4cb1a9f:detect/detect_test.go:aws-access-token:513
+bfbc39eb185a217ead81a7174026f1c55f963660:cmd/generate/config/rules/jwt.go:jwt:17
+bfbc39eb185a217ead81a7174026f1c55f963660:cmd/generate/config/rules/jwt.go:jwt:19
+acce01f2338434a78f6a4a06a097b0fd23280484:README.md:aws-access-token:220
+99d620c719020fa24baa831299f0c964da79875e:detect/detect_test.go:aws-access-token:514
+111c8b47b65627db117bd20be85ff0aee8961eb9:detect/detect_test.go:private-key:567
+99d620c719020fa24baa831299f0c964da79875e:detect/detect_test.go:aws-access-token:512
+99d620c719020fa24baa831299f0c964da79875e:detect/detect_test.go:aws-access-token:513
+69f161c0a0cc0f7858f7d0609d656f4edcedd84c:detect/detect_test.go:discord-api-token:326
+9701bf1724d822c0d5bbb7627535dd639a37bf56:testdata/repos/staged/api/api.go:aws-access-token:7
+9701bf1724d822c0d5bbb7627535dd639a37bf56:detect/detect_test.go:aws-access-token:505
+9701bf1724d822c0d5bbb7627535dd639a37bf56:detect/detect_test.go:aws-access-token:506
+9701bf1724d822c0d5bbb7627535dd639a37bf56:detect/detect_test.go:aws-access-token:507
+9701bf1724d822c0d5bbb7627535dd639a37bf56:testdata/repos/staged/api/api.go:aws-access-token:6
+9701bf1724d822c0d5bbb7627535dd639a37bf56:testdata/repos/staged/api/api.go:aws-access-token:7
+91ff8f9b7020a16dac9b8b9ef98560ea1cb464f8:testdata/repos/small/api/ignoreCommit.go:aws-access-token:20
+91ff8f9b7020a16dac9b8b9ef98560ea1cb464f8:testdata/repos/small/api/ignoreGlobal.go:aws-access-token:20
+91ff8f9b7020a16dac9b8b9ef98560ea1cb464f8:testdata/repos/nogit/api.go:aws-access-token:20
+adf617b3b4628e1160fa3d135b4c3dfd45c05e15:testdata/repos/nogit/api.go:aws-access-token:20
+adf617b3b4628e1160fa3d135b4c3dfd45c05e15:testdata/repos/small/api/ignoreGlobal.go:aws-access-token:20
+adf617b3b4628e1160fa3d135b4c3dfd45c05e15:testdata/repos/small/api/ignoreCommit.go:aws-access-token:20
+f361c5ef71853923277e3f284890083bc7825205:detect/reader_test.go:aws-access-token:12
+
+8cfa6b2e43544895f52d2e37535ccfe29a6cdfd3:cmd/generate/config/rules/infracost.go:infracost-api-token:24
+8cfa6b2e43544895f52d2e37535ccfe29a6cdfd3:cmd/generate/config/rules/infracost.go:generic-api-key:29
+8cfa6b2e43544895f52d2e37535ccfe29a6cdfd3:cmd/generate/config/rules/discord.go:discord-client-secret:64
+8cfa6b2e43544895f52d2e37535ccfe29a6cdfd3:cmd/generate/config/rules/grafana.go:grafana-cloud-api-token:42
+8cfa6b2e43544895f52d2e37535ccfe29a6cdfd3:cmd/generate/config/rules/grafana.go:grafana-service-account-token:80
+9152eaa57a91d7249bd0b3c3a86b9e837072a828:detect/reader_test.go:aws-access-token:12
+9152eaa57a91d7249bd0b3c3a86b9e837072a828:cmd/generate/config/rules/aws.go:aws-access-token:42
+93acc6e82adb46ef442fcb44bd9fd83489690ca3:cmd/generate/config/rules/1password.go:1password-service-account-token:25
+93acc6e82adb46ef442fcb44bd9fd83489690ca3:cmd/generate/config/rules/1password.go:1password-service-account-token:27
+93acc6e82adb46ef442fcb44bd9fd83489690ca3:cmd/generate/config/rules/1password.go:1password-service-account-token:28
+93acc6e82adb46ef442fcb44bd9fd83489690ca3:cmd/generate/config/rules/1password.go:generic-api-key:37
+83a57244cdd0bfe1634326ab04a29b9b139bf158:cmd/generate/config/rules/curl.go:openai-api-key:125
+83a57244cdd0bfe1634326ab04a29b9b139bf158:cmd/generate/config/rules/curl.go:curl-auth-header:100
+83a57244cdd0bfe1634326ab04a29b9b139bf158:cmd/generate/config/rules/curl.go:curl-auth-header:102
+83a57244cdd0bfe1634326ab04a29b9b139bf158:cmd/generate/config/rules/curl.go:curl-auth-header:108
+83a57244cdd0bfe1634326ab04a29b9b139bf158:cmd/generate/config/rules/curl.go:curl-auth-header:112
+83a57244cdd0bfe1634326ab04a29b9b139bf158:cmd/generate/config/rules/curl.go:curl-auth-header:121
+83a57244cdd0bfe1634326ab04a29b9b139bf158:cmd/generate/config/rules/curl.go:curl-auth-header:122
+83a57244cdd0bfe1634326ab04a29b9b139bf158:cmd/generate/config/rules/curl.go:curl-auth-header:123
+83a57244cdd0bfe1634326ab04a29b9b139bf158:cmd/generate/config/rules/curl.go:curl-auth-header:126
+83a57244cdd0bfe1634326ab04a29b9b139bf158:cmd/generate/config/rules/curl.go:curl-auth-header:131
+83a57244cdd0bfe1634326ab04a29b9b139bf158:cmd/generate/config/rules/curl.go:curl-auth-header:134
+83a57244cdd0bfe1634326ab04a29b9b139bf158:cmd/generate/config/rules/curl.go:curl-auth-header:137
+83a57244cdd0bfe1634326ab04a29b9b139bf158:cmd/generate/config/rules/curl.go:curl-auth-header:137
+83a57244cdd0bfe1634326ab04a29b9b139bf158:cmd/generate/config/rules/curl.go:generic-api-key:139
+83a57244cdd0bfe1634326ab04a29b9b139bf158:cmd/generate/config/rules/curl.go:jwt:134
+83a57244cdd0bfe1634326ab04a29b9b139bf158:cmd/generate/config/rules/curl.go:jwt:170
+cf5334fd61d16fb4af1362856ebfb98397c5d4b3:cmd/generate/config/rules/curl.go:curl-auth-user:32
+cf5334fd61d16fb4af1362856ebfb98397c5d4b3:cmd/generate/config/rules/curl.go:curl-auth-user:33
+cf5334fd61d16fb4af1362856ebfb98397c5d4b3:cmd/generate/config/rules/curl.go:curl-auth-user:40
+cf5334fd61d16fb4af1362856ebfb98397c5d4b3:cmd/generate/config/rules/curl.go:curl-auth-user:42
+cf5334fd61d16fb4af1362856ebfb98397c5d4b3:cmd/generate/config/rules/curl.go:curl-auth-user:43
+cf5334fd61d16fb4af1362856ebfb98397c5d4b3:cmd/generate/config/rules/curl.go:curl-auth-user:44
+cf5334fd61d16fb4af1362856ebfb98397c5d4b3:cmd/generate/config/rules/curl.go:curl-auth-user:45
+aabe3815394d24d5b8198ba6068a99e0ba7601b1:config/config_test.go:aws-access-token:72
+b9f7fdaacb9e3799a9b3e4f7f6181963b8931b73:config/config_test.go:aws-access-token:67
+3ef444d24677c863bb724fa406dd12464b7f2362:config/config_test.go:aws-access-token:39
+8fb39ba8dc9d872d57cc3151b3750e8234b9b980:cmd/generate/config/rules/azure.go:azure-ad-client-secret:33
+2278a2a97e422c8075207d17195b29e7f4ff15e1:detect/decoder_test.go:generic-api-key:22
+2278a2a97e422c8075207d17195b29e7f4ff15e1:detect/decoder_test.go:generic-api-key:32
+2278a2a97e422c8075207d17195b29e7f4ff15e1:detect/decoder_test.go:generic-api-key:37
+2278a2a97e422c8075207d17195b29e7f4ff15e1:detect/decoder_test.go:generic-api-key:54
+2278a2a97e422c8075207d17195b29e7f4ff15e1:detect/decoder_test.go:generic-api-key:59
+2278a2a97e422c8075207d17195b29e7f4ff15e1:detect/decoder_test.go:generic-api-key:64
+2278a2a97e422c8075207d17195b29e7f4ff15e1:detect/detect_test.go:private-key:23
+2278a2a97e422c8075207d17195b29e7f4ff15e1:detect/detect_test.go:generic-api-key:39
+2278a2a97e422c8075207d17195b29e7f4ff15e1:detect/detect_test.go:jwt:32
+2278a2a97e422c8075207d17195b29e7f4ff15e1:detect/detect_test.go:private-key:365
+2278a2a97e422c8075207d17195b29e7f4ff15e1:detect/detect_test.go:private-key:366
+2278a2a97e422c8075207d17195b29e7f4ff15e1:detect/detect_test.go:private-key:368
+2278a2a97e422c8075207d17195b29e7f4ff15e1:detect/detect_test.go:private-key:393
+2278a2a97e422c8075207d17195b29e7f4ff15e1:detect/detect_test.go:private-key:394
+2278a2a97e422c8075207d17195b29e7f4ff15e1:detect/detect_test.go:aws-access-token:407
+2278a2a97e422c8075207d17195b29e7f4ff15e1:detect/detect_test.go:aws-access-token:408
+2278a2a97e422c8075207d17195b29e7f4ff15e1:detect/detect_test.go:generic-api-key:452
+f8dcd838da26f591c70acbbc3dea8d8b4d1649c7:detect/detect_test.go:generic-api-key:616
+f8dcd838da26f591c70acbbc3dea8d8b4d1649c7:detect/detect_test.go:generic-api-key:618
+f8dcd838da26f591c70acbbc3dea8d8b4d1649c7:testdata/repos/nogit/.env.prod:generic-api-key:4
+032c47e7e1ebfb745d3b66ef448697d4cbf6a406:detect/detect_test.go:generic-api-key:38
+032c47e7e1ebfb745d3b66ef448697d4cbf6a406:detect/detect_test.go:generic-api-key:451
+6c5e01c144b3d5e48422ab66a353f4cbdc14b24a:detect/detect_test.go:private-key:22
+6c5e01c144b3d5e48422ab66a353f4cbdc14b24a:detect/detect_test.go:jwt:31
+6c5e01c144b3d5e48422ab66a353f4cbdc14b24a:detect/decoder_test.go:generic-api-key:22
+6c5e01c144b3d5e48422ab66a353f4cbdc14b24a:detect/decoder_test.go:generic-api-key:32
+6c5e01c144b3d5e48422ab66a353f4cbdc14b24a:detect/decoder_test.go:generic-api-key:37
+6c5e01c144b3d5e48422ab66a353f4cbdc14b24a:detect/decoder_test.go:generic-api-key:54
+6c5e01c144b3d5e48422ab66a353f4cbdc14b24a:detect/decoder_test.go:generic-api-key:59
+6c5e01c144b3d5e48422ab66a353f4cbdc14b24a:detect/decoder_test.go:generic-api-key:64
+6c5e01c144b3d5e48422ab66a353f4cbdc14b24a:detect/detect_test.go:private-key:359
+6c5e01c144b3d5e48422ab66a353f4cbdc14b24a:detect/detect_test.go:private-key:360
+6c5e01c144b3d5e48422ab66a353f4cbdc14b24a:detect/detect_test.go:private-key:362
+6c5e01c144b3d5e48422ab66a353f4cbdc14b24a:detect/detect_test.go:private-key:387
+6c5e01c144b3d5e48422ab66a353f4cbdc14b24a:detect/detect_test.go:private-key:388
+6c5e01c144b3d5e48422ab66a353f4cbdc14b24a:detect/detect_test.go:aws-access-token:401
+6c5e01c144b3d5e48422ab66a353f4cbdc14b24a:detect/detect_test.go:aws-access-token:402
+78f7d3f5dfba03f816418f987ff3a78643c1eda7:cmd/generate/config/rules/flyio.go:flyio-access-token:26
+78f7d3f5dfba03f816418f987ff3a78643c1eda7:cmd/generate/config/rules/flyio.go:flyio-access-token:30
+78f7d3f5dfba03f816418f987ff3a78643c1eda7:cmd/generate/config/rules/flyio.go:flyio-access-token:34
+78f7d3f5dfba03f816418f987ff3a78643c1eda7:cmd/generate/config/rules/flyio.go:flyio-access-token:37
+78f7d3f5dfba03f816418f987ff3a78643c1eda7:cmd/generate/config/rules/flyio.go:flyio-access-token:38
+3698060a2bcf926b8ae459270d9bcb7b69339104:cmd/generate/config/rules/kubernetes.go:generic-api-key:56
+3698060a2bcf926b8ae459270d9bcb7b69339104:cmd/generate/config/rules/kubernetes.go:generic-api-key:68
+3698060a2bcf926b8ae459270d9bcb7b69339104:cmd/generate/config/rules/kubernetes.go:generic-api-key:79
+3698060a2bcf926b8ae459270d9bcb7b69339104:cmd/generate/config/rules/kubernetes.go:generic-api-key:147
+3698060a2bcf926b8ae459270d9bcb7b69339104:cmd/generate/config/rules/kubernetes.go:generic-api-key:153
+3698060a2bcf926b8ae459270d9bcb7b69339104:cmd/generate/config/rules/kubernetes.go:generic-api-key:162
+5740eddd75b2a1149374438afe80c7cf2535b35f:README.md:aws-access-token:221
+5740eddd75b2a1149374438afe80c7cf2535b35f:README.md:aws-access-token:223
+5740eddd75b2a1149374438afe80c7cf2535b35f:README.md:aws-access-token:259
+5740eddd75b2a1149374438afe80c7cf2535b35f:cmd/generate/config/rules/generic.go:clojars-api-token:42
+372d99cfdb92a1e177badbfc1cd65bd692df9025:cmd/generate/config/rules/hashicorp.go:hashicorp-tf-api-token:24
+372d99cfdb92a1e177badbfc1cd65bd692df9025:cmd/generate/config/rules/vault.go:vault-service-token:22
+372d99cfdb92a1e177badbfc1cd65bd692df9025:cmd/generate/config/rules/vault.go:vault-service-token:25
+3be7faa1ffc80f1aa071192a09141d5e829e1af3:cmd/generate/config/rules/vault.go:vault-service-token:22
+3be7faa1ffc80f1aa071192a09141d5e829e1af3:cmd/generate/config/rules/hashicorp.go:hashicorp-tf-api-token:24
+3be7faa1ffc80f1aa071192a09141d5e829e1af3:cmd/generate/config/rules/vault.go:vault-service-token:25
+840c3cb24dcf14bf3332793f0702e75085ff5de2:detect/verify_test.go:generic-api-key:39
+840c3cb24dcf14bf3332793f0702e75085ff5de2:detect/verify_test.go:generic-api-key:47
+840c3cb24dcf14bf3332793f0702e75085ff5de2:detect/verify_test.go:generic-api-key:88
+c1345e1b2b63260d860637530ba4d17571d547d6:cmd/generate/config/rules/openshift.go:openshift-user-token:27
+c1345e1b2b63260d860637530ba4d17571d547d6:cmd/generate/config/rules/openshift.go:openshift-user-token:28
+821b2323940b1792d9001d0812a2a4f7480a69c0:cmd/generate/config/rules/cloudflare.go:cloudflare-origin-ca-key:20
+821b2323940b1792d9001d0812a2a4f7480a69c0:cmd/generate/config/rules/cloudflare.go:cloudflare-origin-ca-key:21
+e265bfbbc3b208a23f0e46dd4a96795817068b77:detect/validate_test.go:generic-api-key:93
+9d06c40017ba6710032e9bc08ebbc056175629cf:detect/validate_test.go:github-pat:33
+9d06c40017ba6710032e9bc08ebbc056175629cf:detect/validate_test.go:github-pat:36
+9d06c40017ba6710032e9bc08ebbc056175629cf:detect/validate_test.go:generic-api-key:43
+9d06c40017ba6710032e9bc08ebbc056175629cf:detect/validate_test.go:generic-api-key:49
+9d06c40017ba6710032e9bc08ebbc056175629cf:detect/validate_test.go:generic-api-key:57
+e9135cf0b598738b5fc63ca004db8ab30845393d:cmd/generate/config/rules/jwt.go:jwt:48
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-organization-api-token:85
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-organization-api-token:86
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-organization-api-token:87
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-organization-api-token:88
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-organization-api-token:89
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-organization-api-token:90
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-organization-api-token:91
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-organization-api-token:93
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-organization-api-token:95
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-organization-api-token:96
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-organization-api-token:97
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-access-token:30
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-access-token:31
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-access-token:32
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-access-token:33
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-access-token:34
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-access-token:35
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-access-token:36
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-access-token:37
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-access-token:38
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-access-token:39
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-access-token:40
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-access-token:41
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-access-token:42
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-access-token:43
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-access-token:45
+9fb36b242d75aac1a2bf885724dfd9886db08ea7:cmd/generate/config/rules/huggingface.go:huggingface-access-token:46
+463d24618fa42fc7629dc30c9744ebe36c5df1ab:cmd/generate/config/rules/slack.go:slack-user-token:66
+463d24618fa42fc7629dc30c9744ebe36c5df1ab:cmd/generate/config/rules/slack.go:slack-config-access-token:115
+463d24618fa42fc7629dc30c9744ebe36c5df1ab:cmd/generate/config/rules/slack.go:slack-legacy-workspace-token:210
+025908808f2ad1ce244f9806b8dd593bd9afbab0:detect/detect_test.go:discord-api-token:326
+e002920355ac91770a329cfa69d6359bd665ba66:cmd/generate/config/rules/privatekey.go:private-key:26
+e890a8e8098ee8021d25a429315a6c153126db22:cmd/generate/config/rules/jwt.go:jwt:17
+9326f35380636bcbe61e94b0584d1618c4b5c2c2:detect/detect_test.go:pypi-upload-token:27
+9326f35380636bcbe61e94b0584d1618c4b5c2c2:detect/detect_test.go:pypi-upload-token:32
+9326f35380636bcbe61e94b0584d1618c4b5c2c2:detect/detect_test.go:pypi-upload-token:33
+3a3e13c3b5f85b0116cf2a0cd92529baf22d0ac9:testdata/repos/with_square_and_google/env:gcp-api-key:3
+45c898c5ea56ee503a048c1bac1404cf63855edc:test_data/test_repos/test_dir_2/env:gcp-api-key:3
+45c898c5ea56ee503a048c1bac1404cf63855edc:test_data/test_dir_one_google_leak_and_square_leak.json:gcp-api-key:20
+45c898c5ea56ee503a048c1bac1404cf63855edc:test_data/test_dir_one_google_leak_and_square_leak.json:gcp-api-key:22
+f6460a7365479a48581e0641b40147914542bb24:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:16
+f6460a7365479a48581e0641b40147914542bb24:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:17
+f6460a7365479a48581e0641b40147914542bb24:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:42
+f6460a7365479a48581e0641b40147914542bb24:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:43
+f6460a7365479a48581e0641b40147914542bb24:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:68
+f6460a7365479a48581e0641b40147914542bb24:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:69
+f6460a7365479a48581e0641b40147914542bb24:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:94
+f6460a7365479a48581e0641b40147914542bb24:test_data/test_local_owner_aws_leak_depth_2.json:aws-access-token:95
+7bd55e33b504f76fc2aec27f4f479a5fb2606480:src/constants.go:private-key:42
+e79ffc6ae8f66931d687407e07bc0632fb262091:src/constants.go:private-key:29
+2b995fda446e03b7660c327fec41265f03199c71:config.go:private-key:34
+ccef3680d5552443c999345567ea60909c863c0a:checks_test.go:aws-access-token:52
+1cecd5e0908ab581f217ebb2cb58829204530c79:README.md:aws-access-token:25
+1cecd5e0908ab581f217ebb2cb58829204530c79:README.md:aws-access-token:27
+e56870aecf8ac2733affc82e1ac25e3be9092db3:cmd/generate/config/rules/curl.go:generic-api-key:116
+239e6323639b18ba8a1081f17788a658da075dd7:cmd/generate/config/rules/sumologic.go:sumologic-access-token:72
+239e6323639b18ba8a1081f17788a658da075dd7:cmd/generate/config/rules/sumologic.go:sumologic-access-id:40
+239e6323639b18ba8a1081f17788a658da075dd7:cmd/generate/config/rules/readme.go:readme-api-token:26
+239e6323639b18ba8a1081f17788a658da075dd7:cmd/generate/config/rules/prefect.go:prefect-api-token:26
+239e6323639b18ba8a1081f17788a658da075dd7:cmd/generate/config/rules/databricks.go:databricks-api-token:25
+239e6323639b18ba8a1081f17788a658da075dd7:cmd/generate/config/rules/databricks.go:generic-api-key:22
+c24a3a654b18d689732ec3199f0a19a254505b04:detect/detect_test.go:generic-api-key:52
+c08cb1dc9aee87186dba4eebbc13b8aaa2351f0c:detect/detect_test.go:generic-api-key:52
+ee0da5c7fa5f3c9a7f1617e162497199cac3537f:README.md:generic-api-key:480
+782f3104786efdce0f809bce8a9ff31f2fa1c9ed:README.md:generic-api-key:481
diff --git a/.golangci.yaml b/.golangci.yaml
new file mode 100644
index 0000000..1bd2cb4
--- /dev/null
+++ b/.golangci.yaml
@@ -0,0 +1,86 @@
+version: '2'
+linters:
+ default: none
+ # It might be worth going through some of the disabled linters and enabling
+ # them and fixing the items they call out e.g.: cyclop, prealloc,
+ # paralleltest, prealloc, errcheck, dupl, unused, testifylint, gosec,
+ # gocritic, perfsprint, exptostd, intrange, perfsprint (maybe others?)
+ disable:
+ - cyclop
+ - depguard
+ - dupl
+ - err113
+ - errcheck
+ - exhaustive
+ - exhaustruct
+ - exptostd
+ - forbidigo
+ - funcorder
+ - funlen
+ - gochecknoglobals
+ - gochecknoinits
+ - gocognit
+ - goconst
+ - gocritic
+ - gocyclo
+ - godot
+ - godox
+ - gosec
+ - gosmopolitan
+ - intrange
+ - lll
+ - maintidx
+ - mnd
+ - musttag
+ - nestif
+ - nilerr
+ - nlreturn
+ - nonamedreturns
+ - paralleltest
+ - perfsprint
+ - prealloc
+ - predeclared
+ - tagliatelle
+ - testifylint
+ - testpackage
+ - tparallel
+ - unparam
+ - unused
+ - varnamelen
+ - wastedassign
+ - whitespace
+ - wrapcheck
+ - wsl
+ - zerologlint # doesn't seem to catch gitleaks/v8/logging mistakes
+ enable:
+ - inamedparam
+ - misspell
+ - revive
+ - misspell
+ - inamedparam
+ - exhaustruct
+ - inamedparam
+ - misspell
+ - nonamedreturns
+ - staticcheck
+ - unconvert
+ exclusions:
+ rules:
+ - linters:
+ - staticcheck
+ source: 'detector\.Detect\w+\(|sources\.DirectoryTargets\(|detect\.(?:Fragment|RemoteInfo)'
+ - linters:
+ - misspell
+ source: '"(?:addres|busines|clas)",'
+ settings:
+ staticcheck:
+ checks:
+ - all
+ - '-QF1001'
+ - '-ST1000'
+ - '-ST1003'
+ - '-ST1018'
+ - '-ST1020'
+ - '-ST1021'
+ revive:
+ severity: error
diff --git a/.goreleaser.yml b/.goreleaser.yml
new file mode 100644
index 0000000..573d4c9
--- /dev/null
+++ b/.goreleaser.yml
@@ -0,0 +1,31 @@
+project_name: gitleaks
+
+builds:
+ - main: main.go
+ binary: gitleaks
+ goos:
+ - darwin
+ - linux
+ - windows
+ goarch:
+ - amd64
+ - "386"
+ - arm
+ - arm64
+ goarm:
+ - "6"
+ - "7"
+ tags:
+ - gore2regex
+ ldflags:
+ - -s -w -X=github.com/zricethezav/gitleaks/v8/version.Version={{.Version}}
+archives:
+ - builds: [gitleaks]
+ format_overrides:
+ - goos: windows
+ format: zip
+ replacements:
+ amd64: x64
+ 386: x32
+release:
+ prerelease: true
diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml
new file mode 100644
index 0000000..66cbc46
--- /dev/null
+++ b/.pre-commit-hooks.yaml
@@ -0,0 +1,17 @@
+- id: gitleaks
+ name: Detect hardcoded secrets
+ description: Detect hardcoded secrets using Gitleaks
+ entry: gitleaks git --pre-commit --redact --staged --verbose
+ language: golang
+ pass_filenames: false
+- id: gitleaks-docker
+ name: Detect hardcoded secrets
+ description: Detect hardcoded secrets using Gitleaks
+ entry: zricethezav/gitleaks git --pre-commit --redact --staged --verbose
+ language: docker_image
+ pass_filenames: false
+- id: gitleaks-system
+ name: Detect hardcoded secrets
+ description: Detect hardcoded secrets using Gitleaks
+ entry: gitleaks git --pre-commit --redact --staged --verbose
+ language: system
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..0833112
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,102 @@
+# Contribution guidelines
+
+## General
+
+### Issues
+
+If you have a feature or bug fix you would like to contribute please check if
+there are any open issues describing your proposed addition. If there are open
+issues, make a comment stating you are working on fixing or implementing said
+issue. If not, then please open an issue describing your addition. Make sure to
+link your PR to an issue.
+
+### Pull Requests
+
+Fill out the template as best you can. Make sure your tests pass. If you see a
+PR that isn't one you opened and want it introduced in the next release,
+give it a :thumbsup: on the PR description.
+
+## Adding new Gitleaks rules
+
+If you want to add a new rule to the [default Gitleaks configuration](https://github.com/zricethezav/gitleaks/blob/master/config/gitleaks.toml) then follow these steps.
+
+1. Create a `cmd/generate/config/rules/{provider}.go` file.
+ This file is used to generate a new Gitleaks rule.
+ Let's look at `beamer.go` for example. Comments have been added for context.
+
+ ```golang
+ func Beamer() *config.Rule {
+ // Define Rule
+ r := config.Rule{
+ // Human readable description of the rule
+ Description: "Beamer API token",
+
+ // Unique ID for the rule
+ RuleID: "beamer-api-token",
+
+ // Regex capture group for the actual secret
+
+
+
+ // Regex used for detecting secrets. See regex section below for more details
+ Regex: GenerateSemiGenericRegex([]string{"beamer"}, `b_[a-z0-9=_\-]{44}`, true)
+
+ // Keywords used for string matching on fragments (think of this as a prefilter)
+ Keywords: []string{"beamer"},
+ }
+
+ // validate
+ tps := []string{
+ generateSampleSecret("beamer", "b_"+secrets.NewSecret(alphaNumericExtended("44"))),
+ }
+ fps := []string{
+ `R21A-A-V010SP13RC181024R16900-CN-B_250K-Release-OTA-97B6C6C59241976086FABDC41472150C.bfu`,
+ }
+ return validate(r, tps, fps)
+ }
+ ```
+
+ Feel free to use this example as a template when writing new rules.
+ This file should be fairly self-explanatory except for a few items;
+ regex and secret generation. To help with maintence, _most_ rules should
+ be uniform. The functions,
+ [`GenerateSemiGenericRegex`](https://github.com/zricethezav/gitleaks/blob/master/cmd/generate/config/rules/rule.go#L31) and [`GenerateUniqueTokenRegex`](https://github.com/zricethezav/gitleaks/blob/master/cmd/generate/config/rules/rule.go#L44) will generate rules
+ that follow defined patterns.
+
+ The function signatures look like this:
+
+ ```golang
+ func GenerateSemiGenericRegex(identifiers []string, secretRegex string, isCaseInsensitive bool) *regexp.Regexp
+
+ func GenerateUniqueTokenRegex(secretRegex string, isCaseInsensitive bool) *regexp.Regexp
+ ```
+
+ `GenerateSemiGenericRegex` accepts a list of identifiers, a regex, and a boolean indicating whether the pattern should be case-insensitive.
+ The list of identifiers _should_ match the list of `Keywords` in the rule
+ definition above. Both `identifiers` in the `GenerateSemiGenericRegex`
+ function _and_ `Keywords` act as filters for Gitleaks telling the program
+ "_at least one of these strings must be present to be considered a leak_"
+
+ `GenerateUniqueTokenRegex` just accepts a regex and a boolean indicating whether the pattern should be case-insensitive. If you are writing a rule for a
+ token that is unique enough not to require an identifier then you can use
+ this function. For example, Pulumi's API Token has the prefix `pul-` which is
+ unique enough to use `GenerateUniqueTokenRegex`. But something like Beamer's API
+ token that has a `b_` prefix is not unique enough to use `GenerateUniqueTokenRegex`,
+ so instead we use `GenerateSemiGenericRegex` and require a `beamer`
+ identifier is part of the rule.
+ If a token's prefix has more than `3` characters then you could
+ probably get away with using `GenerateUniqueTokenRegex`.
+
+ Last thing you'll want to hit before we move on from this file is the
+ validation part. You can use `generateSampleSecret` to create a secret for the
+ true positives (`tps` in the example above) used in `validate`.
+
+1. Update `cmd/generate/config/main.go`. Extend `configRules` slice with
+ the `rules.Beamer(),` in `main()`. Try and keep
+ this alphabetically pretty please.
+
+1. Run `make config/gitleaks.toml`
+
+1. Check out your new rules in `config/gitleaks.toml` and see if everything looks good.
+
+1. Open a PR
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..9a9f1fa
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,13 @@
+FROM golang:1.24 AS build
+WORKDIR /go/src/github.com/zricethezav/gitleaks
+COPY . .
+RUN VERSION=$(git describe --tags --abbrev=0) && \
+CGO_ENABLED=0 go build -o bin/gitleaks -ldflags "-X=github.com/zricethezav/gitleaks/v8/version.Version=${VERSION}"
+
+FROM alpine:3.22
+RUN apk add --no-cache bash git openssh-client
+COPY --from=build /go/src/github.com/zricethezav/gitleaks/bin/* /usr/bin/
+
+RUN git config --global --add safe.directory '*'
+
+ENTRYPOINT ["gitleaks"]
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..3c270b3
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 Zachary Rice
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..7c7112c
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,37 @@
+.PHONY: test test-cover failfast profile clean format build
+
+PKG=github.com/zricethezav/gitleaks
+VERSION := `git fetch --tags && git tag | sort -V | tail -1`
+LDFLAGS=-ldflags "-X=github.com/zricethezav/gitleaks/v8/version.Version=$(VERSION)"
+COVER=--cover --coverprofile=cover.out
+
+test-cover:
+ go test -v ./... --race $(COVER) $(PKG)
+ go tool cover -html=cover.out
+
+format:
+ go fmt ./...
+
+test: config/gitleaks.toml format
+ go test -v ./... --race $(PKG)
+
+failfast: format
+ go test -failfast ./...
+
+build: config/gitleaks.toml format
+ go mod tidy
+ go build $(LDFLAGS)
+
+lint:
+ golangci-lint run
+
+clean:
+ rm -rf profile
+ find . -type f -name '*.got.*' -delete
+ find . -type f -name '*.out' -delete
+
+profile: build
+ ./scripts/profile.sh './gitleaks' '.'
+
+config/gitleaks.toml: $(wildcard cmd/generate/config/**/*)
+ go generate ./...
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6bdd5d9
--- /dev/null
+++ b/README.md
@@ -0,0 +1,630 @@
+# Gitleaks
+
+```
+┌─○───┐
+│ │╲ │
+│ │ ○ │
+│ ○ ░ │
+└─░───┘
+```
+
+> [!WARNING]
+> Gitleaks is feature complete. I'm not merging new features into Gitleaks. Future releases will be security patches only. I'm shifting my focus to [Betterleaks](https://github.com/betterleaks/betterleaks)
+
+[license]: ./LICENSE
+[badge-license]: https://img.shields.io/github/license/gitleaks/gitleaks.svg
+[go-docs-badge]: https://pkg.go.dev/badge/github.com/gitleaks/gitleaks/v8?status
+[go-docs]: https://pkg.go.dev/github.com/zricethezav/gitleaks/v8
+[badge-build]: https://github.com/gitleaks/gitleaks/actions/workflows/test.yml/badge.svg
+[build]: https://github.com/gitleaks/gitleaks/actions/workflows/test.yml
+[go-report-card-badge]: https://goreportcard.com/badge/github.com/gitleaks/gitleaks/v8
+[go-report-card]: https://goreportcard.com/report/github.com/gitleaks/gitleaks/v8
+[dockerhub]: https://hub.docker.com/r/zricethezav/gitleaks
+[dockerhub-badge]: https://img.shields.io/docker/pulls/zricethezav/gitleaks.svg
+[gitleaks-action]: https://github.com/gitleaks/gitleaks-action
+[gitleaks-badge]: https://img.shields.io/badge/protected%20by-gitleaks-blue
+
+
+[![GitHub Action Test][badge-build]][build]
+[![Docker Hub][dockerhub-badge]][dockerhub]
+[![Gitleaks Action][gitleaks-badge]][gitleaks-action]
+[![GoDoc][go-docs-badge]][go-docs]
+[![GoReportCard][go-report-card-badge]][go-report-card]
+[![License][badge-license]][license]
+
+Gitleaks is a tool for **detecting** secrets like passwords, API keys, and tokens in git repos, files, and whatever else you wanna throw at it via `stdin`. If you wanna learn more about how the detection engine works check out this blog: [Regex is (almost) all you need](https://lookingatcomputer.substack.com/p/regex-is-almost-all-you-need).
+
+```
+➜ ~/code(master) gitleaks git -v
+
+ ○
+ │╲
+ │ ○
+ ○ ░
+ ░ gitleaks
+
+
+Finding: "export BUNDLE_ENTERPRISE__CONTRIBSYS__COM=cafebabe:deadbeef",
+Secret: cafebabe:deadbeef
+RuleID: sidekiq-secret
+Entropy: 2.609850
+File: cmd/generate/config/rules/sidekiq.go
+Line: 23
+Commit: cd5226711335c68be1e720b318b7bc3135a30eb2
+Author: John
+Email: john@users.noreply.github.com
+Date: 2022-08-03T12:31:40Z
+Fingerprint: cd5226711335c68be1e720b318b7bc3135a30eb2:cmd/generate/config/rules/sidekiq.go:sidekiq-secret:23
+```
+
+
+## Getting Started
+
+Gitleaks can be installed using Homebrew, Docker, or Go. Gitleaks is also available in binary form for many popular platforms and OS types on the [releases page](https://github.com/gitleaks/gitleaks/releases). In addition, Gitleaks can be implemented as a pre-commit hook directly in your repo or as a GitHub action using [Gitleaks-Action](https://github.com/gitleaks/gitleaks-action).
+
+### Installing
+
+```bash
+# MacOS
+brew install gitleaks
+
+# Docker (DockerHub)
+docker pull zricethezav/gitleaks:latest
+docker run -v ${path_to_host_folder_to_scan}:/path zricethezav/gitleaks:latest [COMMAND] [OPTIONS] [SOURCE_PATH]
+
+# Docker (ghcr.io)
+docker pull ghcr.io/gitleaks/gitleaks:latest
+docker run -v ${path_to_host_folder_to_scan}:/path ghcr.io/gitleaks/gitleaks:latest [COMMAND] [OPTIONS] [SOURCE_PATH]
+
+# From Source (make sure `go` is installed)
+git clone https://github.com/gitleaks/gitleaks.git
+cd gitleaks
+make build
+```
+
+### Pre-Commit
+
+1. Install pre-commit from https://pre-commit.com/#install
+2. Create a `.pre-commit-config.yaml` file at the root of your repository with the following content:
+
+ ```
+ repos:
+ - repo: https://github.com/gitleaks/gitleaks
+ rev: v8.24.2
+ hooks:
+ - id: gitleaks
+ ```
+
+ for a [native execution of gitleaks](https://github.com/gitleaks/gitleaks/releases) or use the [`gitleaks-docker` pre-commit ID](https://github.com/gitleaks/gitleaks/blob/master/.pre-commit-hooks.yaml) for executing gitleaks using the [official Docker images](#docker)
+
+3. Auto-update the config to the latest repos' versions by executing `pre-commit autoupdate`
+4. Install with `pre-commit install`
+5. Now you're all set!
+
+```
+➜ git commit -m "this commit contains a secret"
+Detect hardcoded secrets.................................................Failed
+```
+
+Note: to disable the gitleaks pre-commit hook you can prepend `SKIP=gitleaks` to the commit command
+and it will skip running gitleaks
+
+```
+➜ SKIP=gitleaks git commit -m "skip gitleaks check"
+Detect hardcoded secrets................................................Skipped
+```
+
+## Usage
+
+```
+Gitleaks scans code, past or present, for secrets
+
+Usage:
+ gitleaks [command]
+
+Available Commands:
+ completion Generate the autocompletion script for the specified shell
+ dir scan directories or files for secrets
+ git scan git repositories for secrets
+ help Help about any command
+ stdin detect secrets from stdin
+ version display gitleaks version
+
+Flags:
+ -b, --baseline-path string path to baseline with issues that can be ignored
+ -c, --config string config file path
+ order of precedence:
+ 1. --config/-c
+ 2. env var GITLEAKS_CONFIG
+ 3. env var GITLEAKS_CONFIG_TOML with the file content
+ 4. (target path)/.gitleaks.toml
+ If none of the four options are used, then gitleaks will use the default config
+ --diagnostics string enable diagnostics (http OR comma-separated list: cpu,mem,trace). cpu=CPU prof, mem=memory prof, trace=exec tracing, http=serve via net/http/pprof
+ --diagnostics-dir string directory to store diagnostics output files when not using http mode (defaults to current directory)
+ --enable-rule strings only enable specific rules by id
+ --exit-code int exit code when leaks have been encountered (default 1)
+ -i, --gitleaks-ignore-path string path to .gitleaksignore file or folder containing one (default ".")
+ -h, --help help for gitleaks
+ --ignore-gitleaks-allow ignore gitleaks:allow comments
+ -l, --log-level string log level (trace, debug, info, warn, error, fatal) (default "info")
+ --max-archive-depth int allow scanning into nested archives up to this depth (default "0", no archive traversal is done)
+ --max-decode-depth int allow recursive decoding up to this depth (default "0", no decoding is done)
+ --max-target-megabytes int files larger than this will be skipped
+ --no-banner suppress banner
+ --no-color turn off color for verbose output
+ --redact uint[=100] redact secrets from logs and stdout. To redact only parts of the secret just apply a percent value from 0..100. For example --redact=20 (default 100%)
+ -f, --report-format string output format (json, csv, junit, sarif, template)
+ -r, --report-path string report file
+ --report-template string template file used to generate the report (implies --report-format=template)
+ --timeout int set a timeout for gitleaks commands in seconds (default "0", no timeout is set)
+ -v, --verbose show verbose output from scan
+ --version version for gitleaks
+
+Use "gitleaks [command] --help" for more information about a command.
+```
+
+### Commands
+
+⚠️ v8.19.0 introduced a change that deprecated `detect` and `protect`. Those commands are still available but
+are hidden in the `--help` menu. Take a look at this [gist](https://gist.github.com/zricethezav/b325bb93ebf41b9c0b0507acf12810d2) for easy command translations.
+If you find v8.19.0 broke an existing command (`detect`/`protect`), please open an issue.
+
+There are three scanning modes: `git`, `dir`, and `stdin`.
+
+#### Git
+
+The `git` command lets you scan local git repos. Under the hood, gitleaks uses the `git log -p` command to scan patches.
+You can configure the behavior of `git log -p` with the `log-opts` option.
+For example, if you wanted to run gitleaks on a range of commits you could use the following
+command: `gitleaks git -v --log-opts="--all commitA..commitB" path_to_repo`. See the [git log](https://git-scm.com/docs/git-log) documentation for more information.
+If there is no target specified as a positional argument, then gitleaks will attempt to scan the current working directory as a git repo.
+
+#### Dir
+
+The `dir` (aliases include `files`, `directory`) command lets you scan directories and files. Example: `gitleaks dir -v path_to_directory_or_file`.
+If there is no target specified as a positional argument, then gitleaks will scan the current working directory.
+
+#### Stdin
+
+You can also stream data to gitleaks with the `stdin` command. Example: `cat some_file | gitleaks -v stdin`
+
+### Creating a baseline
+
+When scanning large repositories or repositories with a long history, it can be convenient to use a baseline. When using a baseline,
+gitleaks will ignore any old findings that are present in the baseline. A baseline can be any gitleaks report. To create a gitleaks report, run gitleaks with the `--report-path` parameter.
+
+```
+gitleaks git --report-path gitleaks-report.json # This will save the report in a file called gitleaks-report.json
+```
+
+Once as baseline is created it can be applied when running the detect command again:
+
+```
+gitleaks git --baseline-path gitleaks-report.json --report-path findings.json
+```
+
+After running the detect command with the --baseline-path parameter, report output (findings.json) will only contain new issues.
+
+## Pre-Commit hook
+
+You can run Gitleaks as a pre-commit hook by copying the example `pre-commit.py` script into
+your `.git/hooks/` directory.
+
+## Load Configuration
+
+The order of precedence is:
+
+1. `--config/-c` option:
+ ```bash
+ gitleaks git --config /home/dev/customgitleaks.toml .
+ ```
+2. Environment variable `GITLEAKS_CONFIG` with the file path:
+ ```bash
+ export GITLEAKS_CONFIG="/home/dev/customgitleaks.toml"
+ gitleaks git .
+ ```
+3. Environment variable `GITLEAKS_CONFIG_TOML` with the file content:
+ ```bash
+ export GITLEAKS_CONFIG_TOML=`cat customgitleaks.toml`
+ gitleaks git .
+ ```
+4. A `.gitleaks.toml` file within the target path:
+ ```bash
+ gitleaks git .
+ ```
+
+If none of the four options are used, then gitleaks will use the default config.
+
+## Configuration
+
+Gitleaks offers a configuration format you can follow to write your own secret detection rules:
+
+```toml
+# Title for the gitleaks configuration file.
+title = "Custom Gitleaks configuration"
+
+# You have basically two options for your custom configuration:
+#
+# 1. define your own configuration, default rules do not apply
+#
+# use e.g., the default configuration as starting point:
+# https://github.com/gitleaks/gitleaks/blob/master/config/gitleaks.toml
+#
+# 2. extend a configuration, the rules are overwritten or extended
+#
+# When you extend a configuration the extended rules take precedence over the
+# default rules. I.e., if there are duplicate rules in both the extended
+# configuration and the default configuration the extended rules or
+# attributes of them will override the default rules.
+# Another thing to know with extending configurations is you can chain
+# together multiple configuration files to a depth of 2. Allowlist arrays are
+# appended and can contain duplicates.
+
+# useDefault and path can NOT be used at the same time. Choose one.
+[extend]
+# useDefault will extend the default gitleaks config built in to the binary
+# the latest version is located at:
+# https://github.com/gitleaks/gitleaks/blob/master/config/gitleaks.toml
+useDefault = true
+# or you can provide a path to a configuration to extend from.
+# The path is relative to where gitleaks was invoked,
+# not the location of the base config.
+# path = "common_config.toml"
+# If there are any rules you don't want to inherit, they can be specified here.
+disabledRules = [ "generic-api-key"]
+
+# An array of tables that contain information that define instructions
+# on how to detect secrets
+[[rules]]
+# Unique identifier for this rule
+id = "awesome-rule-1"
+
+# Short human-readable description of the rule.
+description = "awesome rule 1"
+
+# Golang regular expression used to detect secrets. Note Golang's regex engine
+# does not support lookaheads.
+regex = '''one-go-style-regex-for-this-rule'''
+
+# Int used to extract secret from regex match and used as the group that will have
+# its entropy checked if `entropy` is set.
+secretGroup = 3
+
+# Float representing the minimum shannon entropy a regex group must have to be considered a secret.
+entropy = 3.5
+
+# Golang regular expression used to match paths. This can be used as a standalone rule or it can be used
+# in conjunction with a valid `regex` entry.
+path = '''a-file-path-regex'''
+
+# Keywords are used for pre-regex check filtering. Rules that contain
+# keywords will perform a quick string compare check to make sure the
+# keyword(s) are in the content being scanned. Ideally these values should
+# either be part of the identiifer or unique strings specific to the rule's regex
+# (introduced in v8.6.0)
+keywords = [
+ "auth",
+ "password",
+ "token",
+]
+
+# Array of strings used for metadata and reporting purposes.
+tags = ["tag","another tag"]
+
+ # ⚠️ In v8.21.0 `[rules.allowlist]` was replaced with `[[rules.allowlists]]`.
+ # This change was backwards-compatible: instances of `[rules.allowlist]` still work.
+ #
+ # You can define multiple allowlists for a rule to reduce false positives.
+ # A finding will be ignored if _ANY_ `[[rules.allowlists]]` matches.
+ [[rules.allowlists]]
+ description = "ignore commit A"
+ # When multiple criteria are defined the default condition is "OR".
+ # e.g., this can match on |commits| OR |paths| OR |stopwords|.
+ condition = "OR"
+ commits = [ "commit-A", "commit-B"]
+ paths = [
+ '''go\.mod''',
+ '''go\.sum'''
+ ]
+ # note: stopwords targets the extracted secret, not the entire regex match
+ # like 'regexes' does. (stopwords introduced in 8.8.0)
+ stopwords = [
+ '''client''',
+ '''endpoint''',
+ ]
+
+ [[rules.allowlists]]
+ # The "AND" condition can be used to make sure all criteria match.
+ # e.g., this matches if |regexes| AND |paths| are satisfied.
+ condition = "AND"
+ # note: |regexes| defaults to check the _Secret_ in the finding.
+ # Acceptable values for |regexTarget| are "secret" (default), "match", and "line".
+ regexTarget = "match"
+ regexes = [ '''(?i)parseur[il]''' ]
+ paths = [ '''package-lock\.json''' ]
+
+# You can extend a particular rule from the default config. e.g., gitlab-pat
+# if you have defined a custom token prefix on your GitLab instance
+[[rules]]
+id = "gitlab-pat"
+# all the other attributes from the default rule are inherited
+
+ [[rules.allowlists]]
+ regexTarget = "line"
+ regexes = [ '''MY-glpat-''' ]
+
+
+# ⚠️ In v8.25.0 `[allowlist]` was replaced with `[[allowlists]]`.
+#
+# Global allowlists have a higher order of precedence than rule-specific allowlists.
+# If a commit listed in the `commits` field below is encountered then that commit will be skipped and no
+# secrets will be detected for said commit. The same logic applies for regexes and paths.
+[[allowlists]]
+description = "global allow list"
+commits = [ "commit-A", "commit-B", "commit-C"]
+paths = [
+ '''gitleaks\.toml''',
+ '''(.*?)(jpg|gif|doc)'''
+]
+# note: (global) regexTarget defaults to check the _Secret_ in the finding.
+# Acceptable values for regexTarget are "match" and "line"
+regexTarget = "match"
+regexes = [
+ '''219-09-9999''',
+ '''078-05-1120''',
+ '''(9[0-9]{2}|666)-\d{2}-\d{4}''',
+]
+# note: stopwords targets the extracted secret, not the entire regex match
+# like 'regexes' does. (stopwords introduced in 8.8.0)
+stopwords = [
+ '''client''',
+ '''endpoint''',
+]
+
+# ⚠️ In v8.25.0, `[[allowlists]]` have a new field called |targetRules|.
+#
+# Common allowlists can be defined once and assigned to multiple rules using |targetRules|.
+# This will only run on the specified rules, not globally.
+[[allowlists]]
+targetRules = ["awesome-rule-1", "awesome-rule-2"]
+description = "Our test assets trigger false-positives in a couple rules."
+paths = ['''tests/expected/._\.json$''']
+```
+
+Refer to the default [gitleaks config](https://github.com/gitleaks/gitleaks/blob/master/config/gitleaks.toml) for examples or follow the [contributing guidelines](https://github.com/gitleaks/gitleaks/blob/master/CONTRIBUTING.md) if you would like to contribute to the default configuration. Additionally, you can check out [this gitleaks blog post](https://blog.gitleaks.io/stop-leaking-secrets-configuration-2-3-aeed293b1fbf) which covers advanced configuration setups.
+
+### Additional Configuration
+
+#### Composite Rules (Multi-part or `required` Rules)
+In v8.28.0 Gitleaks introduced composite rules, which are made up of a single "primary" rule and one or more auxiliary or `required` rules. To create a composite rule, add a `[[rules.required]]` table to the primary rule specifying an `id` and optionally `withinLines` and/or `withinColumns` proximity constraints. A fragment is a chunk of content that Gitleaks processes at once (typically a file, part of a file, or git diff), and proximity matching instructs the primary rule to only report a finding if the auxiliary `required` rules also find matches within the specified area of the fragment.
+
+**Proximity matching:** Using the `withinLines` and `withinColumns` fields instructs the primary rule to only report a finding if the auxiliary `required` rules also find matches within the specified proximity. You can set:
+
+- **`withinLines: N`** - required findings must be within N lines (vertically)
+- **`withinColumns: N`** - required findings must be within N characters (horizontally)
+- **Both** - creates a rectangular search area (both constraints must be satisfied)
+- **Neither** - fragment-level matching (required findings can be anywhere in the same fragment)
+
+Here are diagrams illustrating each proximity behavior:
+
+```
+p = primary captured secret
+a = auxiliary (required) captured secret
+fragment = section of data gitleaks is looking at
+
+
+ *Fragment-level proximity*
+ Any required finding in the fragment
+ ┌────────┐
+ ┌──────┤fragment├─────┐
+ │ └──────┬─┤ │ ┌───────┐
+ │ │a│◀────┼─│✓ MATCH│
+ │ ┌─┐└─┘ │ └───────┘
+ │┌─┐ │p│ │
+ ││a│ ┌─┐└─┘ │ ┌───────┐
+ │└─┘ │a│◀──────────┼─│✓ MATCH│
+ └─▲─────┴─┴───────────┘ └───────┘
+ │ ┌───────┐
+ └────│✓ MATCH│
+ └───────┘
+
+
+ *Column bounded proximity*
+ `withinColumns = 3`
+ ┌────────┐
+ ┌────┬─┤fragment├─┬───┐
+ │ └──────┬─┤ │ ┌───────────┐
+ │ │ │a│◀┼───┼─│+1C ✓ MATCH│
+ │ ┌─┐└─┘ │ └───────────┘
+ │┌─┐ │ │p│ │ │
+┌──▶│a│ ┌─┐ └─┘ │ ┌───────────┐
+│ │└─┘ ││a│◀────────┼───┼─│-2C ✓ MATCH│
+│ │ ┘ │ └───────────┘
+│ └── -3C ───0C─── +3C ─┘
+│ ┌─────────┐
+│ │ -4C ✗ NO│
+└──│ MATCH │
+ └─────────┘
+
+
+ *Line bounded proximity*
+ `withinLines = 4`
+ ┌────────┐
+ ┌─────┤fragment├─────┐
+ +4L─ ─ ┴────────┘─ ─ ─│
+ │ │
+ │ ┌─┐ │ ┌────────────┐
+ │ ┌─┐ │a│◀──┼─│+1L ✓ MATCH │
+ 0L ┌─┐ │p│ └─┘ │ ├────────────┤
+ │ │a│◀──┴─┴────────┼─│-1L ✓ MATCH │
+ │ └─┘ │ └────────────┘
+ │ │ ┌─────────┐
+ -4L─ ─ ─ ─ ─ ─ ─ ─┌─┐─│ │-5L ✗ NO │
+ │ │a│◀┼─│ MATCH │
+ └────────────────┴─┴─┘ └─────────┘
+
+
+ *Line and column bounded proximity*
+ `withinLines = 4`
+ `withinColumns = 3`
+ ┌────────┐
+ ┌─────┤fragment├─────┐
+ +4L ┌└────────┴ ┐ │
+ │ ┌─┐ │ ┌───────────────┐
+ │ │ │a│◀┼───┼─│+2L/+1C ✓ MATCH│
+ │ ┌─┐└─┘ │ └───────────────┘
+ 0L │ │p│ │ │
+ │ └─┘ │
+ │ │ │ │ ┌────────────┐
+ -4L ─ ─ ─ ─ ─ ─┌─┐ │ │-5L/+3C ✗ NO│
+ │ │a│◀┼─│ MATCH │
+ └───-3C────0L───+3C┴─┘ └────────────┘
+```
+
+Some final quick thoughts on composite rules.
This is an experimental feature! It's subject to change so don't go sellin' a new B2B SaaS feature built ontop of this feature. Scan type (git vs dir) based context is interesting. I'm monitoring the situation. Composite rules might not be super useful for git scans because gitleaks only looks at additions in the git history. It could be useful to scan non-additions in git history for `required` rules. Oh, right this is a readme, I'll shut up now.
+
+#### gitleaks:allow
+
+If you are knowingly committing a test secret that gitleaks will catch you can add a `gitleaks:allow` comment to that line which will instruct gitleaks
+to ignore that secret. Ex:
+
+```
+class CustomClass:
+ discord_client_secret = '8dyfuiRyq=vVc3RRr_edRk-fK__JItpZ' #gitleaks:allow
+
+```
+
+#### .gitleaksignore
+
+You can ignore specific findings by creating a `.gitleaksignore` file at the root of your repo. In release v8.10.0 Gitleaks added a `Fingerprint` value to the Gitleaks report. Each leak, or finding, has a Fingerprint that uniquely identifies a secret. Add this fingerprint to the `.gitleaksignore` file to ignore that specific secret. See Gitleaks' [.gitleaksignore](https://github.com/gitleaks/gitleaks/blob/master/.gitleaksignore) for an example. Note: this feature is experimental and is subject to change in the future.
+
+#### Decoding
+
+Sometimes secrets are encoded in a way that can make them difficult to find
+with just regex. Now you can tell gitleaks to automatically find and decode
+encoded text. The flag `--max-decode-depth` enables this feature (the default
+value "0" means the feature is disabled by default).
+
+Recursive decoding is supported since decoded text can also contain encoded
+text. The flag `--max-decode-depth` sets the recursion limit. Recursion stops
+when there are no new segments of encoded text to decode, so setting a really
+high max depth doesn't mean it will make that many passes. It will only make as
+many as it needs to decode the text. Overall, decoding only minimally increases
+scan times.
+
+The findings for encoded text differ from normal findings in the following
+ways:
+
+- The location points the bounds of the encoded text
+ - If the rule matches outside the encoded text, the bounds are adjusted to
+ include that as well
+- The match and secret contain the decoded value
+- Two tags are added `decoded:` and `decode-depth:`
+
+Currently supported encodings:
+
+- **percent** - Any printable ASCII percent encoded values
+- **hex** - Any printable ASCII hex encoded values >= 32 characters
+- **base64** - Any printable ASCII base64 encoded values >= 16 characters
+
+#### Archive Scanning
+
+Sometimes secrets are packaged within archive files like zip files or tarballs,
+making them difficult to discover. Now you can tell gitleaks to automatically
+extract and scan the contents of archives. The flag `--max-archive-depth`
+enables this feature for both `dir` and `git` scan types. The default value of
+"0" means this feature is disabled by default.
+
+Recursive scanning is supported since archives can also contain other archives.
+The `--max-archive-depth` flag sets the recursion limit. Recursion stops when
+there are no new archives to extract, so setting a very high max depth just
+sets the potential to go that deep. It will only go as deep as it needs to.
+
+The findings for secrets located within an archive will include the path to the
+file inside the archive. Inner paths are separated with `!`.
+
+Example finding (shortened for brevity):
+
+```
+Finding: DB_PASSWORD=8ae31cacf141669ddfb5da
+...
+File: testdata/archives/nested.tar.gz!archives/files.tar!files/.env.prod
+Line: 4
+Commit: 6e6ee6596d337bb656496425fb98644eb62b4a82
+...
+Fingerprint: 6e6ee6596d337bb656496425fb98644eb62b4a82:testdata/archives/nested.tar.gz!archives/files.tar!files/.env.prod:generic-api-key:4
+Link: https://github.com/leaktk/gitleaks/blob/6e6ee6596d337bb656496425fb98644eb62b4a82/testdata/archives/nested.tar.gz
+```
+
+This means a secret was detected on line 4 of `files/.env.prod.` which is in
+`archives/files.tar` which is in `testdata/archives/nested.tar.gz`.
+
+Currently supported formats:
+
+The [compression](https://github.com/mholt/archives?tab=readme-ov-file#supported-compression-formats)
+and [archive](https://github.com/mholt/archives?tab=readme-ov-file#supported-archive-formats)
+formats supported by mholt's [archives package](https://github.com/mholt/archives)
+are supported.
+
+#### Reporting
+
+Gitleaks has built-in support for several report formats: [`json`](https://github.com/gitleaks/gitleaks/blob/master/testdata/expected/report/json_simple.json), [`csv`](https://github.com/gitleaks/gitleaks/blob/master/testdata/expected/report/csv_simple.csv?plain=1), [`junit`](https://github.com/gitleaks/gitleaks/blob/master/testdata/expected/report/junit_simple.xml), and [`sarif`](https://github.com/gitleaks/gitleaks/blob/master/testdata/expected/report/sarif_simple.sarif).
+
+If none of these formats fit your need, you can create your own report format with a [Go `text/template` .tmpl file](https://www.digitalocean.com/community/tutorials/how-to-use-templates-in-go#step-4-writing-a-template) and the `--report-template` flag. The template can use [extended functionality from the `Masterminds/sprig` template library](https://masterminds.github.io/sprig/).
+
+For example, the following template provides a custom JSON output:
+```gotemplate
+# jsonextra.tmpl
+[{{ $lastFinding := (sub (len . ) 1) }}
+{{- range $i, $finding := . }}{{with $finding}}
+ {
+ "Description": {{ quote .Description }},
+ "StartLine": {{ .StartLine }},
+ "EndLine": {{ .EndLine }},
+ "StartColumn": {{ .StartColumn }},
+ "EndColumn": {{ .EndColumn }},
+ "Line": {{ quote .Line }},
+ "Match": {{ quote .Match }},
+ "Secret": {{ quote .Secret }},
+ "File": "{{ .File }}",
+ "SymlinkFile": {{ quote .SymlinkFile }},
+ "Commit": {{ quote .Commit }},
+ "Entropy": {{ .Entropy }},
+ "Author": {{ quote .Author }},
+ "Email": {{ quote .Email }},
+ "Date": {{ quote .Date }},
+ "Message": {{ quote .Message }},
+ "Tags": [{{ $lastTag := (sub (len .Tags ) 1) }}{{ range $j, $tag := .Tags }}{{ quote . }}{{ if ne $j $lastTag }},{{ end }}{{ end }}],
+ "RuleID": {{ quote .RuleID }},
+ "Fingerprint": {{ quote .Fingerprint }}
+ }{{ if ne $i $lastFinding }},{{ end }}
+{{- end}}{{ end }}
+]
+```
+
+Usage:
+```sh
+$ gitleaks dir ~/leaky-repo/ --report-path "report.json" --report-format template --report-template testdata/report/jsonextra.tmpl
+```
+
+## Sponsorships
+
+
+
+
+
+
+
+
+
+## Exit Codes
+
+You can always set the exit code when leaks are encountered with the --exit-code flag. Default exit codes below:
+
+```
+0 - no leaks present
+1 - leaks or error encountered
+126 - unknown flag
+```
+
+### Join the Discord! [](https://discord.gg/8Hzbrnkr7E)
diff --git a/README.wehub.md b/README.wehub.md
new file mode 100644
index 0000000..f8881eb
--- /dev/null
+++ b/README.wehub.md
@@ -0,0 +1,7 @@
+# WeHub 来源说明
+
+- 原始项目:`gitleaks/gitleaks`
+- 原始仓库:https://github.com/gitleaks/gitleaks
+- 导入方式:上游默认分支的最新快照
+- 原作者、版权和许可证信息以原始仓库及本仓库 LICENSE 为准
+- 本文件仅用于记录来源,不代表 WeHub 是原项目作者
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..1750c8d
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,19 @@
+# Security Policy
+
+## Supported Versions
+
+| Version | Supported |
+|---------|-----------|
+| Latest | Yes |
+
+## Reporting a Vulnerability
+
+If you discover a security vulnerability in gitleaks, please report it responsibly:
+
+1. **Do not open a public issue.**
+2. Use [GitHub's private vulnerability reporting](https://github.com/gitleaks/gitleaks/security/advisories/new) to submit your report directly.
+3. Include a description of the vulnerability, steps to reproduce, and any relevant logs or screenshots.
+
+## Scope
+
+This policy covers `gitleaks` (this repository). For vulnerabilities in `gitleaks-action`, please report them at [gitleaks/gitleaks-action](https://github.com/gitleaks/gitleaks-action/security/advisories/new).
diff --git a/USERS.md b/USERS.md
new file mode 100644
index 0000000..3c3cd69
--- /dev/null
+++ b/USERS.md
@@ -0,0 +1,26 @@
+## Who uses Gitleaks?
+
+As the Gitleaks Community grows, we'd like to keep a list of our users.
+
+Here's a running list of some organizations using Gitleaks[^1]:
+
+1. [GitLab](https://docs.gitlab.com/ee/user/application_security/secret_detection/)
+1. [Gitleaks](https://gitleaks.io)
+1. [GoReleaser](https://goreleaser.com)
+2. [Trendyol](https://trendyol.com)
+
+Feel free to [add yours](https://github.com/zricethezav/gitleaks/edit/master/USERS.md)!
+
+
+
+[^1]: Entries were either added by the companies themselves or by the maintainers after seeing it in the wild.
+ You can see all public repositories using Gitleaks or Gitleaks-Action by [searching on GitHub](https://github.com/search?q=gitleaks).
+
+
diff --git a/cmd/detect.go b/cmd/detect.go
new file mode 100644
index 0000000..9616117
--- /dev/null
+++ b/cmd/detect.go
@@ -0,0 +1,136 @@
+// The `detect` and `protect` command is now deprecated. Here are some equivalent commands
+// to help guide you.
+
+// OLD CMD: gitleaks detect --source={repo}
+// NEW CMD: gitleaks git {repo}
+
+// OLD CMD: gitleaks protect --source={repo}
+// NEW CMD: gitleaks git --pre-commit {repo}
+
+// OLD CMD: gitleaks protect --staged --source={repo}
+// NEW CMD: gitleaks git --pre-commit --staged {repo}
+
+// OLD CMD: gitleaks detect --no-git --source={repo}
+// NEW CMD: gitleaks directory {directory/file}
+
+// OLD CMD: gitleaks detect --no-git --pipe
+// NEW CMD: gitleaks stdin
+
+package cmd
+
+import (
+ "os"
+ "time"
+
+ "github.com/spf13/cobra"
+
+ "github.com/zricethezav/gitleaks/v8/cmd/scm"
+ "github.com/zricethezav/gitleaks/v8/logging"
+ "github.com/zricethezav/gitleaks/v8/report"
+ "github.com/zricethezav/gitleaks/v8/sources"
+)
+
+func init() {
+ rootCmd.AddCommand(detectCmd)
+ detectCmd.Flags().Bool("no-git", false, "treat git repo as a regular directory and scan those files, --log-opts has no effect on the scan when --no-git is set")
+ detectCmd.Flags().Bool("pipe", false, "scan input from stdin, ex: `cat some_file | gitleaks detect --pipe`")
+ detectCmd.Flags().Bool("follow-symlinks", false, "scan files that are symlinks to other files")
+ detectCmd.Flags().StringP("source", "s", ".", "path to source")
+ detectCmd.Flags().String("log-opts", "", "git log options")
+ detectCmd.Flags().String("platform", "", "the target platform used to generate links (github, gitlab)")
+}
+
+var detectCmd = &cobra.Command{
+ Use: "detect",
+ Short: "detect secrets in code",
+ Run: runDetect,
+ Hidden: true,
+}
+
+func runDetect(cmd *cobra.Command, args []string) {
+ // start timer
+ start := time.Now()
+ sourcePath := mustGetStringFlag(cmd, "source")
+
+ // setup config (aka, the thing that defines rules)
+ initConfig(sourcePath)
+ initDiagnostics()
+ cfg := Config(cmd)
+
+ // create detector
+ detector := Detector(cmd, cfg, sourcePath)
+
+ // parse flags
+ detector.FollowSymlinks = mustGetBoolFlag(cmd, "follow-symlinks")
+ exitCode := mustGetIntFlag(cmd, "exit-code")
+ noGit := mustGetBoolFlag(cmd, "no-git")
+ fromPipe := mustGetBoolFlag(cmd, "pipe")
+ // determine what type of scan:
+ // - git: scan the history of the repo
+ // - no-git: scan files by treating the repo as a plain directory
+ var (
+ err error
+ findings []report.Finding
+ )
+ if noGit {
+ findings, err = detector.DetectSource(
+ cmd.Context(), &sources.Files{
+ Config: &cfg,
+ FollowSymlinks: detector.FollowSymlinks,
+ MaxFileSize: detector.MaxTargetMegaBytes * 1_000_000,
+ Path: sourcePath,
+ Sema: detector.Sema,
+ MaxArchiveDepth: detector.MaxArchiveDepth,
+ },
+ )
+
+ if err != nil {
+ // don't exit on error, just log it
+ logging.Error().Err(err).Msg("failed to scan directory")
+ }
+ } else if fromPipe {
+ findings, err = detector.DetectSource(
+ cmd.Context(), &sources.File{
+ Content: os.Stdin,
+ MaxArchiveDepth: detector.MaxArchiveDepth,
+ },
+ )
+
+ if err != nil {
+ // log fatal to exit, no need to continue since a report
+ // will not be generated when scanning from a pipe...for now
+ logging.Fatal().Err(err).Msg("failed scan input from stdin")
+ }
+ } else {
+ var (
+ gitCmd *sources.GitCmd
+ scmPlatform scm.Platform
+ )
+
+ logOpts := mustGetStringFlag(cmd, "log-opts")
+ if gitCmd, err = sources.NewGitLogCmdContext(cmd.Context(), sourcePath, logOpts); err != nil {
+ logging.Fatal().Err(err).Msg("could not create Git cmd")
+ }
+
+ if scmPlatform, err = scm.PlatformFromString(mustGetStringFlag(cmd, "platform")); err != nil {
+ logging.Fatal().Err(err).Send()
+ }
+
+ findings, err = detector.DetectSource(
+ cmd.Context(), &sources.Git{
+ Cmd: gitCmd,
+ Config: &detector.Config,
+ Remote: sources.NewRemoteInfoContext(cmd.Context(), scmPlatform, sourcePath),
+ Sema: detector.Sema,
+ MaxArchiveDepth: detector.MaxArchiveDepth,
+ },
+ )
+
+ if err != nil {
+ // don't exit on error, just log it
+ logging.Error().Err(err).Msg("failed to scan Git repository")
+ }
+ }
+
+ findingSummaryAndExit(detector, findings, exitCode, start, err)
+}
diff --git a/cmd/diagnostics.go b/cmd/diagnostics.go
new file mode 100644
index 0000000..a48ce80
--- /dev/null
+++ b/cmd/diagnostics.go
@@ -0,0 +1,239 @@
+package cmd
+
+import (
+ "errors"
+ "fmt"
+ "net/http"
+ _ "net/http/pprof"
+ "os"
+ "path/filepath"
+ "runtime"
+ "runtime/pprof"
+ "runtime/trace"
+ "strings"
+
+ "github.com/zricethezav/gitleaks/v8/logging"
+)
+
+// DiagnosticsManager manages various types of diagnostics
+type DiagnosticsManager struct {
+ Enabled bool
+ DiagTypes []string
+ OutputDir string
+ cpuProfile *os.File
+ memProfile string
+ traceProfile *os.File
+}
+
+// NewDiagnosticsManager creates a new DiagnosticsManager instance
+func NewDiagnosticsManager(diagnosticsFlag string, diagnosticsDir string) (*DiagnosticsManager, error) {
+ if diagnosticsFlag == "" {
+ return &DiagnosticsManager{Enabled: false}, nil
+ }
+
+ dm := &DiagnosticsManager{
+ Enabled: true,
+ DiagTypes: strings.Split(diagnosticsFlag, ","),
+ OutputDir: diagnosticsDir,
+ }
+
+ if diagnosticsFlag == "http" {
+ if len(diagnosticsDir) != 0 {
+ return nil, errors.New("the diagnostics directory should not be set in http mode")
+ }
+
+ return dm, nil
+ }
+
+ // If no output directory is specified, use the current directory
+ if dm.OutputDir == "" {
+ var err error
+ dm.OutputDir, err = os.Getwd()
+ if err != nil {
+ return nil, fmt.Errorf("failed to get current directory: %w", err)
+ }
+ logging.Debug().Msgf("No diagnostics directory specified, using current directory: %s", dm.OutputDir)
+ }
+
+ // Create the output directory if it doesn't exist
+ if err := os.MkdirAll(dm.OutputDir, 0755); err != nil {
+ return nil, fmt.Errorf("failed to create diagnostics directory: %w", err)
+ }
+
+ // Make sure the output directory is absolute
+ if !filepath.IsAbs(dm.OutputDir) {
+ absPath, err := filepath.Abs(dm.OutputDir)
+ if err != nil {
+ return nil, fmt.Errorf("failed to get absolute path for diagnostics directory: %w", err)
+ }
+ dm.OutputDir = absPath
+ }
+
+ logging.Debug().Msgf("Diagnostics enabled: %s", strings.Join(dm.DiagTypes, ","))
+ logging.Debug().Msgf("Diagnostics output directory: %s", dm.OutputDir)
+
+ return dm, nil
+}
+
+// StartDiagnostics starts all enabled diagnostics
+func (dm *DiagnosticsManager) StartDiagnostics() error {
+ if !dm.Enabled {
+ return nil
+ }
+
+ var err error
+
+ for _, diagType := range dm.DiagTypes {
+ diagType = strings.TrimSpace(diagType)
+ switch diagType {
+ case "cpu":
+ if err = dm.StartCPUProfile(); err != nil {
+ return err
+ }
+ case "mem":
+ if err = dm.SetupMemoryProfile(); err != nil {
+ return err
+ }
+ case "trace":
+ if err = dm.StartTraceProfile(); err != nil {
+ return err
+ }
+ case "http":
+ if err = dm.StartHttpHandler(); err != nil {
+ return err
+ }
+ default:
+ logging.Warn().Msgf("Unknown diagnostics type: %s", diagType)
+ }
+ }
+
+ return nil
+}
+
+// StopDiagnostics stops all started diagnostics
+func (dm *DiagnosticsManager) StopDiagnostics() {
+ if !dm.Enabled {
+ return
+ }
+
+ logging.Debug().Msg("Stopping diagnostics and writing profiling data...")
+
+ for _, diagType := range dm.DiagTypes {
+ diagType = strings.TrimSpace(diagType)
+ switch diagType {
+ case "cpu":
+ dm.StopCPUProfile()
+ case "mem":
+ dm.WriteMemoryProfile()
+ case "trace":
+ dm.StopTraceProfile()
+ case "http":
+ // No need to stop the http one
+ }
+ }
+}
+
+func (dm *DiagnosticsManager) StartHttpHandler() error {
+ if len(dm.DiagTypes) > 1 {
+ return errors.New("other diagnostics modes should not be enabled when http mode is enabled")
+ }
+
+ go func() {
+ logging.Error().Err(http.ListenAndServe("localhost:6060", nil)).Send()
+ }()
+
+ logging.Info().Str("url", "http://localhost:6060/debug/pprof/").Msg("Diagnostics server started")
+ return nil
+}
+
+// StartCPUProfile starts CPU profiling
+func (dm *DiagnosticsManager) StartCPUProfile() error {
+ cpuProfilePath := filepath.Join(dm.OutputDir, "cpu.pprof")
+ f, err := os.Create(cpuProfilePath)
+ if err != nil {
+ return fmt.Errorf("could not create CPU profile at %s: %w", cpuProfilePath, err)
+ }
+
+ if err := pprof.StartCPUProfile(f); err != nil {
+ _ = f.Close()
+ return fmt.Errorf("could not start CPU profile: %w", err)
+ }
+
+ dm.cpuProfile = f
+ return nil
+}
+
+// StopCPUProfile stops CPU profiling
+func (dm *DiagnosticsManager) StopCPUProfile() {
+ if dm.cpuProfile != nil {
+ pprof.StopCPUProfile()
+ if err := dm.cpuProfile.Close(); err != nil {
+ logging.Error().Err(err).Msg("Error closing CPU profile file")
+ }
+ logging.Info().Msgf("CPU profile written to: %s", dm.cpuProfile.Name())
+ dm.cpuProfile = nil
+ }
+}
+
+// SetupMemoryProfile sets up memory profiling to be written when StopDiagnostics is called
+func (dm *DiagnosticsManager) SetupMemoryProfile() error {
+ memProfilePath := filepath.Join(dm.OutputDir, "mem.pprof")
+ dm.memProfile = memProfilePath
+ return nil
+}
+
+// WriteMemoryProfile writes the memory profile to disk
+func (dm *DiagnosticsManager) WriteMemoryProfile() {
+ if dm.memProfile == "" {
+ return
+ }
+
+ f, err := os.Create(dm.memProfile)
+ if err != nil {
+ logging.Error().Err(err).Msgf("Could not create memory profile at %s", dm.memProfile)
+ return
+ }
+
+ // Get memory profile
+ runtime.GC() // Run GC before taking the memory profile
+ if err := pprof.WriteHeapProfile(f); err != nil {
+ logging.Error().Err(err).Msg("Could not write memory profile")
+ } else {
+ logging.Info().Msgf("Memory profile written to: %s", dm.memProfile)
+ }
+
+ if err := f.Close(); err != nil {
+ logging.Error().Err(err).Msg("Error closing memory profile file")
+ }
+
+ dm.memProfile = ""
+}
+
+// StartTraceProfile starts execution tracing
+func (dm *DiagnosticsManager) StartTraceProfile() error {
+ traceProfilePath := filepath.Join(dm.OutputDir, "trace.out")
+ f, err := os.Create(traceProfilePath)
+ if err != nil {
+ return fmt.Errorf("could not create trace profile at %s: %w", traceProfilePath, err)
+ }
+
+ if err := trace.Start(f); err != nil {
+ _ = f.Close()
+ return fmt.Errorf("could not start trace profile: %w", err)
+ }
+
+ dm.traceProfile = f
+ return nil
+}
+
+// StopTraceProfile stops execution tracing
+func (dm *DiagnosticsManager) StopTraceProfile() {
+ if dm.traceProfile != nil {
+ trace.Stop()
+ if err := dm.traceProfile.Close(); err != nil {
+ logging.Error().Err(err).Msg("Error closing trace profile file")
+ }
+ logging.Info().Msgf("Trace profile written to: %s", dm.traceProfile.Name())
+ dm.traceProfile = nil
+ }
+}
diff --git a/cmd/directory.go b/cmd/directory.go
new file mode 100644
index 0000000..d91700f
--- /dev/null
+++ b/cmd/directory.go
@@ -0,0 +1,74 @@
+package cmd
+
+import (
+ "time"
+
+ "github.com/spf13/cobra"
+
+ "github.com/zricethezav/gitleaks/v8/logging"
+ "github.com/zricethezav/gitleaks/v8/sources"
+)
+
+func init() {
+ rootCmd.AddCommand(directoryCmd)
+ directoryCmd.Flags().Bool("follow-symlinks", false, "scan files that are symlinks to other files")
+}
+
+var directoryCmd = &cobra.Command{
+ Use: "dir [flags] [path]",
+ Aliases: []string{"file", "directory"},
+ Short: "scan directories or files for secrets",
+ Run: runDirectory,
+}
+
+func runDirectory(cmd *cobra.Command, args []string) {
+ // grab source
+ source := "."
+ if len(args) == 1 {
+ source = args[0]
+ if source == "" {
+ source = "."
+ }
+ }
+
+ initConfig(source)
+ initDiagnostics()
+ var err error
+
+ // setup config (aka, the thing that defines rules)
+ cfg := Config(cmd)
+
+ // start timer
+ start := time.Now()
+
+ detector := Detector(cmd, cfg, source)
+
+ // set follow symlinks flag
+ if detector.FollowSymlinks, err = cmd.Flags().GetBool("follow-symlinks"); err != nil {
+ logging.Fatal().Err(err).Send()
+ }
+
+ // set exit code
+ exitCode, err := cmd.Flags().GetInt("exit-code")
+ if err != nil {
+ logging.Fatal().Err(err).Msg("could not get exit code")
+ }
+
+ findings, err := detector.DetectSource(
+ cmd.Context(),
+ &sources.Files{
+ Config: &cfg,
+ FollowSymlinks: detector.FollowSymlinks,
+ MaxFileSize: detector.MaxTargetMegaBytes * 1_000_000,
+ Path: source,
+ Sema: detector.Sema,
+ MaxArchiveDepth: detector.MaxArchiveDepth,
+ },
+ )
+
+ if err != nil {
+ logging.Error().Err(err).Msg("failed scan directory")
+ }
+
+ findingSummaryAndExit(detector, findings, exitCode, start, err)
+}
diff --git a/cmd/generate/config/base/config.go b/cmd/generate/config/base/config.go
new file mode 100644
index 0000000..7e2ff23
--- /dev/null
+++ b/cmd/generate/config/base/config.go
@@ -0,0 +1,121 @@
+package base
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/zricethezav/gitleaks/v8/config"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+func CreateGlobalConfig() config.Config {
+ return config.Config{
+ Title: "gitleaks config",
+ Allowlists: []*config.Allowlist{
+ {
+ Description: "global allow lists",
+ Regexes: []*regexp.Regexp{
+ // ----------- General placeholders -----------
+ regexp.MustCompile(`(?i)^true|false|null$`),
+ // Awkward workaround to detect repeated characters.
+ func() *regexp.Regexp {
+ var (
+ letters = "abcdefghijklmnopqrstuvwxyz*."
+ patterns []string
+ )
+ for _, char := range letters {
+ if char == '*' || char == '.' {
+ patterns = append(patterns, fmt.Sprintf("\\%c+", char))
+ } else {
+ patterns = append(patterns, fmt.Sprintf("%c+", char))
+ }
+ }
+ return regexp.MustCompile("^(?i:" + strings.Join(patterns, "|") + ")$")
+ }(),
+
+ // ----------- Environment Variables -----------
+ regexp.MustCompile(`^\$(?:\d+|{\d+})$`),
+ regexp.MustCompile(`^\$(?:[A-Z_]+|[a-z_]+)$`),
+ regexp.MustCompile(`^\${(?:[A-Z_]+|[a-z_]+)}$`),
+
+ // ----------- Interpolated Variables -----------
+ // Ansible (https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html)
+ regexp.MustCompile(`^\{\{[ \t]*[\w ().|]+[ \t]*}}$`),
+ // GitHub Actions
+ // https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables
+ // https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions
+ regexp.MustCompile(`^\$\{\{[ \t]*(?:(?:env|github|secrets|vars)(?:\.[A-Za-z]\w+)+[\w "'&./=|]*)[ \t]*}}$`),
+ // NuGet (https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file#using-environment-variables)
+ regexp.MustCompile(`^%(?:[A-Z_]+|[a-z_]+)%$`),
+ // String formatting.
+ regexp.MustCompile(`^%[+\-# 0]?[bcdeEfFgGoOpqstTUvxX]$`), // Golang (https://pkg.go.dev/fmt)
+ regexp.MustCompile(`^\{\d{0,2}}$`), // Python (https://docs.python.org/3/tutorial/inputoutput.html)
+ // Urban Code Deploy (https://www.ibm.com/support/pages/replace-token-step-replaces-replacement-values-windows-variables)
+ regexp.MustCompile(`^@(?:[A-Z_]+|[a-z_]+)@$`),
+
+ // ----------- Miscellaneous -----------
+ // File paths
+ regexp.MustCompile(`^/Users/(?i)[a-z0-9]+/[\w .-/]+$`), // MacOS
+ regexp.MustCompile(`^/(?:bin|etc|home|opt|tmp|usr|var)/[\w ./-]+$`), // Linux
+ // 11980 Jps -Dapplication.home=D:\develop_tools\jdk\jdk1.8.0_131 -Xms8m
+ //regexp.MustCompile(`^$`), // Windows
+ },
+ Paths: []*regexp.Regexp{
+ regexp.MustCompile(`gitleaks\.toml`),
+
+ // ----------- Documents and media -----------
+ regexp.MustCompile(`(?i)\.(?:bmp|gif|jpe?g|png|svg|tiff?)$`), // Images
+ regexp.MustCompile(`(?i)\.(?:eot|[ot]tf|woff2?)$`), // Fonts
+ regexp.MustCompile(`(?i)\.(?:docx?|xlsx?|pdf|bin|socket|vsidx|v2|suo|wsuo|.dll|pdb|exe|gltf)$`),
+
+ // ----------- Golang files -----------
+ regexp.MustCompile(`go\.(?:mod|sum|work(?:\.sum)?)$`),
+ regexp.MustCompile(`(?:^|/)vendor/modules\.txt$`),
+ regexp.MustCompile(`(?:^|/)vendor/(?:github\.com|golang\.org/x|google\.golang\.org|gopkg\.in|istio\.io|k8s\.io|sigs\.k8s\.io)(?:/.*)?$`),
+
+ // ----------- Java files -----------
+ // Gradle
+ regexp.MustCompile(`(?:^|/)gradlew(?:\.bat)?$`),
+ regexp.MustCompile(`(?:^|/)gradle\.lockfile$`),
+ regexp.MustCompile(`(?:^|/)mvnw(?:\.cmd)?$`),
+ regexp.MustCompile(`(?:^|/)\.mvn/wrapper/MavenWrapperDownloader\.java$`),
+
+ // ----------- JavaScript files -----------
+ // Dependencies and lock files.
+ regexp.MustCompile(`(?:^|/)node_modules(?:/.*)?$`),
+ regexp.MustCompile(`(?:^|/)(?:deno\.lock|npm-shrinkwrap\.json|package-lock\.json|pnpm-lock\.yaml|yarn\.lock)$`),
+ regexp.MustCompile(`(?:^|/)bower_components(?:/.*)?$`),
+ // TODO: Add more common static assets, such as swagger-ui.
+ regexp.MustCompile(`(?:^|/)(?:angular|bootstrap|jquery(?:-?ui)?|plotly|swagger-?ui)[a-zA-Z0-9.-]*(?:\.min)?\.js(?:\.map)?$`),
+ regexp.MustCompile(`(?:^|/)javascript\.json$`),
+
+ // ----------- Python files -----------
+ // Dependencies and lock files.
+ regexp.MustCompile(`(?:^|/)(?:Pipfile|poetry)\.lock$`),
+ // Virtual environments
+ regexp.MustCompile(`(?i)(?:^|/)(?:v?env|virtualenv)/lib(?:64)?(?:/.*)?$`),
+ regexp.MustCompile(`(?i)(?:^|/)(?:lib(?:64)?/python[23](?:\.\d{1,2})+|python/[23](?:\.\d{1,2})+/lib(?:64)?)(?:/.*)?$`),
+ // dist-info directory (https://py-pkgs.org/04-package-structure.html#building-sdists-and-wheels)
+ regexp.MustCompile(`(?i)(?:^|/)[a-z0-9_.]+-[0-9.]+\.dist-info(?:/.+)?$`),
+
+ // ----------- Ruby files -----------
+ regexp.MustCompile(`(?:^|/)vendor/(?:bundle|ruby)(?:/.*?)?$`),
+ regexp.MustCompile(`\.gem$`), // tar archive
+
+ // Misc
+ regexp.MustCompile(`verification-metadata\.xml`),
+ regexp.MustCompile(`Database.refactorlog`),
+
+ // ----------- Git files ------------
+ regexp.MustCompile(`(?:^|/)\.git$`),
+ },
+ StopWords: []string{
+ "abcdefghijklmnopqrstuvwxyz", // character range
+ // ----------- Secrets -----------
+ // Checkmarx client secret. (https://github.com/checkmarx-ts/checkmarx-python-sdk/blob/86560f6e2a3e46d16322101294da10d5d190312d/README.md?plain=1#L56)
+ "014df517-39d1-4453-b7b3-9930c563627c",
+ },
+ },
+ },
+ }
+}
diff --git a/cmd/generate/config/base/config_test.go b/cmd/generate/config/base/config_test.go
new file mode 100644
index 0000000..322df3e
--- /dev/null
+++ b/cmd/generate/config/base/config_test.go
@@ -0,0 +1,203 @@
+package base
+
+import (
+ "testing"
+)
+
+var allowlistRegexTests = map[string]struct {
+ invalid []string
+ valid []string
+}{
+ "general placeholders": {
+ invalid: []string{
+ `true`, `True`, `false`, `False`, `null`, `NULL`,
+ },
+ },
+ "general placeholders - repeated characters": {
+ invalid: []string{
+ `aaaaaaaaaaaaaaaaa`, `BBBBBBBBBBbBBBBBBBbBB`, `********************`,
+ },
+ valid: []string{`aaaaaaaaaaaaaaaaaaabaa`, `pas*************d`},
+ },
+ "environment variables": {
+ invalid: []string{`$2`, `$GIT_PASSWORD`, `${GIT_PASSWORD}`, `$password`},
+ valid: []string{`$yP@R.@=ibxI`, `$2a6WCust9aE`, `${not_complete1`},
+ },
+ "interpolated variables - ansible": {
+ invalid: []string{
+ `{{ x }}`, `{{ password }}`, `{{password}}`, `{{ data.proxy_password }}`,
+ `{{ dict1 | ansible.builtin.combine(dict2) }}`,
+ },
+ },
+ "interpolated variables - github actions": {
+ invalid: []string{
+ `${{ env.First_Name }}`,
+ `${{ env.DAY_OF_WEEK == 'Monday' }}`,
+ `${{env.JAVA_VERSION}}`,
+ `${{ github.event.issue.title }}`,
+ `${{ github.repository == "Gattocrucco/lsqfitgp" }}`,
+ `${{ github.event.pull_request.number || github.ref }}`,
+ `${{ github.event_name == 'pull_request' && github.event.action == 'unassigned' }}`,
+ `${{ secrets.SuperSecret }}`,
+ `${{ vars.JOB_NAME }}`,
+ `${{ vars.USE_VARIABLES == 'true' }}`,
+ },
+ },
+ "interpolated variables - nuget": {
+ invalid: []string{
+ `%MY_PASSWORD%`, `%password%`,
+ },
+ },
+ "interpolated variables - string fmt - golang": {
+ invalid: []string{
+ `%b`, `%c`, `%d`, `% d`, `%e`, `%E`, `%f`, `%F`, `%g`, `%G`, `%o`, `%O`, `%p`, `%q`, `%-s`, `%s`, `%t`, `%T`, `%U`, `%#U`, `%+v`, `%#v`, `%v`, `%x`, `%X`,
+ },
+ },
+ "interpolated variables - string fmt - python": {
+ invalid: []string{
+ `{}`, `{0}`, `{10}`,
+ },
+ },
+ "interpolated variables - ucd": {
+ invalid: []string{`@password@`, `@LDAP_PASS@`},
+ valid: []string{`@username@mastodon.example`},
+ },
+ "miscellaneous - file paths": {
+ invalid: []string{
+ // MacOS
+ `/Users/james/Projects/SwiftCode/build/Release`,
+ // Linux
+ `/tmp/screen-exchange`,
+ },
+ valid: []string{},
+ },
+}
+
+func TestConfigAllowlistRegexes(t *testing.T) {
+ cfg := CreateGlobalConfig()
+ allowlists := cfg.Allowlists
+ for name, cases := range allowlistRegexTests {
+ t.Run(name, func(t *testing.T) {
+ for _, c := range cases.invalid {
+ for _, a := range allowlists {
+ if !a.RegexAllowed(c) {
+ t.Errorf("invalid value not marked as allowed: %s", c)
+ }
+ }
+ }
+
+ for _, c := range cases.valid {
+ for _, a := range allowlists {
+ if a.RegexAllowed(c) {
+ t.Errorf("valid value marked as allowed: %s", c)
+ }
+ }
+ }
+ })
+ }
+}
+
+func BenchmarkConfigAllowlistRegexes(b *testing.B) {
+ cfg := CreateGlobalConfig()
+ allowlists := cfg.Allowlists
+ for n := 0; n < b.N; n++ {
+ for _, cases := range allowlistRegexTests {
+ for _, c := range cases.invalid {
+ for _, a := range allowlists {
+ a.RegexAllowed(c)
+ }
+ }
+
+ for _, c := range cases.valid {
+ for _, a := range allowlists {
+ a.RegexAllowed(c)
+ }
+ }
+ }
+ }
+}
+
+var allowlistPathsTests = map[string]struct {
+ invalid []string
+ valid []string
+}{
+ "javascript - common static assets": {
+ invalid: []string{
+ `tests/e2e/nuget/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js`,
+ `src/main/static/lib/angular.1.2.16.min.js`,
+ `src/main/resources/static/jquery-ui-1.12.1/jquery-ui-min.js`,
+ `src/main/resources/static/js/jquery-ui-1.10.4.min.js`,
+ `src-static/js/plotly.min.js`,
+ `swagger/swaggerui/swagger-ui-bundle.js.map`,
+ `swagger/swaggerui/swagger-ui-es-bundle.js.map`,
+ `src/main/static/swagger-ui.min.js`,
+ `swagger/swaggerui/swagger-ui.js`,
+ },
+ },
+ "python": {
+ invalid: []string{
+ // lock files
+ `Pipfile.lock`, `poetry.lock`,
+ // virtual environments
+ "env/lib/python3.7/site-packages/urllib3/util/url.py",
+ "venv/Lib/site-packages/regex-2018.08.29.dist-info/DESCRIPTION.rst",
+ "venv/lib64/python3.5/site-packages/pynvml.py",
+ "python/python3/virtualenv/Lib/site-packages/pyphonetics/utils.py",
+ "virtualenv/lib64/python3.7/base64.py",
+ // packages
+ "cde-root/usr/lib64/python2.4/site-packages/Numeric.pth",
+ "lib/python3.9/site-packages/setuptools/_distutils/msvccompiler.py",
+ "lib/python3.8/site-packages/botocore/data/alexaforbusiness/2017-11-09/service-2.json",
+ "code/python/3.7.4/Lib/site-packages/dask/bytes/tests/test_bytes_utils.py",
+ "python/3.7.4/Lib/site-packages/fsspec/utils.py",
+ "python/2.7.16.32/Lib/bsddb/test/test_dbenv.py",
+ "python/lib/python3.8/site-packages/boto3/data/ec2/2016-04-01/resources-1.json",
+ // distinfo
+ "libs/PyX-0.15.dist-info/AUTHORS",
+ },
+ },
+}
+
+func TestConfigAllowlistPaths(t *testing.T) {
+ cfg := CreateGlobalConfig()
+ allowlists := cfg.Allowlists
+ for name, cases := range allowlistPathsTests {
+ t.Run(name, func(t *testing.T) {
+ for _, c := range cases.invalid {
+ for _, a := range allowlists {
+ if !a.PathAllowed(c) {
+ t.Errorf("invalid path not marked as allowed: %s", c)
+ }
+ }
+ }
+
+ for _, c := range cases.valid {
+ for _, a := range allowlists {
+ if a.PathAllowed(c) {
+ t.Errorf("valid path marked as allowed: %s", c)
+ }
+ }
+ }
+ })
+ }
+}
+
+func BenchmarkConfigAllowlistPaths(b *testing.B) {
+ cfg := CreateGlobalConfig()
+ allowlists := cfg.Allowlists
+ for n := 0; n < b.N; n++ {
+ for _, cases := range allowlistPathsTests {
+ for _, c := range cases.invalid {
+ for _, a := range allowlists {
+ a.PathAllowed(c)
+ }
+ }
+
+ for _, c := range cases.valid {
+ for _, a := range allowlists {
+ a.PathAllowed(c)
+ }
+ }
+ }
+ }
+}
diff --git a/cmd/generate/config/main.go b/cmd/generate/config/main.go
new file mode 100644
index 0000000..f5a9b96
--- /dev/null
+++ b/cmd/generate/config/main.go
@@ -0,0 +1,301 @@
+package main
+
+import (
+ "os"
+ "slices"
+ "text/template"
+
+ "github.com/zricethezav/gitleaks/v8/cmd/generate/config/base"
+ "github.com/zricethezav/gitleaks/v8/cmd/generate/config/rules"
+ "github.com/zricethezav/gitleaks/v8/config"
+ "github.com/zricethezav/gitleaks/v8/logging"
+)
+
+const (
+ templatePath = "rules/config.tmpl"
+)
+
+//go:generate go run $GOFILE ../../../config/gitleaks.toml
+
+func main() {
+ if len(os.Args) < 2 {
+ _, _ = os.Stderr.WriteString("Specify path to the gitleaks.toml config\n")
+ os.Exit(2)
+ }
+ gitleaksConfigPath := os.Args[1]
+
+ configRules := []*config.Rule{
+ rules.OnePasswordSecretKey(),
+ rules.OnePasswordServiceAccountToken(),
+ rules.AdafruitAPIKey(),
+ rules.AdobeClientID(),
+ rules.AdobeClientSecret(),
+ rules.AgeSecretKey(),
+ rules.AirtableApiKey(),
+ rules.AirtablePersonalAccessToken(),
+ rules.AlgoliaApiKey(),
+ rules.AlibabaAccessKey(),
+ rules.AlibabaSecretKey(),
+ rules.AmazonBedrockAPIKeyLongLived(),
+ rules.AmazonBedrockAPIKeyShortLived(),
+ rules.AnthropicAdminApiKey(),
+ rules.AnthropicApiKey(),
+ rules.ArtifactoryApiKey(),
+ rules.ArtifactoryReferenceToken(),
+ rules.AsanaClientID(),
+ rules.AsanaClientSecret(),
+ rules.Atlassian(),
+ rules.Authress(),
+ rules.AWS(),
+ rules.AzureActiveDirectoryClientSecret(),
+ rules.BitBucketClientID(),
+ rules.BitBucketClientSecret(),
+ rules.BittrexAccessKey(),
+ rules.BittrexSecretKey(),
+ rules.Beamer(),
+ rules.CodecovAccessToken(),
+ rules.CoinbaseAccessToken(),
+ rules.ClickHouseCloud(),
+ rules.Clojars(),
+ rules.CloudflareAPIKey(),
+ rules.CloudflareGlobalAPIKey(),
+ rules.CloudflareOriginCAKey(),
+ rules.CohereAPIToken(),
+ rules.ConfluentAccessToken(),
+ rules.ConfluentSecretKey(),
+ rules.Contentful(),
+ rules.CurlHeaderAuth(),
+ rules.CurlBasicAuth(),
+ rules.Databricks(),
+ rules.DatadogtokenAccessToken(),
+ rules.DefinedNetworkingAPIToken(),
+ rules.DigitalOceanPAT(),
+ rules.DigitalOceanOAuthToken(),
+ rules.DigitalOceanRefreshToken(),
+ rules.DiscordAPIToken(),
+ rules.DiscordClientID(),
+ rules.DiscordClientSecret(),
+ rules.Doppler(),
+ rules.DropBoxAPISecret(),
+ rules.DropBoxLongLivedAPIToken(),
+ rules.DropBoxShortLivedAPIToken(),
+ rules.DroneciAccessToken(),
+ rules.Duffel(),
+ rules.Dynatrace(),
+ rules.EasyPost(),
+ rules.EasyPostTestAPI(),
+ rules.EtsyAccessToken(),
+ rules.FacebookSecret(),
+ rules.FacebookAccessToken(),
+ rules.FacebookPageAccessToken(),
+ rules.FastlyAPIToken(),
+ rules.FinicityClientSecret(),
+ rules.FinicityAPIToken(),
+ rules.FlickrAccessToken(),
+ rules.FinnhubAccessToken(),
+ rules.FlutterwavePublicKey(),
+ rules.FlutterwaveSecretKey(),
+ rules.FlutterwaveEncKey(),
+ rules.FlyIOAccessToken(),
+ rules.FrameIO(),
+ rules.Freemius(),
+ rules.FreshbooksAccessToken(),
+ rules.GoCardless(),
+ // TODO figure out what makes sense for GCP
+ // rules.GCPServiceAccount(),
+ rules.GCPAPIKey(),
+ rules.GitHubPat(),
+ rules.GitHubFineGrainedPat(),
+ rules.GitHubOauth(),
+ rules.GitHubApp(),
+ rules.GitHubRefresh(),
+ rules.GitlabCiCdJobToken(),
+ rules.GitlabDeployToken(),
+ rules.GitlabFeatureFlagClientToken(),
+ rules.GitlabFeedToken(),
+ rules.GitlabIncomingMailToken(),
+ rules.GitlabKubernetesAgentToken(),
+ rules.GitlabOauthAppSecret(),
+ rules.GitlabPat(),
+ rules.GitlabPatRoutable(),
+ rules.GitlabPipelineTriggerToken(),
+ rules.GitlabRunnerRegistrationToken(),
+ rules.GitlabRunnerAuthenticationToken(),
+ rules.GitlabRunnerAuthenticationTokenRoutable(),
+ rules.GitlabScimToken(),
+ rules.GitlabSessionCookie(),
+ rules.GitterAccessToken(),
+ rules.GrafanaApiKey(),
+ rules.GrafanaCloudApiToken(),
+ rules.GrafanaServiceAccountToken(),
+ rules.HarnessApiKey(),
+ rules.HashiCorpTerraform(),
+ rules.HashicorpField(),
+ rules.Heroku(),
+ rules.HerokuV2(),
+ rules.HubSpot(),
+ rules.HuggingFaceAccessToken(),
+ rules.HuggingFaceOrganizationApiToken(),
+ rules.Intercom(),
+ rules.Intra42ClientSecret(),
+ rules.JFrogAPIKey(),
+ rules.JFrogIdentityToken(),
+ rules.JWT(),
+ rules.JWTBase64(),
+ rules.KrakenAccessToken(),
+ rules.KubernetesSecret(),
+ rules.KucoinAccessToken(),
+ rules.KucoinSecretKey(),
+ rules.LaunchDarklyAccessToken(),
+ rules.LinearAPIToken(),
+ rules.LinearClientSecret(),
+ rules.LinkedinClientID(),
+ rules.LinkedinClientSecret(),
+ rules.LobAPIToken(),
+ rules.LobPubAPIToken(),
+ rules.LookerClientID(),
+ rules.LookerClientSecret(),
+ rules.MailChimp(),
+ rules.MailGunPubAPIToken(),
+ rules.MailGunPrivateAPIToken(),
+ rules.MailGunSigningKey(),
+ rules.MapBox(),
+ rules.MattermostAccessToken(),
+ rules.MaxMindLicenseKey(),
+ rules.Meraki(),
+ rules.MessageBirdAPIToken(),
+ rules.MessageBirdClientID(),
+ rules.NetlifyAccessToken(),
+ rules.NewRelicUserID(),
+ rules.NewRelicUserKey(),
+ rules.NewRelicBrowserAPIKey(),
+ rules.NewRelicInsertKey(),
+ rules.Notion(),
+ rules.NPM(),
+ rules.NugetConfigPassword(),
+ rules.NytimesAccessToken(),
+ rules.OctopusDeployApiKey(),
+ rules.OktaAccessToken(),
+ rules.OpenAI(),
+ rules.OpenshiftUserToken(),
+ rules.PerplexityAPIKey(),
+ rules.PlaidAccessID(),
+ rules.PlaidSecretKey(),
+ rules.PlaidAccessToken(),
+ rules.PlanetScalePassword(),
+ rules.PlanetScaleAPIToken(),
+ rules.PlanetScaleOAuthToken(),
+ rules.PostManAPI(),
+ rules.Prefect(),
+ rules.PrivateAIToken(),
+ rules.PrivateKey(),
+ rules.PrivateKeyPKCS12File(),
+ rules.PulumiAPIToken(),
+ rules.PyPiUploadToken(),
+ rules.RapidAPIAccessToken(),
+ rules.ReadMe(),
+ rules.RubyGemsAPIToken(),
+ rules.ScalingoAPIToken(),
+ rules.SendbirdAccessID(),
+ rules.SendbirdAccessToken(),
+ rules.SendGridAPIToken(),
+ rules.SendInBlueAPIToken(),
+ rules.SentryAccessToken(),
+ rules.SentryOrgToken(),
+ rules.SentryUserToken(),
+ rules.SettlemintApplicationAccessToken(),
+ rules.SettlemintPersonalAccessToken(),
+ rules.SettlemintServiceAccessToken(),
+ rules.ShippoAPIToken(),
+ rules.ShopifyAccessToken(),
+ rules.ShopifyCustomAccessToken(),
+ rules.ShopifyPrivateAppAccessToken(),
+ rules.ShopifySharedSecret(),
+ rules.SidekiqSecret(),
+ rules.SidekiqSensitiveUrl(),
+ rules.SlackBotToken(),
+ rules.SlackUserToken(),
+ rules.SlackAppLevelToken(),
+ rules.SlackConfigurationToken(),
+ rules.SlackConfigurationRefreshToken(),
+ rules.SlackLegacyBotToken(),
+ rules.SlackLegacyWorkspaceToken(),
+ rules.SlackLegacyToken(),
+ rules.SlackWebHookUrl(),
+ rules.Snyk(),
+ rules.Sonar(),
+ rules.SourceGraph(),
+ rules.StripeAccessToken(),
+ rules.SquareAccessToken(),
+ rules.SquareSpaceAccessToken(),
+ rules.SumoLogicAccessID(),
+ rules.SumoLogicAccessToken(),
+ rules.TeamsWebhook(),
+ rules.TelegramBotToken(),
+ rules.TravisCIAccessToken(),
+ rules.Twilio(),
+ rules.TwitchAPIToken(),
+ rules.TwitterAPIKey(),
+ rules.TwitterAPISecret(),
+ rules.TwitterAccessToken(),
+ rules.TwitterAccessSecret(),
+ rules.TwitterBearerToken(),
+ rules.Typeform(),
+ rules.VaultBatchToken(),
+ rules.VaultServiceToken(),
+ rules.YandexAPIKey(),
+ rules.YandexAWSAccessToken(),
+ rules.YandexAccessToken(),
+ rules.ZendeskSecretKey(),
+ rules.GenericCredential(),
+ rules.InfracostAPIToken(),
+ }
+
+ // ensure rules have unique ids
+ ruleLookUp := make(map[string]config.Rule, len(configRules))
+ for _, rule := range configRules {
+ if err := rule.Validate(); err != nil {
+ logging.Fatal().Err(err).
+ Str("rule-id", rule.RuleID).
+ Msg("Failed to validate rule")
+ }
+
+ // check if rule is in ruleLookUp
+ if _, ok := ruleLookUp[rule.RuleID]; ok {
+ logging.Fatal().
+ Str("rule-id", rule.RuleID).
+ Msg("rule id is not unique")
+ }
+ // TODO: eventually change all the signatures to get ride of this
+ // nasty dereferencing.
+ ruleLookUp[rule.RuleID] = *rule
+
+ // Slices are de-duplicated with a map, every iteration has a different order.
+ // This is an awkward workaround.
+ for _, allowlist := range rule.Allowlists {
+ slices.Sort(allowlist.Commits)
+ slices.Sort(allowlist.StopWords)
+ }
+ }
+
+ tmpl, err := template.ParseFiles(templatePath)
+ if err != nil {
+ logging.Fatal().Err(err).Msg("Failed to parse template")
+ }
+
+ f, err := os.Create(gitleaksConfigPath)
+ if err != nil {
+ logging.Fatal().Err(err).Msg("Failed to create rules.toml")
+ }
+ defer f.Close()
+
+ cfg := base.CreateGlobalConfig()
+ cfg.Rules = ruleLookUp
+ for _, allowlist := range cfg.Allowlists {
+ slices.Sort(allowlist.Commits)
+ slices.Sort(allowlist.StopWords)
+ }
+ if err = tmpl.Execute(f, cfg); err != nil {
+ logging.Fatal().Err(err).Msg("could not execute template")
+ }
+}
diff --git a/cmd/generate/config/rules/1password.go b/cmd/generate/config/rules/1password.go
new file mode 100644
index 0000000..fe78072
--- /dev/null
+++ b/cmd/generate/config/rules/1password.go
@@ -0,0 +1,81 @@
+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"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+// https://developer.1password.com/docs/service-accounts/security/?token-example=encoded
+func OnePasswordServiceAccountToken() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "1password-service-account-token",
+ Description: "Uncovered a possible 1Password service account token, potentially compromising access to secrets in vaults.",
+ Regex: regexp.MustCompile(`ops_eyJ[a-zA-Z0-9+/]{250,}={0,3}`),
+ Entropy: 4,
+ Keywords: []string{"ops_"},
+ }
+
+ // validate
+ tps := []string{
+ utils.GenerateSampleSecret("1password", secrets.NewSecret(`ops_eyJ[a-zA-Z0-9+/]{250,}={0,3}`)),
+ `### 1Password System Vault Name
+export OP_SERVICE_ACCOUNT_TOKEN=ops_eyJzaWduSW5BZGRyZXNzIjoibXkuMXBhc3N3b3JkLmNvbSIsInVzZXJBdXRoIjp7Im1ldGhvZCI6IlNSUGctNDA5NiIsImFsZyI6IlBCRVMyZy1IUzI1NiIsIml0ZXJhdGlvbnMiOjY1MdAwMCwic2FsdCI6InE2dE0tYzNtRDhiNUp2OHh1YVzsUmcifSwiZW1haWwiOiJ5Z3hmcm0zb21oY3NtQDFwYXNzd29yZHNlcnZpY2VhY2NvdW50cy5jb20iLCJzcnBYIjoiM2E5NDdhZmZhMDQ5NTAxZjkxYzk5MGFiY2JiYWRlZjFjMjM5Y2Q3YTMxYmI1MmQyZjUzOTA2Y2UxOTA1OTYwYiIsIm11ayI6eyJhbGciOiJBMjU2R0NNIiwiZXh0Ijp0cnVlLCJrIjoiVVpleERsLVgyUWxpa0VqRjVUUjRoODhOd29ZcHRqSHptQmFTdlNrWGZmZyIsImtleV9vcHMiOlsiZW5jcnlwdCIsImRlY3J5cHQiXSwia3R5Ijoib2N0Iiwia2lkIjoibXAifSwic2VjcmV0S2V5IjoiQTMtNDZGUUVNLUVZS1hTQS1NUU0yUy04U0JSUS01QjZGUC1HS1k2ViIsInRocm90dGxlU2VjcmV0Ijp7InNlZWQiOiJjZmU2ZTU0NGUxZTlmY2NmZjJlYjBhYWZmYTEzNjZlMmE2ZmUwZDVlZGI2ZTUzOTVkZTljZmY0NDY3NDUxOGUxIiwidXVpZCI6IjNVMjRMNVdCNkpFQ0pEQlhJNFZOSTRCUzNRIn0sImRldmljZVV1aWQiOiJqaGVlY3F4cm41YTV6ZzRpMnlkbjRqd3U3dSJ9
+`,
+ `PYTEST_SVC_ACCT_TOKEN=ops_eyJzaWduSW5BZGRyZXNzIjoiemFjaC1hbmQtbGVhbm5lLjFwYXNzd29yZC5jb20iLCJ1c2VyQXV0aCI6eyJtZXRob2QiOiJTUlBnLTQwOTYiLCJhbGciOiJQQkVLMmctSFMyNTYiLCJpdGVyYXRpb25zIjo2NTAwMDAsInNhbHQiOiJlYUZRQmNVemJyTHhnM2d4bHFQLVVBIn0sImVtYWlsIjoiMm9iNGRpeDdiNTdrYUAxcGFzc3dvcmRzZXJ2aWNlYWNjb3VudHMuY29tIiwic3JwWCI6ImVmZDY4YjNhZTkwMmRjZjRiMzEzYjE5MjYwZmY0OGUzMjU2ZDlhOGNkM2JmMmY3YzI2YzU1ZWJkNjZlZGU4NWEiLCJtdWsiOnsiYWxnIjoiQTI1NkdDTSIsImV4dCI6dHJ1ZSwiayI6IlMwaGE0SDhqbEhRblJCWmxvYnBmR1BneERmbS1pRGNkZWY0bFdYU0VSbmMiLCJrZXlfb3BzIjpbImRlY3J5cHQiLCJlbmNyeXB0Il0sImt0eSI6Im9jdCIsImtpZCI6Im1wIn0sInNlY3JldEtleSI6IkEzLUdHOUVRNi1LUzQ0QVctQU5QVkYtUkdQTDktQlNKUTMtR1NHR0giLCJ0aHJvdHRsZVNlY3JldCI6eyJzZWVkIjoiN2I0OTMxMmJiOTlkZTFiNjU5ODZkYzIzOWU4YWNmZWMxMTU0M2E2OGQxYmYwMjZmZTgzMjg3NWYxNmJlOWY2NiIsInV1aWQiOiJDV1RHQ0hMNlNWRkdSTlg0SzNENUJVSDZDSSJ9LCJkZXZpY2VVdWlkIjoiMnFld3JpaGtqbmt1Zmh6ZGdmZ2hnNmM1cGUifQ`,
+ ` "sourceContent": "ops_eyJlbWFpbCI6ImVqd2U2NHFtbHhocmlAMXBhc3N3b3Jkc2VydmljZWFjY291bnRzLmxjbCIsIm11ayI6eyJhbGciOiJBMjU2R0NNIiwiZXh0Ijp0cnVlLCJrIjoiTThWUGZJYzhWRWZUaGNNWExhS0NLRjhzTWg1Sk1ac1BBdHU5MmZRTmItbyIsImtleV9vcHMiOlsiZW5jcnlwdCIsImRlY3J5cHQiXSwia3R5Ijoib2N0Iiwia2lkIjoibXAifSwic2VjcmV0S2V5IjoiQTMtQzRaSk1OLVBRVFpUTC1IR0w4NC1HNjRNNy1LVlpSTi00WlZQNiIsInNycFgiOiI4NzBkNjdhOWU2MjY2MjVkOWUzNjg1MDc4MDRjOWMzMmU2NjFjNTdlN2U1NTg3NzgyOTFiZjI5ZDVhMjc5YWUxIiwic2lnbkluQWRkcmVzcyI6ImdvdGhhbS5iNWxvY2FsLmNvbTo0MDAwIiwidXNlckF1dGgiOnsibWV0aG9kIjoiU1JQZy00MDk2IiwiYWxnIjoiUEJFUzJnLUhTMjU2IiwiaXRlcmF0aW9ucyI6MTAwMDAwLCJzYWx0IjoiRk1SVVBpeXJONFhmXzhIb2g2WVJYUSJ9fQ\n\nops_token is secret.\n",`,
+ }
+ fps := []string{
+ // Invalid
+ ` login:
+ serviceAccountToken:
+ fn::secret: ops_eyJzaWduSW5B..[Redacted]`,
+ `: To start using this service account, run the following command:
+:
+: export OP_SERVICE_ACCOUNT_TOKEN=ops_eyJzaWduSW5BZGRyZXNzIjoiaHR0cHM6...`,
+ // Low entropy.
+ `ops_eyJxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`,
+ }
+ return utils.Validate(r, tps, fps)
+}
+
+// Reference:
+// - https://1passwordstatic.com/files/security/1password-white-paper.pdf
+func OnePasswordSecretKey() *config.Rule {
+ // 1Password secret keys include several hyphens but these are only for readability
+ // and are stripped during 1Password login. This means that the following are technically
+ // the same valid key:
+ // - A3ASWWYB798JRYLJVD423DC286TVMH43EB
+ // - A-3-A-S-W-W-Y-B-7-9-8-J-R-Y-L-J-V-D-4-2-3-D-C-2-8-6-T-V-M-H-4-3-E-B
+ // But in practice, when these keys are added to a vault, exported in an emergency kit, or
+ // copied, they have hyphens that follow one of two patterns I can find:
+ // - A3-ASWWYB-798JRY-LJVD4-23DC2-86TVM-H43EB (every key I've generated has this pattern)
+ // - A3-ASWWYB-798JRYLJVD4-23DC2-86TVM-H43EB (the whitepaper includes this example, which could just be a typo)
+ // To avoid a complicated regex that checks for every possible situation it's probably best
+ // to scan for the these two patterns.
+ r := config.Rule{
+ Description: "Uncovered a possible 1Password secret key, potentially compromising access to secrets in vaults.",
+ RuleID: "1password-secret-key",
+ Regex: regexp.MustCompile(`\bA3-[A-Z0-9]{6}-(?:(?:[A-Z0-9]{11})|(?:[A-Z0-9]{6}-[A-Z0-9]{5}))-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}\b`),
+ Entropy: 3.8,
+ Keywords: []string{"A3-"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("1password", secrets.NewSecret(`A3-[A-Z0-9]{6}-[A-Z0-9]{11}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}`))
+ tps = append(tps, utils.GenerateSampleSecrets("1password", secrets.NewSecret(`A3-[A-Z0-9]{6}-[A-Z0-9]{6}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}`))...)
+ tps = append(tps,
+ // from whitepaper
+ `A3-ASWWYB-798JRYLJVD4-23DC2-86TVM-H43EB`,
+ `A3-ASWWYB-798JRY-LJVD4-23DC2-86TVM-H43EB`,
+ )
+ fps := []string{
+ // low entropy
+ `A3-XXXXXX-XXXXXXXXXXX-XXXXX-XXXXX-XXXXX`,
+ // lowercase
+ `A3-xXXXXX-XXXXXX-XXXXX-XXXXX-XXXXX-XXXXX`,
+ }
+ return utils.Validate(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/adafruit.go b/cmd/generate/config/rules/adafruit.go
new file mode 100644
index 0000000..b769205
--- /dev/null
+++ b/cmd/generate/config/rules/adafruit.go
@@ -0,0 +1,21 @@
+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"
+)
+
+func AdafruitAPIKey() *config.Rule {
+ // define 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: utils.GenerateSemiGenericRegex([]string{"adafruit"}, utils.AlphaNumericExtendedShort("32"), true),
+ Keywords: []string{"adafruit"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("adafruit", secrets.NewSecret(utils.AlphaNumericExtendedShort("32")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/adobe.go b/cmd/generate/config/rules/adobe.go
new file mode 100644
index 0000000..1287b04
--- /dev/null
+++ b/cmd/generate/config/rules/adobe.go
@@ -0,0 +1,39 @@
+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"
+)
+
+func AdobeClientID() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "adobe-client-id",
+ Description: "Detected a pattern that resembles an Adobe OAuth Web Client ID, posing a risk of compromised Adobe integrations and data breaches.",
+ Regex: utils.GenerateSemiGenericRegex([]string{"adobe"}, utils.Hex("32"), true),
+ Entropy: 2,
+ Keywords: []string{"adobe"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("adobe", secrets.NewSecret(utils.Hex("32")))
+ return utils.Validate(r, tps, nil)
+}
+
+func AdobeClientSecret() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "adobe-client-secret",
+ Description: "Discovered a potential Adobe Client Secret, which, if exposed, could allow unauthorized Adobe service access and data manipulation.",
+ Regex: utils.GenerateUniqueTokenRegex(`p8e-(?i)[a-z0-9]{32}`, false),
+ Entropy: 2,
+ Keywords: []string{"p8e-"},
+ }
+
+ // validate
+ tps := []string{
+ "adobeClient := \"p8e-" + secrets.NewSecret(utils.Hex("32")) + "\"",
+ }
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/age.go b/cmd/generate/config/rules/age.go
new file mode 100644
index 0000000..6908aa7
--- /dev/null
+++ b/cmd/generate/config/rules/age.go
@@ -0,0 +1,21 @@
+package rules
+
+import (
+ "github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
+ "github.com/zricethezav/gitleaks/v8/config"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+func AgeSecretKey() *config.Rule {
+ // define rule
+ r := config.Rule{
+ Description: "Discovered a potential Age encryption tool secret key, risking data decryption and unauthorized access to sensitive information.",
+ RuleID: "age-secret-key",
+ Regex: regexp.MustCompile(`AGE-SECRET-KEY-1[QPZRY9X8GF2TVDW0S3JN54KHCE6MUA7L]{58}`),
+ Keywords: []string{"AGE-SECRET-KEY-1"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("age", `AGE-SECRET-KEY-1QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ`) // gitleaks:allow
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/airtable.go b/cmd/generate/config/rules/airtable.go
new file mode 100644
index 0000000..354ad19
--- /dev/null
+++ b/cmd/generate/config/rules/airtable.go
@@ -0,0 +1,37 @@
+package rules
+
+import (
+ "regexp"
+
+ "github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
+ "github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
+ "github.com/zricethezav/gitleaks/v8/config"
+)
+
+func AirtableApiKey() *config.Rule {
+ // define 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: utils.GenerateSemiGenericRegex([]string{"airtable"}, utils.AlphaNumeric("17"), true),
+ Keywords: []string{"airtable"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("airtable", secrets.NewSecret(utils.AlphaNumeric("17")))
+ return utils.Validate(r, tps, nil)
+}
+
+func AirtablePersonalAccessToken() *config.Rule {
+ // define rule
+ r := config.Rule{
+ Description: "Uncovered a possible Airtable Personal AccessToken, potentially compromising database access and leading to data leakage or alteration.",
+ RuleID: "airtable-personnal-access-token",
+ Regex: regexp.MustCompile(`\b(pat[[:alnum:]]{14}\.[a-f0-9]{64})\b`),
+ Keywords: []string{"airtable"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("airtable", "pat"+secrets.NewSecret(utils.AlphaNumeric("14")+"\\."+utils.Hex("64")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/algolia.go b/cmd/generate/config/rules/algolia.go
new file mode 100644
index 0000000..03b5058
--- /dev/null
+++ b/cmd/generate/config/rules/algolia.go
@@ -0,0 +1,21 @@
+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"
+)
+
+func AlgoliaApiKey() *config.Rule {
+ // define 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: utils.GenerateSemiGenericRegex([]string{"algolia"}, `[a-z0-9]{32}`, true),
+ Keywords: []string{"algolia"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("algolia", secrets.NewSecret(utils.Hex("32")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/alibaba.go b/cmd/generate/config/rules/alibaba.go
new file mode 100644
index 0000000..67d5739
--- /dev/null
+++ b/cmd/generate/config/rules/alibaba.go
@@ -0,0 +1,40 @@
+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"
+)
+
+func AlibabaAccessKey() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "alibaba-access-key-id",
+ Description: "Detected an Alibaba Cloud AccessKey ID, posing a risk of unauthorized cloud resource access and potential data compromise.",
+ Regex: utils.GenerateUniqueTokenRegex(`LTAI(?i)[a-z0-9]{20}`, false),
+ Entropy: 2,
+ Keywords: []string{"LTAI"},
+ }
+
+ // validate
+ tps := []string{
+ "alibabaKey := \"LTAI" + secrets.NewSecret(utils.Hex("20")) + "\"",
+ }
+ return utils.Validate(r, tps, nil)
+}
+
+// TODO
+func AlibabaSecretKey() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "alibaba-secret-key",
+ Description: "Discovered a potential Alibaba Cloud Secret Key, potentially allowing unauthorized operations and data access within Alibaba Cloud.",
+ Regex: utils.GenerateSemiGenericRegex([]string{"alibaba"}, utils.AlphaNumeric("30"), true),
+ Entropy: 2,
+ Keywords: []string{"alibaba"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("alibaba", secrets.NewSecret(utils.AlphaNumeric("30")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/anthropic.go b/cmd/generate/config/rules/anthropic.go
new file mode 100644
index 0000000..a3d956e
--- /dev/null
+++ b/cmd/generate/config/rules/anthropic.go
@@ -0,0 +1,69 @@
+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"
+)
+
+func AnthropicApiKey() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "anthropic-api-key",
+ Description: "Identified an Anthropic API Key, which may compromise AI assistant integrations and expose sensitive data to unauthorized access.",
+ Regex: utils.GenerateUniqueTokenRegex(`sk-ant-api03-[a-zA-Z0-9_\-]{93}AA`, false),
+ Keywords: []string{
+ "sk-ant-api03",
+ },
+ }
+
+ // validate
+ tps := []string{
+ // Valid API key example
+ "sk-ant-api03-abc123xyz-456def789ghij-klmnopqrstuvwx-3456yza789bcde-1234fghijklmnopby56aaaogaopaaaabc123xyzAA",
+ // Generate additional random test keys
+ utils.GenerateSampleSecret("anthropic", "sk-ant-api03-"+secrets.NewSecret(utils.AlphaNumericExtendedShort("93"))+"AA"),
+ }
+
+ fps := []string{
+ // Too short key (missing characters)
+ "sk-ant-api03-abc123xyz-456de-klMnopqrstuvwx-3456yza789bcde-1234fghijklmnopAA",
+ // Wrong suffix
+ "sk-ant-api03-abc123xyz-456def789ghij-klmnopqrstuvwx-3456yza789bcde-1234fghijklmnopby56aaaogaopaaaabc123xyzBB",
+ // Wrong prefix (admin key, not API key)
+ "sk-ant-admin01-abc123xyz-456def789ghij-klmnopqrstuvwx-3456yza789bcde-1234fghijklmnopby56aaaogaopaaaabc123xyzAA",
+ }
+
+ return utils.Validate(r, tps, fps)
+}
+
+func AnthropicAdminApiKey() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "anthropic-admin-api-key",
+ Description: "Detected an Anthropic Admin API Key, risking unauthorized access to administrative functions and sensitive AI model configurations.",
+ Regex: utils.GenerateUniqueTokenRegex(`sk-ant-admin01-[a-zA-Z0-9_\-]{93}AA`, false),
+ Keywords: []string{
+ "sk-ant-admin01",
+ },
+ }
+
+ // validate
+ tps := []string{
+ // Valid admin key example
+ "sk-ant-admin01-abc12fake-456def789ghij-klmnopqrstuvwx-3456yza789bcde-12fakehijklmnopby56aaaogaopaaaabc123xyzAA",
+ // Generate additional random test keys
+ utils.GenerateSampleSecret("anthropic", "sk-ant-admin01-"+secrets.NewSecret(utils.AlphaNumericExtendedShort("93"))+"AA"),
+ }
+
+ fps := []string{
+ // Too short key (missing characters)
+ "sk-ant-admin01-abc123xyz-456de-klMnopqrstuvwx-3456yza789bcde-1234fghijklmnopAA",
+ // Wrong suffix
+ "sk-ant-admin01-abc123xyz-456def789ghij-klmnopqrstuvwx-3456yza789bcde-1234fghijklmnopby56aaaogaopaaaabc123xyzBB",
+ // Wrong prefix (API key, not admin key)
+ "sk-ant-api03-abc123xyz-456def789ghij-klmnopqrstuvwx-3456yza789bcde-1234fghijklmnopby56aaaogaopaaaabc123xyzAA",
+ }
+
+ return utils.Validate(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/artifactory.go b/cmd/generate/config/rules/artifactory.go
new file mode 100644
index 0000000..63c5ec8
--- /dev/null
+++ b/cmd/generate/config/rules/artifactory.go
@@ -0,0 +1,58 @@
+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"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+func ArtifactoryApiKey() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "artifactory-api-key",
+ Description: "Detected an Artifactory api key, posing a risk unauthorized access to the central repository.",
+ Regex: regexp.MustCompile(`\bAKCp[A-Za-z0-9]{69}\b`),
+ Entropy: 4.5,
+ Keywords: []string{"AKCp"},
+ }
+
+ // validate
+ tps := []string{
+ "artifactoryApiKey := \"AKCp" + secrets.NewSecret(utils.AlphaNumeric("69")) + "\"",
+ }
+ // false positives
+ fps := []string{
+ `lowEntropy := AKCpXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX`,
+ "wrongStart := \"AkCp" + secrets.NewSecret(utils.AlphaNumeric("69")) + "\"",
+ "wrongLength := \"AkCp" + secrets.NewSecret(utils.AlphaNumeric("59")) + "\"",
+ "partOfAlongUnrelatedBlob gYnkgAkCp" + secrets.NewSecret(utils.AlphaNumeric("69")) + "VyZSB2",
+ }
+
+ return utils.Validate(r, tps, fps)
+}
+
+func ArtifactoryReferenceToken() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "artifactory-reference-token",
+ Description: "Detected an Artifactory reference token, posing a risk of impersonation and unauthorized access to the central repository.",
+ Regex: regexp.MustCompile(`\bcmVmd[A-Za-z0-9]{59}\b`),
+ Entropy: 4.5,
+ Keywords: []string{"cmVmd"},
+ }
+
+ // validate
+ tps := []string{
+ "artifactoryRefToken := \"cmVmd" + secrets.NewSecret(utils.AlphaNumeric("59")) + "\"",
+ }
+ // false positives
+ fps := []string{
+ `lowEntropy := cmVmdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX`,
+ "wrongStart := \"cmVMd" + secrets.NewSecret(utils.AlphaNumeric("59")) + "\"",
+ "wrongLength := \"cmVmd" + secrets.NewSecret(utils.AlphaNumeric("49")) + "\"",
+ "partOfAlongUnrelatedBlob gYnkgcmVmd" + secrets.NewSecret(utils.AlphaNumeric("59")) + "VyZSB2",
+ }
+
+ return utils.Validate(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/asana.go b/cmd/generate/config/rules/asana.go
new file mode 100644
index 0000000..def28ce
--- /dev/null
+++ b/cmd/generate/config/rules/asana.go
@@ -0,0 +1,36 @@
+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"
+)
+
+func AsanaClientID() *config.Rule {
+ // define 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: utils.GenerateSemiGenericRegex([]string{"asana"}, utils.Numeric("16"), true),
+ Keywords: []string{"asana"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("asana", secrets.NewSecret(utils.Numeric("16")))
+ return utils.Validate(r, tps, nil)
+}
+
+func AsanaClientSecret() *config.Rule {
+ // define 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: utils.GenerateSemiGenericRegex([]string{"asana"}, utils.AlphaNumeric("32"), true),
+
+ Keywords: []string{"asana"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("asana", secrets.NewSecret(utils.AlphaNumeric("32")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/atlassian.go b/cmd/generate/config/rules/atlassian.go
new file mode 100644
index 0000000..ba8b4cb
--- /dev/null
+++ b/cmd/generate/config/rules/atlassian.go
@@ -0,0 +1,36 @@
+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"
+)
+
+func Atlassian() *config.Rule {
+ // define 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: utils.MergeRegexps(
+ utils.GenerateSemiGenericRegex(
+ []string{"(?-i:ATLASSIAN|[Aa]tlassian)", "(?-i:CONFLUENCE|[Cc]onfluence)", "(?-i:JIRA|[Jj]ira)"},
+ `[a-z0-9]{20}[a-f0-9]{4}`, // The last 4 characters are an MD5 hash.
+ true,
+ ),
+ utils.GenerateUniqueTokenRegex(`ATATT3[A-Za-z0-9_\-=]{186}`, false),
+ ),
+ Entropy: 3.5,
+ Keywords: []string{"atlassian", "confluence", "jira", "atatt3"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("atlassian", secrets.NewSecret(utils.AlphaNumeric("20")+"[a-f0-9]{4}"))
+ tps = append(tps, utils.GenerateSampleSecrets("confluence", secrets.NewSecret(utils.AlphaNumeric("20")+"[a-f0-9]{4}"))...)
+ tps = append(tps, utils.GenerateSampleSecrets("jira", secrets.NewSecret(utils.AlphaNumeric("20")+"[a-f0-9]{4}"))...)
+ tps = append(tps, `JIRA_API_TOKEN=HXe8DGg1iJd2AopzyxkFB7F2`)
+ tps = append(tps, utils.GenerateSampleSecrets("jira", "ATATT3xFfGF0K3irG5tKKi-6u-wwaXQFeGwZ-IHR-hQ3CulkKtMSuteRQFfLZ6jihHThzZCg_UjnDt-4Wl_gIRf4zrZJs5JqaeuBhsfJ4W5GD6yGg3W7903gbvaxZPBjxIQQ7BgFDSkPS8oPispw4KLz56mdK-G6CIvLO6hHRrZHY0Q3tvJ6JxE=C63992E6")...)
+
+ fps := []string{"getPagesInConfluenceSpace,searchConfluenceUsingCql"}
+
+ return utils.Validate(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/authress.go b/cmd/generate/config/rules/authress.go
new file mode 100644
index 0000000..c304332
--- /dev/null
+++ b/cmd/generate/config/rules/authress.go
@@ -0,0 +1,31 @@
+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"
+)
+
+func Authress() *config.Rule {
+ // Rule Definition
+ // (Note: When changes are made to this, rerun `go generate ./...` and commit the config/gitleaks.toml file
+ r := config.Rule{
+ RuleID: "authress-service-client-access-key",
+ Description: "Uncovered a possible Authress Service Client Access Key, which may compromise access control services and sensitive data.",
+ Regex: utils.GenerateUniqueTokenRegex(`(?:sc|ext|scauth|authress)_(?i)[a-z0-9]{5,30}\.[a-z0-9]{4,6}\.(?-i:acc)[_-][a-z0-9-]{10,32}\.[a-z0-9+/_=-]{30,120}`, false),
+ Entropy: 2,
+ Keywords: []string{"sc_", "ext_", "scauth_", "authress_"},
+ }
+
+ // validate
+ // https://authress.io/knowledge-base/docs/authorization/service-clients/secrets-scanning/#1-detection
+ 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 := utils.GenerateSampleSecrets("authress", secrets.NewSecret(fmt.Sprintf(`%s\.%s\.%s\.%s`, service_client_id, access_key_id, account_id, signature_key)))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/aws.go b/cmd/generate/config/rules/aws.go
new file mode 100644
index 0000000..545fd68
--- /dev/null
+++ b/cmd/generate/config/rules/aws.go
@@ -0,0 +1,109 @@
+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"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+func AWS() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "aws-access-token",
+ Description: "Identified a pattern that may indicate AWS credentials, risking unauthorized cloud resource access and data breaches on AWS platforms.",
+ Regex: regexp.MustCompile(`\b((?:A3T[A-Z0-9]|AKIA|ASIA|ABIA|ACCA)[A-Z2-7]{16})\b`),
+ Entropy: 3,
+ Keywords: []string{
+ // https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-unique-ids
+ "A3T", // todo: might not be a valid AWS token
+ "AKIA", // Access key
+ "ASIA", // Temporary (AWS STS) access key
+ "ABIA", // AWS STS service bearer token
+ "ACCA", // Context-specific credential
+ },
+ Allowlists: []*config.Allowlist{
+ {
+ Regexes: []*regexp.Regexp{
+ regexp.MustCompile(`.+EXAMPLE$`),
+ },
+ },
+ },
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("AWS", "AKIALALEMEL33243OLIB") // gitleaks:allow
+ // current AWS tokens cannot contain [0,1,8,9], so their entropy is slightly lower than expected.
+ tps = append(tps, utils.GenerateSampleSecrets("AWS", "AKIA"+secrets.NewSecret("[A-Z2-7]{16}"))...)
+ tps = append(tps, utils.GenerateSampleSecrets("AWS", "ASIA"+secrets.NewSecret("[A-Z2-7]{16}"))...)
+ tps = append(tps, utils.GenerateSampleSecrets("AWS", "ABIA"+secrets.NewSecret("[A-Z2-7]{16}"))...)
+ tps = append(tps, utils.GenerateSampleSecrets("AWS", "ACCA"+secrets.NewSecret("[A-Z2-7]{16}"))...)
+ fps := []string{
+ `key = AKIAXXXXXXXXXXXXXXXX`, // Low entropy
+ `aws_access_key: AKIAIOSFODNN7EXAMPLE`, // Placeholder
+ `msgstr "Näytä asiakirjamallikansio."`, // Lowercase
+ `TODAYINASIAASACKOFRICEFELLOVER`, // wrong length
+ `CTTCATAGGGTTCACGCTGTGTAAT-ACG--CCTGAGGC-CACA-AGGGGACTTCAGCAACCGTCGGG-GATTC-ATTGCCA-A--TGGAAGCAATC-TA-TGGGTTA-TCGCGGAGTCCGCAAAGACGGCCAGTATG-AAGCAGATTTCGCAC-CAATGTGACTGCATTTCGTG-ATCGGGGTAAGTA-TC-GCCGATTC-GC--CCGTCCA-AGT-CGAAG-TA--GGCAATATAAAGCTGC-CATTGCCGAAGCTATCTCGCTA-TACTTGAT-AATCGGCGG-TAG-CACAG-GTCGCAGTATCG-AC-T--AGG-CCTCTCAAAAGTT-GGGTCCCGGCCTCTGGGAAAAACACCTCT-A-AGCGTCAATCAGCTCGGTTTCGCATATTA-TGATATCCCCCGTTGACCAATTGA--TAGTACCCGAGCTTACCGTCGG-ATTCTGGAGTCTT-ATGAGGTTACCGACGA-CGCAGTACCATAAGT-GCGCAATTTGACTGTTCCCGTCGAGTAACCA-AGCTTTGCTCA-CCGGGATGCGCGCCGATGTGACCAGGGGGCGCATGTTACATTGAC-A-GCTGGATCATGTTATGAC-GTGGGTC-ATGCTAAAAGCCTAAAGGACGGT-GCATTAGTAT-TACCGGGACCTCATATCAATGCGCTCGCTAGTTCCTCTTCTCTTGATAACGTATATGCGTCAGGCGCCCGTCCGCCTCCAATACGTG-ACAACGTC-AGTACTGAGCCTC--AA-ACATCGTCTTGTTCG-CC-TACAAAGGATCGGTAGAAAACTCAATATTCGGGTATAAGGTCGTAGGAAGTGTGTCGCCCAGGGCCG-CTAGA-AGCGCACACAAGCG-CTCCTGTCAAGGAGTTG-GTGAAAA-ATGAAC--GACT-ATTGCGTCAC--CTACCTCT-AAGTTTTT-GACAATTTCATGGACGAATTGA-AGCGTCCACAAGCATCTGCCGTAGATATGCGGTAGGTTTTTACATATG-TCACTGCAGAGTCACGGACA-CACATCGCTGTCAAAATGCTCGTACCTAGT-GT-TTGCGATCCCCC-GCGGCATTA-TCTTTTGAACCCTCGTCCCTGTGG-CTCTGATGATTGAG-GTCTGTA-TTCCCTCGTTGTGGGGGGATTGGACCTT-TGTATAGGTTCTTTAACCG-ATGGGGGGCCG--ATCGA-A-TA-TGCTCCTGTTTGCCCCGAACCTT-ACCTCGG-TCCAGACA-CTAAGAAAAACCCC-C-ACTGTAAGGTGCTGAGCCTTTGGATAGCC-CGCGAATGAT-CC-TAGTTGACAA-CTGAACGCGCTCGAACA-TGCCC-GCCCTCTGA--CTGCTGTCTG-GCACCTTTAGACACGCGTCGAC-CATATATT-AGCGCTGTCTGTGG-AGGT-TGTGTCTTGTTGCTCA-CT-CATTATCTGT-AACTGGCTCC-CTC-CCAT-TGGCGTCTTTACACCAACCGCTAGGTTACAGTGCA-TCTAGCGCCTATTATCAGGGCGT-TTGCAGCGGCGCGGTGGCTATGT-GTTAGACATATC-CTTACACTGTATGCTAG-AGCAAGCCAC-TCTGAATGGGTTGC-CGATGAATGA-TCTTGATC-GAGCTCGCA-AC---TACATGGAGTCCGAAGTGAACCTACGGATGATCGTATTCCAACACGAGGATC-TATACGTATAGG-A-GGCG-TAATCCACAATTTAGTAACTCTTGACGC---GGATGAAAAT-GTCGTTACACCTTCCAGAGGCTCGG-GTATATATATGACCT--TGTGATTGAGGACGATCTAGAATAA-CT-GT-G-CT-AAAGTACAGTAGTTTCTATGT-GGTAGGTGGAGAATACAGAGTAG-ATGATTC-GTGGGCCACA-C--T-ACTTTCAT-TAGAGCAGAGA-C-GTGAGTGAGTTTTACACTAGCCAGATGGACCG-GTGA-AGTCTAACAGCCACCGCTT-GTGAGGTCGTTTCCCAGTC-ACCCTACTACAGGCAAAAACTCAGTGT-CC-GTGA-GTGCGTTAGTGATATTCCCTAACGGTTAGGTAACT-CATGAATTCA-AT-TAAGCGTGTCC-CGGT-CACGCCCCCATGGGGGCCTTCTTGGGAGG--AGCATCTTAT--AT-GCTCACGTGGTT-GATAGG-A-T-AATACACTTTTAGTCAGTCCATCAATAAC-AAAGGAAC---CAGGTGGTCGCAGATA-TCCCGCTGATATAGCACTGTGTAAACTCAGGTGATA-CTAAGC--GCTCTAAT-ACG-CTTAATGGCAATGCCCAGTTC--ACGACTAGCTTATGAGGCCCAGCTATGGACTGCGGC-GGCATGTCGGC-GATGGTTGCCCTCGCCCTAAATTATGTACGA-T-ACCGCCT-CTTGTTCT-CCGCCCATAGGGT-C--AGCAGGCGATAGACTCCCAGAAATTTCCTCGTCGT-CCGAATAAGACTAACACGACTA-TT-CCTCTAC-GT-G-AA-CTTATCA-CAAATG-GCT-TACC-TAGGTGGTGGCAGATCACTTTCCGGTG-TATTACGAATTGACGCATACCGAC-A-CGC-GCTTGTTGGATAATCGACTCTAACCTCCTCTCTGGCACATGT-GCTGGATTACCTC-TATTTT-TCTCGCTTAG--GGAACG-T-CCTCTGTCGCGTGAG-GTACGTTTCACGGGAG-CGGCTTGTTCATGCCACGTCCATTATCGA-AGTG-C-GTAAGG-A-GAGCCCTA--GACTCTACACGGAAA-TC-AAC-GTAGAAGGCTC-A-CT`,
+ }
+ return utils.Validate(r, tps, fps)
+}
+
+func AmazonBedrockAPIKeyLongLived() *config.Rule {
+ // https://docs.aws.amazon.com/bedrock/latest/userguide/api-keys-how.html
+ // https://medium.com/@adan.alvarez/api-keys-for-bedrock-a-brief-security-overview-2133ed9a2b3f
+ r := config.Rule{
+ RuleID: "aws-amazon-bedrock-api-key-long-lived",
+ Description: "Identified a pattern that may indicate long-lived Amazon Bedrock API keys, risking unauthorized Amazon Bedrock usage",
+ Regex: utils.GenerateUniqueTokenRegex(`ABSK[A-Za-z0-9+/]{109,269}={0,2}`, false),
+ Entropy: 3,
+ Keywords: []string{
+ "ABSK", // Amazon Bedrock API Key (long-lived)
+ },
+ }
+
+ // validate
+ tps := []string{
+ // Valid API key example
+ "ABSKQmVkcm9ja0FQSUtleS1EXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXM=",
+ // Generate additional random test keys
+ utils.GenerateSampleSecret("bedrock", "ABSKQmVkcm9ja0FQSUtleS1"+secrets.NewSecret(utils.AlphaNumeric("108"))+"="),
+ utils.GenerateSampleSecret("bedrock", "ABSKQmVkcm9ja0FQSUtleS1"+secrets.NewSecret(utils.AlphaNumeric("246"))),
+ }
+
+ fps := []string{
+ // Too short key (missing characters)
+ "ABSKQmVkcm9ja0FQSUtleS1EXAMPLE",
+ // Too long
+ "ABSKQmVkcm9ja0FQSUtleS1EXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLE=",
+ // Wrong prefix
+ "AXSKQmVkcm9ja0FQSUtleS1EXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXM=",
+ }
+
+ return utils.Validate(r, tps, fps)
+}
+
+func AmazonBedrockAPIKeyShortLived() *config.Rule {
+ // https://docs.aws.amazon.com/bedrock/latest/userguide/api-keys-how.html
+ // https://github.com/aws/aws-bedrock-token-generator-js/blob/86277e1489354192c64ffc8f995601daacc1f715/src/token.ts#L21
+ r := config.Rule{
+ RuleID: "aws-amazon-bedrock-api-key-short-lived",
+ Description: "Identified a pattern that may indicate short-lived Amazon Bedrock API keys, risking unauthorized Amazon Bedrock usage",
+ Regex: regexp.MustCompile(`bedrock-api-key-YmVkcm9jay5hbWF6b25hd3MuY29t`),
+ Entropy: 3,
+ Keywords: []string{
+ "bedrock-api-key-", // Amazon Bedrock API Key (short lived)
+ },
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("AmazonBedrockAPIKeyShortLived", `bedrock-api-key-YmVkcm9jay5hbWF6b25hd3MuY29t`)
+
+ fps := []string{
+ // Too short key (missing characters)
+ "bedrock-api-key-",
+ // Wrong prefix
+ "bedrock-api-key-YmVkcm9jay5hbWF6b25hd3MuY29x",
+ }
+
+ return utils.Validate(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/azure.go b/cmd/generate/config/rules/azure.go
new file mode 100644
index 0000000..8537856
--- /dev/null
+++ b/cmd/generate/config/rules/azure.go
@@ -0,0 +1,65 @@
+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"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+// References:
+// - https://learn.microsoft.com/en-us/microsoft-365/compliance/sit-defn-azure-ad-client-secret
+// - https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app#add-credentials
+func AzureActiveDirectoryClientSecret() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "azure-ad-client-secret",
+ Description: "Azure AD Client Secret",
+ // After inspecting dozens of secrets, I'm fairly confident that they start with `xxx\dQ~`.
+ // However, this may not be (entirely) true, and this rule might need to be further refined in the future.
+ // Furthermore, it's possible that secrets have a checksum that could be used to further constrain this pattern.
+ Regex: regexp.MustCompile(`(?:^|[\\'"\x60\s>=:(,)])([a-zA-Z0-9_~.]{3}\dQ~[a-zA-Z0-9_~.-]{31,34})(?:$|[\\'"\x60\s<),])`), // wtf, Go? https://github.com/golang/go/issues/18221
+ Entropy: 3,
+ Keywords: []string{
+ "Q~",
+ },
+ }
+
+ // validate
+ tps := []string{
+ `client_secret=bP88Q~rcBcYjzzOhg1Hnn76Wm3jGgakZiZ.8vMgR`, // gitleaks:allow
+ `client_secret=bP88Q~rcBcYjzzOhg1Hnn76Wm3jGgakZiZ.8vMgR
+`, // gitleaks:allow
+ `client_secret: .IQ8Q~79R7TOWOspFnWcEG-dYt4KXqFqxK16cxr`, // gitleaks:allow
+ `AUTH_CLIENTSECRET = _V28Q~IC8qxmlWNpHuDm34JlbKv9LXV5MvUR3a-P`, // gitleaks:allow
+ `~Gg8Q~nVhlLi2vpg_nXBGqFsbGK-t~Hus1JmTa0y`, // gitleaks:allow
+ `"CLIENT_SECRET": "YYz7Q~Sudoqwap1PnzEBA3zqBK~i5uesDIv.C"`, // gitleaks:allow
+ `Set-PSUAuthenticationMethod -Type 'OpenIDConnect' -CallbackPath '/auth/oidc' -ClientId 'fake' -ClientSecret '2Vq7Q~q5VgKljZ7cb3.0sp0Apz.vOjRIPyeTr'`, // gitleaks:allow
+ `client-secret: "t028Q~-aLbmQuinnZtzbgtlEAYstnBWEmGPAoBm"`, // gitleaks:allow
+ `"cas.authn.azure-active-directory.client-secret=qHF8Q~PCM5HhMoyTFc5TYEomnzR6Kim9UJhe8a.P",`, // gitleaks:allow
+ `"line": "client_srt = \"qpF8Q~PCM5MhMoyTFc5TYEomnYRUKim9UJhe8a2P\";",`, // gitleaks:allow
+ `"client_secret": acctest.Representation{RepType: acctest.Required, Create: 'dO29Q~F5-VwnW.lZdd11xFF_t5NAXCaGwDl9NbT1'},`, // gitleaks:allow
+ `Example= GN.7Q~4AkLZBNEbz4Jxlm~O5G6SsyFxYg6zMR`, // gitleaks:allow
+ `"the_value": "QtT8Q~9C-_Ij~RouHVpD2Tuf3oHWGh.DQ3kcjbAn"`, // gitleaks:allow
+ `QtT8Q~9C-_Ij~RouHVpD2Tuf3oHWGh.DQ3kcjbAn`, // gitleaks:allow
+ `(use the client secret: QtT8Q~9C-_Ij~RouHVpD2Tuf3oHWGh.DQ3kcjbAn)`, // gitleaks:allow
+ `(QtT8Q~9C-_Ij~RouHVpD2Tuf3oHWGh.DQ3kcjbAn)`, // gitleaks:allow
+ `\"pass\": \"` + fmt.Sprintf("%s%sQ~%s", secrets.NewSecret(`[\w~.]{3}`), secrets.NewSecret(utils.Numeric("1")), secrets.NewSecret(`[\w~.-]{31,34}`)),
+ }
+ fps := []string{
+ ``,
+ `~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`,
+ `~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`,
+ `.ui.visible.right.sidebar~.ui.visible.left.sidebar~.pusher{transform:translate3d(0,0,0)}`,
+ `buf.WriteString("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n::\n\n")`,
+ `'url': 'http://www.2doc.nl/speel~VARA_101375237~mh17-het-verdriet-van-nederland~.html',`,
+ `@ar = split("~", "965f1453~47~09414c93e4cef985416f472549220827da3ba6fed8ad28e29ef6ad170ad53a69051e9b06f439ef6da5df8670181f7eb2481650");`,
+ `'#!/registries/5/portainer.demo~2Fportainerregistrytesting~2Falpine',`,
+ `// CloudFront-Signature: Ixn4bF1LLrLcB8XG-t5bZbIB0vfwSF2s4gkef~PcNBdx73MVvZD3v8DZ5GzcqNrybMiqdYJY5KqK6vTsf5JXDgwFFz-h98wdsbV-izcuonPdzMHp4Ay4qyXM6Ed5jB9dUWYGwMkA6rsWXpftfX8xmk4tG1LwFuJV6nAsx4cfpuKwo4vU2Hyr2-fkA7MZG8AHkpDdVUnjm1q-Re9HdG0nCq-2lnBAdOchBpJt37narOj-Zg6cbx~6rzQLVQd8XIv-Bn7VTc1tkBAJVtGOHb0Q~PLzSRmtNGYTnpL0z~gp3tq8lhZc2HuvJW5-tZaYP9yufeIzk5bqsT6DT4iDuclKKw__, , , false`,
+ `+ ""`,
+ `client_secret=bP88Q~xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`,
+ }
+ return utils.Validate(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/beamer.go b/cmd/generate/config/rules/beamer.go
new file mode 100644
index 0000000..e401507
--- /dev/null
+++ b/cmd/generate/config/rules/beamer.go
@@ -0,0 +1,25 @@
+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"
+)
+
+func Beamer() *config.Rule {
+ // define 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: utils.GenerateSemiGenericRegex([]string{"beamer"},
+ `b_[a-z0-9=_\-]{44}`, true),
+ Keywords: []string{"beamer"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("beamer", "b_"+secrets.NewSecret(utils.AlphaNumericExtended("44")))
+ fps := []string{
+ `│ ├── R21A-A-V010SP13RC181024R16900-CN-B_250K-Release-OTA-97B6C6C59241976086FABDC41472150C.bfu`,
+ }
+ return utils.Validate(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/bitbucket.go b/cmd/generate/config/rules/bitbucket.go
new file mode 100644
index 0000000..be529fc
--- /dev/null
+++ b/cmd/generate/config/rules/bitbucket.go
@@ -0,0 +1,36 @@
+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"
+)
+
+func BitBucketClientID() *config.Rule {
+ // define rule
+ r := config.Rule{
+ Description: "Discovered a potential Bitbucket Client ID, risking unauthorized repository access and potential codebase exposure.",
+ RuleID: "bitbucket-client-id",
+ Regex: utils.GenerateSemiGenericRegex([]string{"bitbucket"}, utils.AlphaNumeric("32"), true),
+ Keywords: []string{"bitbucket"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("bitbucket", secrets.NewSecret(utils.AlphaNumeric("32")))
+ return utils.Validate(r, tps, nil)
+}
+
+func BitBucketClientSecret() *config.Rule {
+ // define 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: utils.GenerateSemiGenericRegex([]string{"bitbucket"}, utils.AlphaNumericExtended("64"), true),
+
+ Keywords: []string{"bitbucket"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("bitbucket", secrets.NewSecret(utils.AlphaNumeric("64")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/bittrex.go b/cmd/generate/config/rules/bittrex.go
new file mode 100644
index 0000000..29a6d25
--- /dev/null
+++ b/cmd/generate/config/rules/bittrex.go
@@ -0,0 +1,36 @@
+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"
+)
+
+func BittrexAccessKey() *config.Rule {
+ // define 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: utils.GenerateSemiGenericRegex([]string{"bittrex"}, utils.AlphaNumeric("32"), true),
+ Keywords: []string{"bittrex"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("bittrex", secrets.NewSecret(utils.AlphaNumeric("32")))
+ return utils.Validate(r, tps, nil)
+}
+
+func BittrexSecretKey() *config.Rule {
+ // define rule
+ r := config.Rule{
+ Description: "Detected a Bittrex Secret Key, potentially compromising cryptocurrency transactions and financial security.",
+ RuleID: "bittrex-secret-key",
+ Regex: utils.GenerateSemiGenericRegex([]string{"bittrex"}, utils.AlphaNumeric("32"), true),
+
+ Keywords: []string{"bittrex"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("bittrex", secrets.NewSecret(utils.AlphaNumeric("32")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/clickhouse.go b/cmd/generate/config/rules/clickhouse.go
new file mode 100644
index 0000000..190c1e0
--- /dev/null
+++ b/cmd/generate/config/rules/clickhouse.go
@@ -0,0 +1,30 @@
+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"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+func ClickHouseCloud() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "clickhouse-cloud-api-secret-key",
+ Description: "Identified a pattern that may indicate clickhouse cloud API secret key, risking unauthorized clickhouse cloud api access and data breaches on ClickHouse Cloud platforms.",
+ Regex: regexp.MustCompile(`\b(4b1d[A-Za-z0-9]{38})\b`),
+ Entropy: 3,
+ Keywords: []string{
+ "4b1d", // Prefix
+ },
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("ClickHouse", "4b1dbRdW3rOcB7xLthrM4BTBGK1qPLkHigpN1bXD6z")
+ tps = append(tps, utils.GenerateSampleSecrets("ClickHouse", "4b1d"+secrets.NewSecret("[A-Za-z0-9]{38}"))...)
+ fps := []string{
+ `key = 4b1dXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX`, // Low entropy
+ `key = adf4b1dbRdW3rOcB7xLthrM4BTBGK1qPLkHigpN1bXD6z`, // Not start of a word
+ }
+ return utils.Validate(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/clojars.go b/cmd/generate/config/rules/clojars.go
new file mode 100644
index 0000000..d39c7f2
--- /dev/null
+++ b/cmd/generate/config/rules/clojars.go
@@ -0,0 +1,23 @@
+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"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+func Clojars() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "clojars-api-token",
+ Description: "Uncovered a possible Clojars API token, risking unauthorized access to Clojure libraries and potential code manipulation.",
+ Regex: regexp.MustCompile(`(?i)CLOJARS_[a-z0-9]{60}`),
+ Entropy: 2,
+ Keywords: []string{"clojars_"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("clojars", "CLOJARS_"+secrets.NewSecret(utils.AlphaNumeric("60")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/cloudflare.go b/cmd/generate/config/rules/cloudflare.go
new file mode 100644
index 0000000..a876bd6
--- /dev/null
+++ b/cmd/generate/config/rules/cloudflare.go
@@ -0,0 +1,81 @@
+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"
+)
+
+var global_keys = []string{
+ `cloudflare_global_api_key = "d3d1443e0adc9c24564c6c5676d679d47e2ca"`, // gitleaks:allow
+ `CLOUDFLARE_GLOBAL_API_KEY: 674538c7ecac77d064958a04a83d9e9db068c`, // gitleaks:allow
+ `cloudflare: "0574b9f43978174cc2cb9a1068681225433c4"`, // gitleaks:allow
+}
+
+var api_keys = []string{
+ `cloudflare_api_key = "Bu0rrK-lerk6y0Suqo1qSqlDDajOk61wZchCkje4"`, // gitleaks:allow
+ `CLOUDFLARE_API_KEY: 5oK0U90ME14yU6CVxV90crvfqVlNH2wRKBwcLWDc`, // gitleaks:allow
+ `cloudflare: "oj9Yoyq0zmOyWmPPob1aoY5YSNNuJ0fbZSOURBlX"`, // gitleaks:allow
+}
+
+var origin_ca_keys = []string{
+ `CLOUDFLARE_ORIGIN_CA: v1.0-aaa334dc886f30631ba0a610-0d98ef66290d7e50aac7c27b5986c99e6f3f1084c881d8ac0eae5de1d1aa0644076ff57022069b3237d19afe60ad045f207ef2b16387ee37b749441b2ae2e9ebe5b4606e846475d4a5`,
+ `CLOUDFLARE_ORIGIN_CA: v1.0-15d20c7fccb4234ac5cdd756-d5c2630d1b606535cf9320ae7456b090e0896cec64169a92fae4e931ab0f72f111b2e4ffed5b2bb40f6fba6b2214df23b188a23693d59ce3fb0d28f7e89a2206d98271b002dac695ed`,
+}
+
+var identifiers = []string{"cloudflare"}
+
+func CloudflareGlobalAPIKey() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "cloudflare-global-api-key",
+ Description: "Detected a Cloudflare Global API Key, potentially compromising cloud application deployments and operational security.",
+ Regex: utils.GenerateSemiGenericRegex(identifiers, utils.Hex("37"), true),
+ Entropy: 2,
+ Keywords: identifiers,
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("cloudflare", secrets.NewSecret(utils.Hex("37")))
+ tps = append(tps, global_keys...)
+ fps := append(api_keys, origin_ca_keys...)
+
+ return utils.Validate(r, tps, fps)
+}
+
+func CloudflareAPIKey() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "cloudflare-api-key",
+ Description: "Detected a Cloudflare API Key, potentially compromising cloud application deployments and operational security.",
+ Regex: utils.GenerateSemiGenericRegex(identifiers, utils.AlphaNumericExtendedShort("40"), true),
+ Entropy: 2,
+ Keywords: identifiers,
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("cloudflare", secrets.NewSecret(utils.AlphaNumericExtendedShort("40")))
+ tps = append(tps, api_keys...)
+ fps := append(global_keys, origin_ca_keys...)
+
+ return utils.Validate(r, tps, fps)
+}
+
+func CloudflareOriginCAKey() *config.Rule {
+ ca_identifiers := append(identifiers, "v1.0-")
+ // define 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: utils.GenerateUniqueTokenRegex(`v1\.0-`+utils.Hex("24")+"-"+utils.Hex("146"), false),
+ Entropy: 2,
+ Keywords: ca_identifiers,
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("cloudflare", "v1.0-aaa334dc886f30631ba0a610-0d98ef66290d7e50aac7c27b5986c99e6f3f1084c881d8ac0eae5de1d1aa0644076ff57022069b3237d19afe60ad045f207ef2b16387ee37b749441b2ae2e9ebe5b4606e846475d4a5")
+ tps = append(tps, origin_ca_keys...)
+ fps := append(global_keys, api_keys...)
+
+ return utils.Validate(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/codecov.go b/cmd/generate/config/rules/codecov.go
new file mode 100644
index 0000000..63c41e8
--- /dev/null
+++ b/cmd/generate/config/rules/codecov.go
@@ -0,0 +1,23 @@
+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"
+)
+
+func CodecovAccessToken() *config.Rule {
+ // define 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: utils.GenerateSemiGenericRegex([]string{"codecov"}, utils.AlphaNumeric("32"), true),
+ Keywords: []string{
+ "codecov",
+ },
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("codecov", secrets.NewSecret(utils.AlphaNumeric("32")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/cohere.go b/cmd/generate/config/rules/cohere.go
new file mode 100644
index 0000000..d803eb0
--- /dev/null
+++ b/cmd/generate/config/rules/cohere.go
@@ -0,0 +1,32 @@
+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"
+)
+
+func CohereAPIToken() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "cohere-api-token",
+ Description: "Identified a Cohere Token, posing a risk of unauthorized access to AI services and data manipulation.",
+ Regex: utils.GenerateSemiGenericRegex([]string{"cohere", "CO_API_KEY"}, `[a-zA-Z0-9]{40}`, false),
+ Entropy: 4,
+ Keywords: []string{
+ "cohere",
+ "CO_API_KEY",
+ },
+ }
+
+ // validate
+ tps := []string{
+ utils.GenerateSampleSecret("cohere", secrets.NewSecret(`[a-zA-Z0-9]{40}`)),
+ // https://github.com/cohere-ai/cohere-go/blob/abe8044073ed498ffbb206a602d03c2414b64512/client/client.go#L38C30-L38C40
+ `export CO_API_KEY=` + secrets.NewSecret(`[a-zA-Z0-9]{40}`),
+ }
+ fps := []string{
+ `CO_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`,
+ }
+ return utils.Validate(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/coinbase.go b/cmd/generate/config/rules/coinbase.go
new file mode 100644
index 0000000..5d15922
--- /dev/null
+++ b/cmd/generate/config/rules/coinbase.go
@@ -0,0 +1,24 @@
+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"
+)
+
+func CoinbaseAccessToken() *config.Rule {
+ // define 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: utils.GenerateSemiGenericRegex([]string{"coinbase"},
+ utils.AlphaNumericExtendedShort("64"), true),
+ Keywords: []string{
+ "coinbase",
+ },
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("coinbase", secrets.NewSecret(utils.AlphaNumericExtendedShort("64")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/config.tmpl b/cmd/generate/config/rules/config.tmpl
new file mode 100644
index 0000000..9a39a15
--- /dev/null
+++ b/cmd/generate/config/rules/config.tmpl
@@ -0,0 +1,75 @@
+# This file has been auto-generated. Do not edit manually.
+# If you would like to contribute new rules, please use
+# cmd/generate/config/main.go and follow the contributing guidelines
+# at https://github.com/gitleaks/gitleaks/blob/master/CONTRIBUTING.md
+#
+# How the hell does secret scanning work? Read this:
+# https://lookingatcomputer.substack.com/p/regex-is-almost-all-you-need
+#
+# This is the default gitleaks configuration file.
+# Rules and allowlists are defined within this file.
+# Rules instruct gitleaks on what should be considered a secret.
+# Allowlists instruct gitleaks on what is allowed, i.e. not a secret.
+
+title = "{{.Title}}"
+
+# minVersion indicates the minimum Gitleaks version required to use this config.
+# If the running version is older, a warning will be logged and not all
+# config-enabled features are guaranteed to work.
+minVersion = "v8.25.0"
+
+{{ with .Allowlists }}{{ range $i, $allowlist := . }}{{ if or $allowlist.Regexes $allowlist.Paths $allowlist.Commits $allowlist.StopWords }}# TODO: change to [[allowlists]]{{println}}[allowlist]
+{{- with .Description }}{{println}}description = "{{ . }}"{{ end }}
+{{- with .MatchCondition }}{{println}}condition = "{{ .String }}"{{ end }}
+{{- with .Commits -}}{{println}}commits = [
+ {{ range $j, $commit := . }}"{{ $commit }}",{{ end }}
+]{{ end }}
+{{- with .Paths }}{{println}}paths = [{{ range $j, $path := . }}
+ '''{{ $path }}''',{{ end }}
+]{{ end }}
+{{- if and .RegexTarget .Regexes }}{{println}}regexTarget = "{{ .RegexTarget }}"{{ end -}}
+{{- with .Regexes }}{{println}}regexes = [{{ range $i, $regex := . }}
+ '''{{ $regex }}''',{{ end }}
+]{{ end }}
+{{- with .StopWords }}{{println}}stopwords = [{{ range $j, $stopword := . }}
+ "{{ $stopword }}",{{ end }}
+]{{ end }}{{ end }}{{ end }}{{ end }}{{println}}
+
+{{- range $i, $rule := .Rules }}{{println}}[[rules]]
+id = "{{$rule.RuleID}}"
+description = "{{$rule.Description}}"
+{{- with $rule.Regex }}
+regex = '''{{ . }}'''{{ end -}}
+{{- with $rule.Path }}
+path = '''{{ . }}'''{{ end -}}
+{{- with $rule.SecretGroup }}
+secretGroup = {{ . }}{{ end -}}
+{{- with $rule.Entropy }}
+entropy = {{ . }}{{ end -}}
+{{- with $rule.Keywords }}
+{{- if gt (len .) 1}}
+keywords = [{{ range $j, $keyword := . }}
+ "{{ $keyword }}",{{ end }}
+]{{else}}
+keywords = [{{ range $j, $keyword := . }}"{{ $keyword }}"{{ end }}]{{end}}{{ end }}
+{{- with $rule.Tags }}
+tags = [
+ {{ range $j, $tag := . }}"{{ $tag }}",{{ end }}
+]{{ end }}
+{{- with $rule.Allowlists }}{{ range $i, $allowlist := . }}{{ if or $allowlist.Regexes $allowlist.Paths $allowlist.Commits $allowlist.StopWords }}{{println}}[[rules.allowlists]]
+{{- with .Description }}{{println}}description = "{{ . }}"{{ end }}
+{{- with .MatchCondition }}{{println}}condition = "{{ .String }}"{{ end }}
+{{- with .Commits -}}{{println}}commits = [
+ {{ range $j, $commit := . }}"{{ $commit }}",{{ end }}
+]{{ end }}
+{{- with .Paths }}{{println}}paths = [
+ {{ range $j, $path := . }}'''{{ $path }}''',{{ end }}
+]{{ end }}
+{{- if and .RegexTarget .Regexes }}{{println}}regexTarget = "{{ .RegexTarget }}"{{ end -}}
+{{- with .Regexes }}{{println}}regexes = [{{ range $i, $regex := . }}
+ '''{{ $regex }}''',{{ end }}
+]{{ end }}
+{{- with .StopWords }}{{println}}stopwords = [{{ range $j, $stopword := . }}
+ "{{ $stopword }}",{{ end }}
+]{{ end }}{{ end }}{{ end }}{{ end }}
+{{ end }}
diff --git a/cmd/generate/config/rules/confluent.go b/cmd/generate/config/rules/confluent.go
new file mode 100644
index 0000000..8395f9e
--- /dev/null
+++ b/cmd/generate/config/rules/confluent.go
@@ -0,0 +1,40 @@
+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"
+)
+
+func ConfluentSecretKey() *config.Rule {
+ // define 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: utils.GenerateSemiGenericRegex([]string{"confluent"}, utils.AlphaNumeric("64"), true),
+ Keywords: []string{
+ "confluent",
+ },
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("confluent", secrets.NewSecret(utils.AlphaNumeric("64")))
+ return utils.Validate(r, tps, nil)
+}
+
+func ConfluentAccessToken() *config.Rule {
+ // define 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: utils.GenerateSemiGenericRegex([]string{"confluent"}, utils.AlphaNumeric("16"), true),
+
+ Keywords: []string{
+ "confluent",
+ },
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("confluent", secrets.NewSecret(utils.AlphaNumeric("16")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/contentful.go b/cmd/generate/config/rules/contentful.go
new file mode 100644
index 0000000..64ee58d
--- /dev/null
+++ b/cmd/generate/config/rules/contentful.go
@@ -0,0 +1,22 @@
+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"
+)
+
+func Contentful() *config.Rule {
+ // define 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: utils.GenerateSemiGenericRegex([]string{"contentful"},
+ utils.AlphaNumericExtended("43"), true),
+ Keywords: []string{"contentful"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("contentful", secrets.NewSecret(utils.AlphaNumeric("43")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/curl.go b/cmd/generate/config/rules/curl.go
new file mode 100644
index 0000000..be7572f
--- /dev/null
+++ b/cmd/generate/config/rules/curl.go
@@ -0,0 +1,201 @@
+package rules
+
+import (
+ "fmt"
+
+ "github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
+ "github.com/zricethezav/gitleaks/v8/config"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+// https://curl.se/docs/manpage.html#-u
+func CurlBasicAuth() *config.Rule {
+ r := config.Rule{
+ RuleID: "curl-auth-user",
+ Description: "Discovered a potential basic authorization token provided in a curl command, which could compromise the curl accessed resource.",
+ Regex: regexp.MustCompile(`\bcurl\b(?:.*|.*(?:[\r\n]{1,2}.*){1,5})[ \t\n\r](?:-u|--user)(?:=|[ \t]{0,5})("(:[^"]{3,}|[^:"]{3,}:|[^:"]{3,}:[^"]{3,})"|'([^:']{3,}:[^']{3,})'|((?:"[^"]{3,}"|'[^']{3,}'|[\w$@.-]+):(?:"[^"]{3,}"|'[^']{3,}'|[\w${}@.-]+)))(?:\s|\z)`),
+ Keywords: []string{"curl"},
+ Entropy: 2,
+ Allowlists: []*config.Allowlist{
+ {
+ Regexes: []*regexp.Regexp{
+ regexp.MustCompile(`[^:]+:(?:change(?:it|me)|pass(?:word)?|pwd|test|token|\*+|x+)`), // common placeholder passwords
+ regexp.MustCompile(`['"]?<[^>]+>['"]?:['"]?<[^>]+>|<[^:]+:[^>]+>['"]?`), //
+ regexp.MustCompile(`[^:]+:\[[^]]+]`), // [placeholder]
+ regexp.MustCompile(`['"]?[^:]+['"]?:['"]?\$(?:\d|\w+|\{(?:\d|\w+)})['"]?`), // $1 or $VARIABLE
+ regexp.MustCompile(`\$\([^)]+\):\$\([^)]+\)`), // $(cat login.txt)
+ regexp.MustCompile(`['"]?\$?{{[^}]+}}['"]?:['"]?\$?{{[^}]+}}['"]?`), // ${{ secrets.FOO }} or {{ .Values.foo }}
+ },
+ },
+ },
+ }
+
+ // validate
+ tps := []string{
+ // short
+ `curl --cacert ca.crt -u elastic:P@ssw0rd$1 https://localhost:9200`, // same lines, no quotes
+ `sh-5.0$ curl -k -X POST https://infinispan:11222/rest/v2/caches/default/hello \
+ -H 'Content-type: text/plain' \
+ -d 'world' \
+ -u developer:yqDVtkqPECriaLRi`, // different line
+ `curl -u ":d2LkV78zLx!t" https://localhost:9200`, // empty username
+ `curl -u "d2LkV78zLx!t:" https://localhost:9200`, // empty password
+
+ // long
+ `curl -sw '%{http_code}' -X POST --user 'johns:h0pk1ns~21s' $GItHUB_API_URL/$GIT_COMMIT --data`,
+ `curl --user roger23@gmail.com:pQ9wTxu4Fg https://www.dropbox.com/cli_link?host_id=abcdefg -v`, // same line, no quotes
+ `curl -s --user 'api:d2LkV78zLx!t' \
+ https://api.mailgun.net/v2/sandbox91d3515882ecfaa1c65be642.mailgun.org/messages`, // same line, single quotes
+ `curl -s -v --user "j.smith:dB2yF6@qL9vZm1P#4J" "https://api.contoso.org/user/me"`, // same line, double quotes
+ `curl -X POST --user "{acd3c08b-74e8-4f44-a2d0-80694le24f46}":"{ZqL5kVrX1n8tA2}" --header "Accept: application/json" --data "{\"text\":\"Hello, world\",\"source\":\"en\",\"target\":\"es\"}" https://gateway.watsonplatform.net/language-translator/api`,
+ `curl --user kevin:'pRf7vG2h1L8nQkW9' -iX PATCH -H "Content-Type: application/json" -d`, // same line, mixed quoting
+ `$ curl https://api.dropbox.com/oauth2/token \
+ --user c28wlsosanujy2z:qgsnai0xokrw4j1 --data grant_type=authorization_code`, // different line
+
+ // TODO
+ //` curl -s --insecure --url "imaps://whatever.imap.server" --user\
+ //"myuserid:mypassword" --request "STATUS INBOX (UNSEEN)"`,
+ }
+ fps := []string{
+ // short
+ `curl -i -u 'test:test'`,
+ ` curl -sL --user "$1:$2" "$3" > "$4"`, // environment variable
+ `curl -u https://test.com/endpoint`, // placeholder
+ `curl --user neo4j:[PASSWORD] http://[IP]:7474/db/data/`, // placeholder
+ `curl -u "myusername" http://localhost:15130/api/check_user/`, // no password
+ `curl -u username:token`,
+ `curl -u "${_username}:${_password}"`,
+ `curl -u "${username}":"${password}"`,
+ `curl -k -X POST -I -u "SRVC_JENKINS:${APPID}"`,
+ `curl -u ":" https://localhost:9200`, // empty username and password
+
+ // long
+ `curl -sw '%{http_code}' -X POST --user '$USERNAME:$PASSWORD' $GItHUB_API_URL/$GIT_COMMIT --data`,
+ `curl --user "xxx:yyy"`,
+ ` curl -sL --user "$GITHUB_USERNAME:$GITHUB_PASSWORD" "$GITHUB_URL" > "$TESTS_PATH"`, // environment variable
+ // variable interpolation
+ `curl --silent --fail {{- if and $.Values.username $.Values.password }} --user "{{ $.Values.username }}:{{ $.Values.password }}"`,
+ `curl -XGET -i -u "${{ env.ELK_ID }}:${{ build.env.ELK_PASS }}"`,
+ `curl -XGET -i -u "${{needs.vault.outputs.account_id}}:${{needs.vault.outputs.account_password}}"`,
+ `curl -XGET -i -u "${{ steps.vault.outputs.account_id }}:${{ steps.vault.outputs.account_password }}"`,
+ `curl -X POST --user "$(cat ./login.txt):$(cat ./password.txt)"`, // command
+ `curl http://127.0.0.1:5000/file --user user:pass --digest # digest auth`, // placeholder
+ ` curl -X GET --insecure --user "username:password" \`, // placeholder
+ `curl --silent --insecure --user ${f5user}:${f5pass} \`, // placeholder
+ `curl --insecure --ssl-reqd "smtps://smtp.gmail.com" --mail-from "src@gmail.com" --mail-rcpt "dst@gmail.com" --user "src@gmail.com" --upload-file out.txt`, // no password
+
+ // different command
+ `#HTTP command line test
+curl -X POST -H "Content-Type: application/json" -d '{"id":12345,"geo":{"latitude":28.50,"longitude":-81.14}}' http://:8080/serve
+
+#UDP command line test
+echo -n '{"type":"serve","channel":"/","data":{"site_id":8,"post_id":12345,"geo":{"lat":28.50,"long":-81.14}}}' >/dev/udp/127.0.0.1/41234
+
+#UDP Listener (for confirmation)
+nc -u -l 41234`,
+ }
+ return utils.Validate(r, tps, fps)
+}
+
+// https://curl.se/docs/manpage.html#-H
+func CurlHeaderAuth() *config.Rule {
+ // language=regexp
+ authPat := `(?i)(?:Authorization:[ \t]{0,5}(?:Basic[ \t]([a-z0-9+/]{8,}={0,3})|(?:Bearer|(?:Api-)?Token)[ \t]([\w=~@.+/-]{8,})|([\w=~@.+/-]{8,}))|(?:(?:X-(?:[a-z]+-)?)?(?:Api-?)?(?:Key|Token)):[ \t]{0,5}([\w=~@.+/-]{8,}))`
+ r := config.Rule{
+ RuleID: "curl-auth-header",
+ Description: "Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource.",
+ Regex: regexp.MustCompile(
+ // language=regexp
+ fmt.Sprintf(`\bcurl\b(?:.*?|.*?(?:[\r\n]{1,2}.*?){1,5})[ \t\n\r](?:-H|--header)(?:=|[ \t]{0,5})(?:"%s"|'%s')(?:\B|\s|\z)`, authPat, authPat)),
+ Entropy: 2.75,
+ Keywords: []string{"curl"},
+ //Allowlists: []*config.Allowlist{
+ // {
+ // Regexes: []*regexp.Regexp{},
+ // },
+ //},
+ }
+
+ tps := []string{
+ `curl --header 'Authorization: 5eb4223e-5008-46e5-be67-c7b8f2732305'`,
+ // Short flag.
+ `curl -H 'Authorization: Basic YnJvd3Nlcjo=' \`, // same line, single quotes
+ // TODO: Handle short flags combined.
+ //`TOKEN=$(curl -sH "Authorization: Basic $BASIC_TOKEN" "https://$REGISTRY/oauth2/token?service=$REGISTRY&scope=repository:$REPO:pull" | jq -r .access_token)`,
+
+ // Long flag.
+ `curl -k -X POST --header "Authorization: Basic djJlNEpYa0NJUHZ5a2FWT0VRXzRqZmZUdDkwYTp2emNBZGFzZWpmlWZiUDc2VUJjNDNNVDExclVh" "https://api-qa.example.com:8243/token" -d "grant_type=client_credentials"`, // same line, double quotes
+
+ // Basic auth.
+ `curl -X POST -H "Content-Type: application/json" \
+ -H "Authorization: Basic MzUzYjMwMmM0NDU3NGY1NjUwNDU2ODdlNTM0ZTdkNmE6Mjg2OTI0Njk3ZTYxNWE2NzJhNjQ2YTQ5MzU0NTY0NmM=" \
+ -d '{"user":{"emailAddress":"test@example.com"}, "password":"password"}' \
+ 'http://localhost:8080/oauth2-provider/v1.0/users'`, // different line, double quotes
+ `#curl -X POST \
+# https://api.mailgun.net/v3/sandbox7dbcabccd4314c123e8b23599d35f5b6.mailgun.org/messages \
+# -H 'Authorization: Basic YXBpOmtleS1hN2MzNDJ3MzNhNWQxLTU2M2U3MjlwLTZhYjI3YzYzNzM0Ng==' \
+# -F from='Excited User ' \
+# -F to='joe@example.com' \
+# -F subject='Hello' \
+# -F text='Testing some Mailgun awesomness!'`, // different line, single quotes
+
+ // Bearer auth
+ `# curl -X GET "http://localhost:3000/api/cron/status" -H "Authorization: Bearer cfcabd11c7ed9a41b1a3e063c32d5114"`, // same line, double quotes
+ `curl -X PUT -H 'Authorization: Bearer jC+6TUUjCNHcVtAXpcqBCgxnA8r+qD6MatnYaf/+289y7HWpK0BWPyLHv/K4DMN32fufwmeVVjlo8zjgBh8kx3GfS6IqO70w1DVMSCTwX7fhEpiXaxzv0mhSMHDX9Kw63Q6DkavUWUV+MDNhCF5wGQrcdQNncVRF3YkuDHDT/xw2YWyZ/DX8k+gAYiC8gcD8Ueg0ljBVS1IDwPjuGoFPESJVxYr0MDPF2D8Pn2S5rq692U4D9ZLuluS46VA4DK6ig5P7QM5XVXi4V7vXM8qpN/zqneyz+w4PUh6NIX7QG6JczMhYd9maWRWVat5jDdyII63P6sNAy9QZjw+ClW211Q==' -d 'user={"account":"user@domain.com", "roles":["user"]}' http://127.0.0.1:8443/desks/1/occupy`, // same line, single quotes
+ `curl https://api.openai.com/v1/chat/completions \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer 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" \`, // different line, double quotes
+ `curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
+ -H "Authorization: Bearer _FXNljbSRYMWx3TWrd7lgKhLtVZX6iskC8Wcbb4b" \
+ -H "Content-Type:application/json"`,
+ `curl -H "Authorization: Bearer sha256~bRLFnzd59Z3XpZH5_seJPHALOuvbWiKwbFKSsoALkgp"`,
+
+ // Token auth
+ `curl -H "Authorization: Api-Token 22cb987851bc5659l29114c62e60c79abd0d2c08" --request PUT https://appsecclass.report/api/use/635`, // token
+ `curl -H "Authorization: Token 22cb987851bc5659229114c62e60c79abd0d2c08" --request PUT https://appsecclass.report/api/use/635`, // token
+
+ // Nothing
+ `curl -L -H "Authorization:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb25maWRlbmNlIjowLjh9.kvRPfjAhLhtRTczoRgctVGp7KY1QVH3UBZM-gM0x8ec" service1.local -> correct jwt `, // no prefix
+ `curl -L -H "Authorization: sha256~bRLFnzd5@=-.a+/hgdS"`, // no prefix
+
+ // Non-authorization headers.
+ `curl -X GET \
+ -H "apikey: c4ed6c21-9dd5-4a05-8e3f-c56d1151cce8" \
+ -H "Accept: application/json" \`, // apikey
+ `curl -X POST --header "Api-Token: Sk94HG7f6KB"`, // api-token
+ `curl -XPOST http://localhost:8080/api/tasks -H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" -H "Token: 3fea6af1349166ea" -d "content=hello-curl"`, // token
+ `curl -X GET https://octopus.corp.net/
+ -H "X-Octopus-ApiKey: 3a16750d-d363-41a4-8ebd-035408f7730f" \`, // X-$thing-ApiKey
+ }
+ fps := []string{
+ // Placeholders
+ `curl https://example.com/micropub -d h=entry -d "content=Hello World" -H "Authorization: Bearer XXXXXXXXXXXX"`,
+ `curl -X POST https://accounts.spotify.com/api/token -d grant_type=client_credentials --header "Authorization: Basic ..."`,
+ `curl \
+ -H "Authorization: Bearer " \
+ "https://api.openverse.org/v1/audio/?q=test"`,
+ `curl -v -v -v -X POST https://domain/api/v1/authentication/sso/login-url/ \
+ -H 'Content-Type: application/json' \
+ -H "Authorization: Token **********" \
+ -d '{"username": "test", "next": "/luna/"}'`,
+
+ // Variables
+ `curl -XPOST http://localhost:8080/api/token -H "Authorization: basic {base64(email:password[\n])}" => token`, // same line, invalid base64
+ `curl -X GET \
+ -H "apikey: $API_KEY" \
+ -H "Accept: $FORMAT" \
+"$API_URL/rest/v1/stats_derniere_labellisation"`, // API Key placeholder
+ `$ curl -X POST "http://localhost:8000/v1/chat/completions" \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer $API_KEY" \
+ -d '{
+ "model": "chatglm3-6b-32k",
+ "messages": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "Hello!"}]
+ }'`, // different line, placeholder
+ `curl -X GET -H "Content-Type: application/json" -H "Authorization: Bearer $(gcloud auth print-access-token)" https://workflowexecutions.googleapis.com/v1/projects/244283331594/locations/us-central1/workflows/sample-workflow/executions/43c925aa-514a-44c1-a0a4-a9f8f26fd2cb/callbacks/1705791f-d446-4e92-a6d0-a13622422e80_31864a51-8c13-4b03-ad4d-945cdc8d0631`, // script
+
+ // Not valid BASIC
+ `curl -X POST -H "Content-Type: application/json" -H "Authorization: Basic eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb25maWRlbmNlIjowLjh9.kvRPfjAhLhtRTczoRgctVGp7KY1QVH3UBZM-gM0x8ec" \`,
+ }
+ return utils.Validate(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/databricks.go b/cmd/generate/config/rules/databricks.go
new file mode 100644
index 0000000..ca01f67
--- /dev/null
+++ b/cmd/generate/config/rules/databricks.go
@@ -0,0 +1,26 @@
+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"
+)
+
+func Databricks() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "databricks-api-token",
+ Description: "Uncovered a Databricks API token, which may compromise big data analytics platforms and sensitive data processing.",
+ Regex: utils.GenerateUniqueTokenRegex(`dapi[a-f0-9]{32}(?:-\d)?`, false),
+ Entropy: 3,
+ Keywords: []string{"dapi"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("databricks", "dapi"+secrets.NewSecret(utils.Hex("32")))
+ tps = append(tps, `token = dapif13ac4b49d1cb31f69f678e39602e381-2`) // gitleaks:ignore
+ fps := []string{
+ `DATABRICKS_TOKEN=dapi123456789012345678a9bc01234defg5`,
+ }
+ return utils.Validate(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/datadog.go b/cmd/generate/config/rules/datadog.go
new file mode 100644
index 0000000..c33fa81
--- /dev/null
+++ b/cmd/generate/config/rules/datadog.go
@@ -0,0 +1,24 @@
+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"
+)
+
+func DatadogtokenAccessToken() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "datadog-access-token",
+ Description: "Detected a Datadog Access Token, potentially risking monitoring and analytics data exposure and manipulation.",
+ Regex: utils.GenerateSemiGenericRegex([]string{"datadog"},
+ utils.AlphaNumeric("40"), true),
+ Keywords: []string{
+ "datadog",
+ },
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("datadog", secrets.NewSecret(utils.AlphaNumeric("40")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/definednetworking.go b/cmd/generate/config/rules/definednetworking.go
new file mode 100644
index 0000000..17fb54c
--- /dev/null
+++ b/cmd/generate/config/rules/definednetworking.go
@@ -0,0 +1,28 @@
+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"
+)
+
+func DefinedNetworkingAPIToken() *config.Rule {
+ // Define Rule
+ r := config.Rule{
+ // Human redable description of the rule
+ Description: "Identified a Defined Networking API token, which could lead to unauthorized network operations and data breaches.",
+
+ // Unique ID for the rule
+ RuleID: "defined-networking-api-token",
+
+ // Regex used for detecting secrets. See regex section below for more details
+ 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"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("dnkey", "dnkey-"+secrets.NewSecret(utils.AlphaNumericExtended("26"))+"-"+secrets.NewSecret(utils.AlphaNumericExtended("52")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/digitalocean.go b/cmd/generate/config/rules/digitalocean.go
new file mode 100644
index 0000000..1bc2262
--- /dev/null
+++ b/cmd/generate/config/rules/digitalocean.go
@@ -0,0 +1,46 @@
+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"
+)
+
+func DigitalOceanPAT() *config.Rule {
+ r := config.Rule{
+ RuleID: "digitalocean-pat",
+ Description: "Discovered a DigitalOcean Personal Access Token, posing a threat to cloud infrastructure security and data privacy.",
+ Regex: utils.GenerateUniqueTokenRegex(`dop_v1_[a-f0-9]{64}`, false),
+ Entropy: 3,
+ Keywords: []string{"dop_v1_"},
+ }
+
+ tps := utils.GenerateSampleSecrets("do", "dop_v1_"+secrets.NewSecret(utils.Hex("64")))
+ return utils.Validate(r, tps, nil)
+}
+
+func DigitalOceanOAuthToken() *config.Rule {
+ r := config.Rule{
+ RuleID: "digitalocean-access-token",
+ Description: "Found a DigitalOcean OAuth Access Token, risking unauthorized cloud resource access and data compromise.",
+ Entropy: 3,
+ Regex: utils.GenerateUniqueTokenRegex(`doo_v1_[a-f0-9]{64}`, false),
+ Keywords: []string{"doo_v1_"},
+ }
+
+ tps := utils.GenerateSampleSecrets("do", "doo_v1_"+secrets.NewSecret(utils.Hex("64")))
+ return utils.Validate(r, tps, nil)
+}
+
+func DigitalOceanRefreshToken() *config.Rule {
+ r := config.Rule{
+ Description: "Uncovered a DigitalOcean OAuth Refresh Token, which could allow prolonged unauthorized access and resource manipulation.",
+ RuleID: "digitalocean-refresh-token",
+
+ Regex: utils.GenerateUniqueTokenRegex(`dor_v1_[a-f0-9]{64}`, true),
+ Keywords: []string{"dor_v1_"},
+ }
+
+ tps := utils.GenerateSampleSecrets("do", "dor_v1_"+secrets.NewSecret(utils.Hex("64")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/discord.go b/cmd/generate/config/rules/discord.go
new file mode 100644
index 0000000..b458dbe
--- /dev/null
+++ b/cmd/generate/config/rules/discord.go
@@ -0,0 +1,61 @@
+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"
+)
+
+func DiscordAPIToken() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "discord-api-token",
+ Description: "Detected a Discord API key, potentially compromising communication channels and user data privacy on Discord.",
+ Regex: utils.GenerateSemiGenericRegex([]string{"discord"}, utils.Hex("64"), true),
+ Keywords: []string{"discord"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("discord", secrets.NewSecret(utils.Hex("64")))
+ return utils.Validate(r, tps, nil)
+}
+
+func DiscordClientID() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "discord-client-id",
+ Description: "Identified a Discord client ID, which may lead to unauthorized integrations and data exposure in Discord applications.",
+ Regex: utils.GenerateSemiGenericRegex([]string{"discord"}, utils.Numeric("18"), true),
+ Entropy: 2,
+ Keywords: []string{"discord"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("discord", secrets.NewSecret(utils.Numeric("18")))
+ fps := []string{
+ // Low entropy
+ `discord=000000000000000000`,
+ }
+ return utils.Validate(r, tps, fps)
+}
+
+func DiscordClientSecret() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "discord-client-secret",
+ Description: "Discovered a potential Discord client secret, risking compromised Discord bot integrations and data leaks.",
+ Regex: utils.GenerateSemiGenericRegex([]string{"discord"}, utils.AlphaNumericExtended("32"), true),
+ Entropy: 2,
+ Keywords: []string{"discord"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("discord", secrets.NewSecret(utils.Numeric("32")))
+ fps := []string{
+ // Low entropy
+ `discord=00000000000000000000000000000000`,
+ // TODO:
+ //`discord=01234567890123456789012345678901`,
+ }
+ return utils.Validate(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/doppler.go b/cmd/generate/config/rules/doppler.go
new file mode 100644
index 0000000..c5d2dde
--- /dev/null
+++ b/cmd/generate/config/rules/doppler.go
@@ -0,0 +1,26 @@
+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"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+func Doppler() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "doppler-api-token",
+ Description: "Discovered a Doppler API token, posing a risk to environment and secrets management security.",
+ Regex: regexp.MustCompile(`dp\.pt\.(?i)[a-z0-9]{43}`),
+ Entropy: 2,
+ Keywords: []string{`dp.pt.`},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("doppler", "dp.pt."+secrets.NewSecret(utils.AlphaNumeric("43")))
+ return utils.Validate(r, tps, nil)
+}
+
+// TODO add additional doppler formats:
+// https://docs.doppler.com/reference/auth-token-formats
diff --git a/cmd/generate/config/rules/droneci.go b/cmd/generate/config/rules/droneci.go
new file mode 100644
index 0000000..e16aa85
--- /dev/null
+++ b/cmd/generate/config/rules/droneci.go
@@ -0,0 +1,24 @@
+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"
+)
+
+func DroneciAccessToken() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "droneci-access-token",
+ Description: "Detected a Droneci Access Token, potentially compromising continuous integration and deployment workflows.",
+ Regex: utils.GenerateSemiGenericRegex([]string{"droneci"}, utils.AlphaNumeric("32"), true),
+
+ Keywords: []string{
+ "droneci",
+ },
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("droneci", secrets.NewSecret(utils.AlphaNumeric("32")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/dropbox.go b/cmd/generate/config/rules/dropbox.go
new file mode 100644
index 0000000..affd2b4
--- /dev/null
+++ b/cmd/generate/config/rules/dropbox.go
@@ -0,0 +1,48 @@
+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"
+)
+
+func DropBoxAPISecret() *config.Rule {
+ // define 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: utils.GenerateSemiGenericRegex([]string{"dropbox"}, utils.AlphaNumeric("15"), true),
+
+ Keywords: []string{"dropbox"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("dropbox", secrets.NewSecret(utils.AlphaNumeric("15")))
+ return utils.Validate(r, tps, nil)
+}
+
+func DropBoxShortLivedAPIToken() *config.Rule {
+ // define 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: utils.GenerateSemiGenericRegex([]string{"dropbox"}, `sl\.[a-z0-9\-=_]{135}`, true),
+ Keywords: []string{"dropbox"},
+ }
+
+ // validate TODO
+ return &r
+}
+
+func DropBoxLongLivedAPIToken() *config.Rule {
+ // define 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: utils.GenerateSemiGenericRegex([]string{"dropbox"}, `[a-z0-9]{11}(AAAAAAAAAA)[a-z0-9\-_=]{43}`, true),
+ Keywords: []string{"dropbox"},
+ }
+
+ // validate TODO
+ return &r
+}
diff --git a/cmd/generate/config/rules/duffel.go b/cmd/generate/config/rules/duffel.go
new file mode 100644
index 0000000..e7522dd
--- /dev/null
+++ b/cmd/generate/config/rules/duffel.go
@@ -0,0 +1,23 @@
+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"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+func Duffel() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "duffel-api-token",
+ Description: "Uncovered a Duffel API token, which may compromise travel platform integrations and sensitive customer data.",
+ Regex: regexp.MustCompile(`duffel_(?:test|live)_(?i)[a-z0-9_\-=]{43}`),
+ Entropy: 2,
+ Keywords: []string{"duffel_"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("duffel", "duffel_test_"+secrets.NewSecret(utils.AlphaNumericExtended("43")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/dynatrace.go b/cmd/generate/config/rules/dynatrace.go
new file mode 100644
index 0000000..5f1c12b
--- /dev/null
+++ b/cmd/generate/config/rules/dynatrace.go
@@ -0,0 +1,23 @@
+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"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+func Dynatrace() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "dynatrace-api-token",
+ Description: "Detected a Dynatrace API token, potentially risking application performance monitoring and data exposure.",
+ Regex: regexp.MustCompile(`dt0c01\.(?i)[a-z0-9]{24}\.[a-z0-9]{64}`),
+ Entropy: 4,
+ Keywords: []string{"dt0c01."},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("dynatrace", "dt0c01."+secrets.NewSecret(utils.AlphaNumeric("24"))+"."+secrets.NewSecret(utils.AlphaNumeric("64")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/easypost.go b/cmd/generate/config/rules/easypost.go
new file mode 100644
index 0000000..509e2db
--- /dev/null
+++ b/cmd/generate/config/rules/easypost.go
@@ -0,0 +1,55 @@
+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"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+func EasyPost() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "easypost-api-token",
+ Description: "Identified an EasyPost API token, which could lead to unauthorized postal and shipment service access and data exposure.",
+ Regex: regexp.MustCompile(`\bEZAK(?i)[a-z0-9]{54}\b`),
+ Entropy: 2,
+ Keywords: []string{"EZAK"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("EZAK", "EZAK"+secrets.NewSecret(`[a-zA-Z0-9]{54}`))
+ tps = append(tps,
+ "EZAK"+secrets.NewSecret(`[a-zA-Z0-9]{54}`),
+ "example.com?t=EZAK"+secrets.NewSecret(`[a-zA-Z0-9]{54}`)+"&q=1",
+ )
+ fps := []string{
+ // random base64 encoded string
+ `...6wqX6fNUXA/rYqRvfQ+EZAKGqQRiRyqAFRQshGPWOIAwNWGORfKHSBnVNFtVmWYoW6PH23lkqbbDWep95C/3VmWq/edti6...`, // gitleaks:allow
+ }
+ return utils.Validate(r, tps, fps)
+}
+
+func EasyPostTestAPI() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "easypost-test-api-token",
+ Description: "Detected an EasyPost test API token, risking exposure of test environments and potentially sensitive shipment data.",
+ Regex: regexp.MustCompile(`\bEZTK(?i)[a-z0-9]{54}\b`),
+ Entropy: 2,
+ Keywords: []string{"EZTK"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("EZTK", secrets.NewSecret(`EZTK[a-zA-Z0-9]{54}`))
+ tps = append(tps, secrets.NewSecret(`EZTK[a-zA-Z0-9]{54}`))
+ tps = append(tps,
+ "EZTK"+secrets.NewSecret(`[a-zA-Z0-9]{54}`),
+ "example.com?t=EZTK"+secrets.NewSecret(`[a-zA-Z0-9]{54}`)+"&q=1",
+ )
+ fps := []string{
+ // random base64 encoded string
+ `...6wqX6fNUXA/rYqRvfQ+EZTKGqQRiRyqAFRQshGPWOIAwNWGORfKHSBnVNFtVmWYoW6PH23lkqbbDWep95C/3VmWq/edti6...`, // gitleaks:allow
+ }
+ return utils.Validate(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/etsy.go b/cmd/generate/config/rules/etsy.go
new file mode 100644
index 0000000..3107a8c
--- /dev/null
+++ b/cmd/generate/config/rules/etsy.go
@@ -0,0 +1,34 @@
+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"
+)
+
+func EtsyAccessToken() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "etsy-access-token",
+ Description: "Found an Etsy Access Token, potentially compromising Etsy shop management and customer data.",
+ Regex: utils.GenerateSemiGenericRegex([]string{"(?-i:ETSY|[Ee]tsy)"}, utils.AlphaNumeric("24"), true),
+ Entropy: 3,
+ Keywords: []string{
+ "etsy",
+ },
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("ETSY", secrets.NewSecret(utils.AlphaNumeric("24")))
+ tps = append(tps, utils.GenerateSampleSecrets("etsy", secrets.NewSecret(utils.AlphaNumeric("24")))...)
+ tps = append(tps, utils.GenerateSampleSecrets("Etsy", secrets.NewSecret(utils.AlphaNumeric("24")))...)
+ fps := []string{
+ fmt.Sprintf(`SetSysctl = "%s"`, secrets.NewSecret(utils.AlphaNumeric("24"))),
+ ` if err := sysctl.SetSysctl(sysctlBridgeCallIPTables); err != nil {`,
+ `g6Rib2R5hqhkZXRhY2hlZMOpaGFzaF90eXBlCqNrZXnEIwEgETSYcPQGcaAxl8vuQDLahSfhxkEEHu2flbF9ErAooEoKp3BheWxvYWTFAwB7ImJvZHkiOnsia2V5Ijp7ImVsZGVzdF9raWQiOiIwMTIwMTEzNDk4NzBmNDA2NzFhMDMxOTdjYmVlNDAzMmRhODUyN2UxYzY0MTA0MWVlZDlmOTViMTdkMTJiMDI4YTA0YTBhIiwiaG9zdCI6ImtleWJhc2UuaW8iLCJraWQiOiIwMTIwMTEzNDk4NzBmNDA2NzFhMDMxOTdjYmVlNDAzMmRhODUyN2UxYzY0MTA0MWVlZDlmOTViMTdkMTJiMDI4YTA0YTBhIiwidWlkIjoiYzUyZjc2M2MxNzYyNWZiMTI5YWU1ZDZmZThhMGUzMTkiLCJ1c2VybmFtZSI6ImttYXJla3NwYXJ0eiJ9LCJzZXJ2aWNlIjp7Imhvc3RuYW1lIjoia3lsZS5tYXJlay1zcGFydHoub3JnIiwicHJvdG9jb2wiOiJodHRwOiJ9LCJ0eXBlIjoid2ViX3NlcnZpY2VfYmluZGluZyIsInZlcnNpb24iOjF9LCJjbGllbnQiOnsibmFtZSI6ImtleWJhc2UuaW8gZ28gY2xpZW50IiwidmVyc2lvbiI6IjEuMC4xNCJ9LCJjdGltZSI6MTQ1ODU5MDYyMSwiZXhwaXJlX2luIjo1MDQ1NzYwMDAsIm1lcmtsZV9yb290Ijp7ImN0aW1lIjoxNDU4NTkwNTgzLCJoYXNoIjoiODQ0ZWRkNGU0OTQ3MWUzNWQxZTFkOTM5YTc0ZjUwMDc5Nzg3NzljMTAwYzY1NGE2OGI1NDNhYzY2Y2NlYTQ1MGFjNTllNmY3Yjc4ZGZiN2MyYzdjMmYwMzJiYTA2MzdjMzVjZDk1ZGYyZmRiNjFlNjgxMjVmNDkxNjVlZDkwNzMiLCJzZXFubyI6NDE3Mjk5fSwicHJldiI6IjdmNWFkMGZlZmQxNjM4ZjBlOTc1MTk3NzA5YTk2OTVkZmQ1NzU0MTA4NTYxZGUzMDM0ODc2NDcxODdhMDkyYzUiLCJzZXFubyI6OSwidGFnIjoic2lnbmF0dXJlIn2jc2lnxEDDVCB/SdOzo+BznIUCCa5DgISbH+0noUjyAJ4r0sH/tj8lYNpHw3WR93SBCufeElsl7KrxVdg5qU5ADYj26wgOqHNpZ190eXBlIKN0YWfNAgKndmVyc2lvbgE=`,
+ `in XCBuild.XCBBuildServiceSession.setSystemInfo(operatingSystemVersion: __C.NSOperatingSystemVersion, productBuildVersion: Swift.String, nativeArchitecture: Swift.String, completion: (Swift.Bool) -> ()) -> ()`,
+ }
+ return utils.Validate(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/facebook.go b/cmd/generate/config/rules/facebook.go
new file mode 100644
index 0000000..e53dfcc
--- /dev/null
+++ b/cmd/generate/config/rules/facebook.go
@@ -0,0 +1,78 @@
+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"
+)
+
+// This rule includes both App Secret and Client Access Token
+// https://developers.facebook.com/docs/facebook-login/guides/access-tokens/
+func FacebookSecret() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "facebook-secret",
+ Description: "Discovered a Facebook Application secret, posing a risk of unauthorized access to Facebook accounts and personal data exposure.",
+ Regex: utils.GenerateSemiGenericRegex([]string{"facebook"}, utils.Hex("32"), true),
+ Entropy: 3,
+ Keywords: []string{"facebook"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("facebook", secrets.NewSecret(utils.Hex("32")))
+ tps = append(tps,
+ `facebook_app_secret = "6dca6432e45d933e13650d1882bd5e69"`, // gitleaks:allow
+ `facebook_client_access_token: 26f5fd13099f2c1331aafb86f6489692`, // gitleaks:allow
+ )
+ return utils.Validate(r, tps, nil)
+}
+
+// https://developers.facebook.com/docs/facebook-login/guides/access-tokens/#apptokens
+func FacebookAccessToken() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "facebook-access-token",
+ Description: "Discovered a Facebook Access Token, posing a risk of unauthorized access to Facebook accounts and personal data exposure.",
+ Regex: utils.GenerateUniqueTokenRegex(`\d{15,16}(\||%)[0-9a-z\-_]{27,40}`, true),
+ Keywords: []string{"facebook"},
+ Entropy: 3,
+ }
+
+ // validate
+ tps := []string{
+ `{"facebook access_token":"911602140448729|AY-lRJZq9BoDLobvAiP25L7RcMg","token_type":"bearer"}`, // gitleaks:allow
+ `facebook 1308742762612587|rhoK1cbv0DOU_RTX_87O4MkX7AI`, // gitleaks:allow
+ `facebook 1477036645700765|wRPf2v3mt2JfMqCLK8n7oltrEmc`, // gitleaks:allow
+ }
+ return utils.Validate(r, tps, nil)
+}
+
+// https://developers.facebook.com/docs/facebook-login/guides/access-tokens/#pagetokens
+func FacebookPageAccessToken() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "facebook-page-access-token",
+ Description: "Discovered a Facebook Page Access Token, posing a risk of unauthorized access to Facebook accounts and personal data exposure.",
+ Regex: utils.GenerateUniqueTokenRegex("EAA[MC](?i)[a-z0-9]{100,}", false),
+ Entropy: 4,
+ Keywords: []string{"EAAM", "EAAC"},
+ }
+
+ // validate
+ tps := []string{
+ `EAAM9GOnCB9kBO2frzOAWGN2zMnZClQshlWydZCrBNdodesbwimx1mfVJgqZBP5RSpMfUzWhtjTTXHG5I1UlvlwRZCgjm3ZBVGeTYiqAAoxyED6HaUdhpGVNoPUwAuAWWFsi9OvyYBQt22DGLqMIgD7VktuCTTZCWKasz81Q822FPhMTB9VFFyClNzQ0NLZClt9zxpsMMrUZCo1VU1rL3CKavir5QTfBjfCEzHNlWAUDUV2YZD`, // gitleaks:allow
+ `EAAM9GOnCB9kBO2zXpAtRBmCrsPPjdA3KeBl4tqsEpcYd09cpjm9MZCBIklZBjIQBKGIJgFwm8IE17G5pipsfRBRBEHMWxvJsL7iHLUouiprxKRQfAagw8BEEDucceqxTiDhVW2IZAQNNbf0d1JhcapAGntx5S1Csm4j0GgZB3DuUfI2HJ9aViTtdfH2vjBy0wtpXm2iamevohGfoF4NgyRHusDLjqy91uYMkfrkc`, // gitleaks:allow
+ `- name: FACEBOOK_TOKEN
+ value: "EAACEdEose0cBA1bad3afsf286JZCOV1XmV4NobAXqUXZA7U9F1UaaOdQZABvz73030MJoC3gGoQrE8IEoMl4gFA6MmQadlJQBqtRsgIcIhtelIJOJaew"`, // gitleaks:allow
+ }
+ fps := []string{
+ `eaaaC0b75a9329fded2ffa9a02b47e0117831b82`,
+ `"strict-uri-encode@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "strict-uri-encode@npm:2.0.0"
+ checksum: eaac4cf978b6fbd480f1092cab8b233c9b949bcabfc9b598dd79a758f7243c28765ef7639c876fa72940dac687181b35486ea01ff7df3e65ce3848c64822c581
+ languageName: node
+ linkType: hard`,
+ }
+ return utils.Validate(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/fastly.go b/cmd/generate/config/rules/fastly.go
new file mode 100644
index 0000000..6686da7
--- /dev/null
+++ b/cmd/generate/config/rules/fastly.go
@@ -0,0 +1,22 @@
+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"
+)
+
+func FastlyAPIToken() *config.Rule {
+ // define 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: utils.GenerateSemiGenericRegex([]string{"fastly"}, utils.AlphaNumericExtended("32"), true),
+
+ Keywords: []string{"fastly"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("fastly", secrets.NewSecret(utils.AlphaNumericExtended("32")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/finicity.go b/cmd/generate/config/rules/finicity.go
new file mode 100644
index 0000000..14b61c9
--- /dev/null
+++ b/cmd/generate/config/rules/finicity.go
@@ -0,0 +1,37 @@
+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"
+)
+
+func FinicityClientSecret() *config.Rule {
+ // define 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: utils.GenerateSemiGenericRegex([]string{"finicity"}, utils.AlphaNumeric("20"), true),
+
+ Keywords: []string{"finicity"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("finicity", secrets.NewSecret(utils.AlphaNumeric("20")))
+ return utils.Validate(r, tps, nil)
+}
+
+func FinicityAPIToken() *config.Rule {
+ // define rule
+ r := config.Rule{
+ Description: "Detected a Finicity API token, potentially risking financial data access and unauthorized financial operations.",
+ RuleID: "finicity-api-token",
+ Regex: utils.GenerateSemiGenericRegex([]string{"finicity"}, utils.Hex("32"), true),
+
+ Keywords: []string{"finicity"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("finicity", secrets.NewSecret(utils.Hex("32")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/finnhub.go b/cmd/generate/config/rules/finnhub.go
new file mode 100644
index 0000000..4826903
--- /dev/null
+++ b/cmd/generate/config/rules/finnhub.go
@@ -0,0 +1,24 @@
+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"
+)
+
+func FinnhubAccessToken() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "finnhub-access-token",
+ Description: "Found a Finnhub Access Token, risking unauthorized access to financial market data and analytics.",
+ Regex: utils.GenerateSemiGenericRegex([]string{"finnhub"}, utils.AlphaNumeric("20"), true),
+
+ Keywords: []string{
+ "finnhub",
+ },
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("finnhub", secrets.NewSecret(utils.AlphaNumeric("20")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/flickr.go b/cmd/generate/config/rules/flickr.go
new file mode 100644
index 0000000..575d54a
--- /dev/null
+++ b/cmd/generate/config/rules/flickr.go
@@ -0,0 +1,24 @@
+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"
+)
+
+func FlickrAccessToken() *config.Rule {
+ // define 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: utils.GenerateSemiGenericRegex([]string{"flickr"}, utils.AlphaNumeric("32"), true),
+
+ Keywords: []string{
+ "flickr",
+ },
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("flickr", secrets.NewSecret(utils.AlphaNumeric("32")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/flutterwave.go b/cmd/generate/config/rules/flutterwave.go
new file mode 100644
index 0000000..3db76d5
--- /dev/null
+++ b/cmd/generate/config/rules/flutterwave.go
@@ -0,0 +1,53 @@
+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"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+func FlutterwavePublicKey() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "flutterwave-public-key",
+ Description: "Detected a Finicity Public Key, potentially exposing public cryptographic operations and integrations.",
+ Regex: regexp.MustCompile(`FLWPUBK_TEST-(?i)[a-h0-9]{32}-X`),
+ Entropy: 2,
+ Keywords: []string{"FLWPUBK_TEST"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("flutterwavePubKey", "FLWPUBK_TEST-"+secrets.NewSecret(utils.Hex("32"))+"-X")
+ return utils.Validate(r, tps, nil)
+}
+
+func FlutterwaveSecretKey() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "flutterwave-secret-key",
+ Description: "Identified a Flutterwave Secret Key, risking unauthorized financial transactions and data breaches.",
+ Regex: regexp.MustCompile(`FLWSECK_TEST-(?i)[a-h0-9]{32}-X`),
+ Entropy: 2,
+ Keywords: []string{"FLWSECK_TEST"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("flutterwavePubKey", "FLWSECK_TEST-"+secrets.NewSecret(utils.Hex("32"))+"-X")
+ return utils.Validate(r, tps, nil)
+}
+
+func FlutterwaveEncKey() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "flutterwave-encryption-key",
+ Description: "Uncovered a Flutterwave Encryption Key, which may compromise payment processing and sensitive financial information.",
+ Regex: regexp.MustCompile(`FLWSECK_TEST-(?i)[a-h0-9]{12}`),
+ Entropy: 2,
+ Keywords: []string{"FLWSECK_TEST"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("flutterwavePubKey", "FLWSECK_TEST-"+secrets.NewSecret(utils.Hex("12")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/flyio.go b/cmd/generate/config/rules/flyio.go
new file mode 100644
index 0000000..9830a10
--- /dev/null
+++ b/cmd/generate/config/rules/flyio.go
@@ -0,0 +1,57 @@
+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"
+)
+
+// https://fly.io/docs/security/tokens/
+// https://github.com/trufflesecurity/trufflehog/pull/2381/files#r1565860579
+// https://github.com/superfly/macaroon-elixir/blob/8b42043b0a24aada5c8b8eb8505dbf1590557f1b/test/vectors.json#L7
+func FlyIOAccessToken() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "flyio-access-token",
+ Description: "Uncovered a Fly.io API key", // TODO
+ Regex: utils.GenerateUniqueTokenRegex(`(?:fo1_[\w-]{43}|fm1[ar]_[a-zA-Z0-9+\/]{100,}={0,3}|fm2_[a-zA-Z0-9+\/]{100,}={0,3})`, false),
+ Entropy: 4,
+ Keywords: []string{"fo1_", "fm1", "fm2_"},
+ }
+
+ // validate
+ // fo1_
+ tps := utils.GenerateSampleSecrets("fly", secrets.NewSecret(`fo1_[\w-]{43}`))
+ tps = append(tps,
+ `Fly access token: fo1_8rz-j7r2eqJ2U7affEOO3HJN0j63DInyog3eV-glQSc
+`,
+ `=============================================================================================================
+
+fo1_BtKlzvfztw0M2hlLgTdsfPgDFiwM2jJjQXXy6I2pjuQ
+fly deploy`)
+ // fm1
+ tps = append(tps, utils.GenerateSampleSecrets("fly", secrets.NewSecret(`fm1[ar]_[a-zA-Z0-9+\/]{100,}={0,3}`))...)
+ tps = append(tps,
+ `ENV FLY_API_TOKEN="FlyV1 fm1r_lJPECAAAAAAAAMqcxBBLMJKXYKJiT0CI58XmukX/wrVodHlwczovL2FwaS5mbHkuaW8vdjGWAJLOAAFmXh8Lk7lodHRwczovL2FwaS5mbHkuaW8vYWFhL3YxxDy5OfA2M6K6aLEoEDKxehojbj+8ZT9IrXCF5sL/r8m6/1gylwySsNxpD40wnpd/G2ZdjwVaQev1kEuFUgzERxPbtWHDNa+NYIZwbKN6b7/JxdbUprq0M10HI4fwtlxhqhdA/mMaMw70EC4TsfJyghIL98KP4ry5AaXiroRdjrSsFExc/xRCDZKUA5GBzgATuNsfBZGCp2J1aWxkZXIfondnHwHEIMa6NWc4b52S+UY7vjPdwKrz00Uzrc1830mOHzQNLun7,fm1a_lJPERxPbtWHDNa+NYIZwbKN6b7/JxdbUprq0M10HI4fwtlxhqhdA/mMaMw70EC4TsfJyghIL98KP4ry4AaXiroRdjrSsFExc/xRCxBCVlAoRzKV/+qYkxuipIbIcw7lodHRwczovL2FwaS5mbHkuaW8vYWFhL3YxlgSSzmS4Y7nPAAAAASCwgdcKkc4AAUktDMQQURck2h+upbiOrW66Nf5SA8QgrD03xlWju1WQi0AUhlk7YYFzOLDfhRyJ6nEziO37NUE="`,
+ )
+ // fm2
+ tps = append(tps, utils.GenerateSampleSecrets("fly", secrets.NewSecret(`fm2_[a-zA-Z0-9+\/]{100,}={0,3}`))...)
+ tps = append(tps,
+ `# FLY_API_TOKEN: FlyV1 fm2_lJPECAAAAAAAAyZtxBD1hSZ7L5leXsj64ZbDlkm/wrVodHRwczovL2FwaS5mbHkuaW8vdjGWAJLOAAwMDB8Lk7lodHRwczovL2FwaS5mbHkuaW8vYWFhL3YxxDwDnhgJj/ML/nRKMiAYgnvXfNacrGWffj5TdfgGY2LU0ZetT7WzTLQQMO8cN2nRTztl/xLjnnZg5pBwFonETmhNA6Yl0X1tatt8ezA0UjVQiJr93VQ7qAmD5GG2Ce5txhbQv3tmIGsvaC7BOkIqAiR273bhZkO44AYsrCPr2XF8W6Twk7NyU+3UUeDwjw2SlAORgc4APu7vHwWRgqdidWlsZGVyH6J3Zx8BxCAlmLbu1HQDg8ZAGKKmEt4Mbnbqli6lbzBDHsawhcUF4A==,fm2_lJPETmhNA6Yl0X1tatt8ezA0UjVQiJr93VQ7qAmD5GG2Ce5txhbQv3tmIGsvaC7BOkIqAij273bhZkO44AYsrCPr2XF8W6Twk7NyU+3UUeDwj8QQbn07DOV+7SmoLj/uT+dbr8O5aHR0cHM6Ly9hcGkuZmx5LmlvL2FhYS92MZgEks5mqfbvzwAAAAE9PYz9F84AC7QACpHOAAu0AAzEEFfW3B+SzffV/KrAYa8qqpnEIIlD6DqZMZQ9Kt7fEenCCOLA+tUSJ+kmEFIUcc83npOI`,
+ `"BindToParentToken": "FlyV1 fm2_lJPEEKnzKy0lkwV3B+WIlmrdwejEEFv5qmevHU4fMs+2Gr6oOiPC2SAyOTc0NWI4ZmJlNjBlNjJmZTgzNTkxOThhZWE4MjY0M5IMxAMBAgPEIH7VG8u74KwO62hmx8SZO8WaU5o1g3W2IVc7QN6T1VTr",`,
+ )
+ fps := []string{
+ // fo1_
+ `resource "doppler_integration_flyio" "prod" {
+ name = "TF Fly.io"
+ api_key = "fo1_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+}`, // https://github.com/DopplerHQ/terraform-provider-doppler/blob/a012e1a7903cce391be511b391850b29ebfdeb68/docs/resources/integration_flyio.md?plain=1#L17
+ `pub const MINIDUMP_SYSMEMINFO1_PERF_CCTOTALDIRTYPAGES_CCDIRTYPAGETHRESHOLD: u32 = 4u32;`, // https://github.com/microsoft/windows-rs/blob/0f7466c34e774e547d21c579b58b60168c4ee6bc/crates/libs/sys/src/Windows/Win32/System/Diagnostics/Debug/mod.rs#L1258
+ ``,
+ // fm1
+ `signature":"I7l2ZXhw9ajjIE2w9tjHNvYjcHg7E2qldMMhoQKjborcWIj8c40rMj83venoy6gXsg6V6B7dlBWxUmzYJR3lJKGECtCSM5BqBvWhL6wX2CN2lZlvwNCyPjG4PCt5MAK1yV1Xv4fqfz8EfT_U49vOzfM1a_nfhXOzrvdg9XgLkAotWBI31vPKjMBrvPqiLcZ12MDNTSK7ubRpVaehSNxiGYHpLhWTkun9qm_APYYXJBjhJYkej50Qcp7Ou8fs3kH02prYIJt4JbWelr5vUDkgMH3AwEx1eYu5NI_8sESlqosl1nhSDx7zq3X1FV1iJlAYCNwGWzW1tjo8PCaJrIHVZZnhBPMN-6ahmOpKb8GViqd4fCQuNe4VUSOeJg8i97kMuk-4r7hwIubR0XfCGzxr7uGDQBdFANi3c4dLlzBAJNifa6b_hT4Xzqja6RCFSv6Cnalyx3hbSkjbyThnXFavJIiR7cvgTcdECg9VxkaxqqRhfAkLAS3hpXQAIYL_bw61M3LN37WHwdgxN_6yZhbSbOsYPmTxiWvdlDaCP_iaCgXgJNfdQ6kep_I89slynE9gdDZ6NSjFJH2Soml4pR6HnQKPjA3OpoTwPSmZjxXY5I78xvrRqRkjdnVzeufqG8LyA-sAEtC0G_312JOxV4GZINquPGk1qFx8WN59Rxw28Tg",`,
+ // fm2
+ `🗣️ Adobe illustrator软件基础精讲课程
🏷️ #设计师 #资源 #夸克网盘
👉 https://www.ahhhhfs.com/62409/
`,
+ }
+ return utils.Validate(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/frameio.go b/cmd/generate/config/rules/frameio.go
new file mode 100644
index 0000000..ea1e974
--- /dev/null
+++ b/cmd/generate/config/rules/frameio.go
@@ -0,0 +1,22 @@
+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"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+func FrameIO() *config.Rule {
+ // define rule
+ r := config.Rule{
+ Description: "Found a Frame.io API token, potentially compromising video collaboration and project management.",
+ RuleID: "frameio-api-token",
+ Regex: regexp.MustCompile(`fio-u-(?i)[a-z0-9\-_=]{64}`),
+ Keywords: []string{"fio-u-"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("frameio", "fio-u-"+secrets.NewSecret(utils.AlphaNumericExtended("64")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/freemius.go b/cmd/generate/config/rules/freemius.go
new file mode 100644
index 0000000..3716ffe
--- /dev/null
+++ b/cmd/generate/config/rules/freemius.go
@@ -0,0 +1,47 @@
+package rules
+
+import (
+ "github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
+ "github.com/zricethezav/gitleaks/v8/config"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+func Freemius() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "freemius-secret-key",
+ Description: "Detected a Freemius secret key, potentially exposing sensitive information.",
+ Regex: regexp.MustCompile(`(?i)["']secret_key["']\s*=>\s*["'](sk_[\S]{29})["']`),
+ Keywords: []string{"secret_key"},
+ Path: regexp.MustCompile(`(?i)\.php$`),
+ }
+
+ // validate
+ tps := map[string]string{
+ "file.php": `$config = array(
+ "secret_key" => "sk_ubb4yN3mzqGR2x8#P7r5&@*xC$utE",
+ );`,
+ }
+ // It's only used in PHP SDK snippet.
+ // see https://freemius.com/help/documentation/wordpress-sdk/integrating-freemius-sdk/
+ fps := map[string]string{
+ // Invalid format: missing quotes around `secret_key`.
+ "foo.php": `$config = array(
+ secret_key => "sk_abcdefghijklmnopqrstuvwxyz123",
+ );`,
+ // Invalid format: missing quotes around the key value.
+ "bar.php": `$config = array(
+ "secret_key" => sk_abcdefghijklmnopqrstuvwxyz123,
+ );`,
+ // Invalid: different key name.
+ "baz.php": `$config = array(
+ "other_key" => "sk_abcdefghijklmnopqrstuvwxyz123",
+ );`,
+ // Invalid: file extension, should validate only .php files.
+ "foo.html": `$config = array(
+ "secret_key" => "sk_ubb4yN3mzqGR2x8#P7r5&@*xC$utE",
+ );`,
+ }
+
+ return utils.ValidateWithPaths(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/freshbooks.go b/cmd/generate/config/rules/freshbooks.go
new file mode 100644
index 0000000..f63d414
--- /dev/null
+++ b/cmd/generate/config/rules/freshbooks.go
@@ -0,0 +1,24 @@
+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"
+)
+
+func FreshbooksAccessToken() *config.Rule {
+ // define 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: utils.GenerateSemiGenericRegex([]string{"freshbooks"}, utils.AlphaNumeric("64"), true),
+
+ Keywords: []string{
+ "freshbooks",
+ },
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("freshbooks", secrets.NewSecret(utils.AlphaNumeric("64")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/gcp.go b/cmd/generate/config/rules/gcp.go
new file mode 100644
index 0000000..d6ef8a5
--- /dev/null
+++ b/cmd/generate/config/rules/gcp.go
@@ -0,0 +1,90 @@
+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"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+// TODO this one could probably use some work
+func GCPServiceAccount() *config.Rule {
+ // define rule
+ r := config.Rule{
+ Description: "Google (GCP) Service-account",
+ RuleID: "gcp-service-account",
+ Regex: regexp.MustCompile(`\"type\": \"service_account\"`),
+ Keywords: []string{`\"type\": \"service_account\"`},
+ }
+
+ // validate
+ tps := []string{
+ `"type": "service_account"`,
+ }
+ return utils.Validate(r, tps, nil)
+}
+
+func GCPAPIKey() *config.Rule {
+ // define 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: utils.GenerateUniqueTokenRegex(`AIza[\w-]{35}`, false),
+ Entropy: 4,
+ Keywords: []string{"AIza"},
+ Allowlists: []*config.Allowlist{
+ {
+ Regexes: []*regexp.Regexp{
+ // example keys from https://github.com/firebase/firebase-android-sdk
+ regexp.MustCompile(`AIzaSyabcdefghijklmnopqrstuvwxyz1234567`),
+ regexp.MustCompile(`AIzaSyAnLA7NfeLquW1tJFpx_eQCxoX-oo6YyIs`),
+ regexp.MustCompile(`AIzaSyCkEhVjf3pduRDt6d1yKOMitrUEke8agEM`),
+ regexp.MustCompile(`AIzaSyDMAScliyLx7F0NPDEJi1QmyCgHIAODrlU`),
+ regexp.MustCompile(`AIzaSyD3asb-2pEZVqMkmL6M9N6nHZRR_znhrh0`),
+ regexp.MustCompile(`AIzayDNSXIbFmlXbIE6mCzDLQAqITYefhixbX4A`),
+ regexp.MustCompile(`AIzaSyAdOS2zB6NCsk1pCdZ4-P6GBdi_UUPwX7c`),
+ regexp.MustCompile(`AIzaSyASWm6HmTMdYWpgMnjRBjxcQ9CKctWmLd4`),
+ regexp.MustCompile(`AIzaSyANUvH9H9BsUccjsu2pCmEkOPjjaXeDQgY`),
+ regexp.MustCompile(`AIzaSyA5_iVawFQ8ABuTZNUdcwERLJv_a_p4wtM`),
+ regexp.MustCompile(`AIzaSyA4UrcGxgwQFTfaI3no3t7Lt1sjmdnP5sQ`),
+ regexp.MustCompile(`AIzaSyDSb51JiIcB6OJpwwMicseKRhhrOq1cS7g`),
+ regexp.MustCompile(`AIzaSyBF2RrAIm4a0mO64EShQfqfd2AFnzAvvuU`),
+ regexp.MustCompile(`AIzaSyBcE-OOIbhjyR83gm4r2MFCu4MJmprNXsw`),
+ regexp.MustCompile(`AIzaSyB8qGxt4ec15vitgn44duC5ucxaOi4FmqE`),
+ regexp.MustCompile(`AIzaSyA8vmApnrHNFE0bApF4hoZ11srVL_n0nvY`),
+ },
+ },
+ },
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("gcp", secrets.NewSecret(`AIza[\w-]{35}`))
+ tps = append(tps,
+ // non-word character at end
+ `AIzaSyNHxIf32IQ1a1yjl3ZJIqKZqzLAK1XhDk-`, // gitleaks:allow
+ )
+ fps := []string{
+ `GWw4hjABFzZCGiRpmlDyDdo87Jn9BN9THUA47muVRNunLxsa82tMAdvmrhOqNkRKiYMEAFbTJAIzaTesb6Tscfcni8vIpWZqNCXFDFslJtVSvFDq`, // text boundary start
+ `AIzaTesb6Tscfcni8vIpWZqNCXFDFslJtVSvFDqabcd123`, // text boundary end
+ `apiKey: "AIzaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"`, // not enough entropy
+ `AIZASYCO2CXRMC9ELSKLHLHRMBSWDEVEDZTLO2O`, // incorrect case
+ // example keys from https://github.com/firebase/firebase-android-sdk
+ `AIzaSyabcdefghijklmnopqrstuvwxyz1234567`,
+ `AIzaSyAnLA7NfeLquW1tJFpx_eQCxoX-oo6YyIs`,
+ `AIzaSyCkEhVjf3pduRDt6d1yKOMitrUEke8agEM`,
+ `AIzaSyDMAScliyLx7F0NPDEJi1QmyCgHIAODrlU`,
+ `AIzaSyD3asb-2pEZVqMkmL6M9N6nHZRR_znhrh0`,
+ `AIzayDNSXIbFmlXbIE6mCzDLQAqITYefhixbX4A`,
+ `AIzaSyAdOS2zB6NCsk1pCdZ4-P6GBdi_UUPwX7c`,
+ `AIzaSyASWm6HmTMdYWpgMnjRBjxcQ9CKctWmLd4`,
+ `AIzaSyANUvH9H9BsUccjsu2pCmEkOPjjaXeDQgY`,
+ `AIzaSyA5_iVawFQ8ABuTZNUdcwERLJv_a_p4wtM`,
+ `AIzaSyA4UrcGxgwQFTfaI3no3t7Lt1sjmdnP5sQ`,
+ `AIzaSyDSb51JiIcB6OJpwwMicseKRhhrOq1cS7g`,
+ `AIzaSyBF2RrAIm4a0mO64EShQfqfd2AFnzAvvuU`,
+ `AIzaSyBcE-OOIbhjyR83gm4r2MFCu4MJmprNXsw`,
+ `AIzaSyB8qGxt4ec15vitgn44duC5ucxaOi4FmqE`,
+ `AIzaSyA8vmApnrHNFE0bApF4hoZ11srVL_n0nvY`,
+ }
+ return utils.Validate(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/generic.go b/cmd/generate/config/rules/generic.go
new file mode 100644
index 0000000..43fded7
--- /dev/null
+++ b/cmd/generate/config/rules/generic.go
@@ -0,0 +1,299 @@
+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"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+func GenericCredential() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "generic-api-key",
+ Description: "Detected a Generic API Key, potentially exposing access to various services and sensitive operations.",
+ Regex: utils.GenerateSemiGenericRegex([]string{
+ "access",
+ "auth",
+ `(?-i:[Aa]pi|API)`,
+ "credential",
+ "creds",
+ "key",
+ "passw(?:or)?d",
+ "secret",
+ "token",
+ }, `[\w.=-]{10,150}|[a-z0-9][a-z0-9+/]{11,}={0,3}`, true),
+ Keywords: []string{
+ "access",
+ "api",
+ "auth",
+ "key",
+ "credential",
+ "creds",
+ "passwd",
+ "password",
+ "secret",
+ "token",
+ },
+ Entropy: 3.5,
+ Allowlists: []*config.Allowlist{
+ {
+ // NOTE: this is a goofy hack to get around the fact there golang's regex engine does not support positive lookaheads.
+ // Ideally we would want to ensure the secret contains both numbers and alphabetical characters, not just alphabetical characters.
+ Regexes: []*regexp.Regexp{
+ regexp.MustCompile(`^[a-zA-Z_.-]+$`),
+ },
+ },
+ {
+ Description: "Allowlist for Generic API Keys",
+ MatchCondition: config.AllowlistMatchOr,
+ RegexTarget: "match",
+ Regexes: []*regexp.Regexp{
+ regexp.MustCompile(`(?i)(?:` +
+ // Access
+ `access(?:ibility|or)` +
+ `|access[_.-]?id` +
+ `|random[_.-]?access` +
+ // API
+ `|api[_.-]?(?:id|name|version)` + // id/name/version -> not a secret
+ `|rapid|capital` + // common words containing "api"
+ `|[a-z0-9-]*?api[a-z0-9-]*?:jar:` + // Maven META-INF dependencies that contain "api" in the name.
+ // Auth
+ `|author` +
+ `|X-MS-Exchange-Organization-Auth` + // email header
+ `|Authentication-Results` + // email header
+ // Credentials
+ `|(?:credentials?[_.-]?id|withCredentials)` + // Jenkins plugins
+ // Key
+ `|(?:bucket|foreign|hot|idx|natural|primary|pub(?:lic)?|schema|sequence)[_.-]?key` +
+ `|(?:turkey)` +
+ `|key[_.-]?(?:alias|board|code|frame|id|length|mesh|name|pair|press(?:ed)?|ring|selector|signature|size|stone|storetype|word|up|down|left|right)` +
+ // Azure KeyVault
+ `|key[_.-]?vault[_.-]?(?:id|name)|keyVaultToStoreSecrets` +
+ `|key(?:store|tab)[_.-]?(?:file|path)` +
+ `|issuerkeyhash` + // part of ssl cert
+ `|(?-i:[DdMm]onkey|[DM]ONKEY)|keying` + // common words containing "key"
+ // Secret
+ `|(?:secret)[_.-]?(?:length|name|size)` + // name of e.g. env variable
+ `|UserSecretsId` + // https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-8.0&tabs=linux
+
+ // Token
+ `|(?:csrf)[_.-]?token` +
+ `|(?:io\.jsonwebtoken[ \t]?:[ \t]?[\w-]+)` + // Maven library coordinates. (e.g., https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt)
+
+ // General
+ `|(?:api|credentials|token)[_.-]?(?:endpoint|ur[il])` +
+ `|public[_.-]?token` +
+ `|(?:key|token)[_.-]?file` +
+ // Empty variables capturing the next line (e.g., .env files)
+ `|(?-i:(?:[A-Z_]+=\n[A-Z_]+=|[a-z_]+=\n[a-z_]+=)(?:\n|\z))` +
+ `|(?-i:(?:[A-Z.]+=\n[A-Z.]+=|[a-z.]+=\n[a-z.]+=)(?:\n|\z))` +
+ `)`),
+ },
+ StopWords: append(DefaultStopWords,
+ "6fe4476ee5a1832882e326b506d14126", // https://github.com/yarnpkg/berry/issues/6201
+ ),
+ },
+ {
+ RegexTarget: "line",
+ Regexes: []*regexp.Regexp{
+ // Docker build secrets (https://docs.docker.com/build/building/secrets/#using-build-secrets).
+ regexp.MustCompile(`--mount=type=secret,`),
+ // https://github.com/gitleaks/gitleaks/issues/1800
+ regexp.MustCompile(`import[ \t]+{[ \t\w,]+}[ \t]+from[ \t]+['"][^'"]+['"]`),
+ },
+ },
+ {
+ MatchCondition: config.AllowlistMatchAnd,
+ RegexTarget: "line",
+ Regexes: []*regexp.Regexp{
+ regexp.MustCompile(`LICENSE[^=]*=\s*"[^"]+`),
+ regexp.MustCompile(`LIC_FILES_CHKSUM[^=]*=\s*"[^"]+`),
+ regexp.MustCompile(`SRC[^=]*=\s*"[a-zA-Z0-9]+`),
+ },
+ Paths: []*regexp.Regexp{
+ regexp.MustCompile(`\.bb$`),
+ regexp.MustCompile(`\.bbappend$`),
+ regexp.MustCompile(`\.bbclass$`),
+ regexp.MustCompile(`\.inc$`),
+ },
+ },
+ },
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("generic", "CLOJARS_34bf0e88955ff5a1c328d6a7491acc4f48e865a7b8dd4d70a70749037443") //gitleaks:allow
+ tps = append(tps, utils.GenerateSampleSecrets("generic", "Zf3D0LXCM3EIMbgJpUNnkRtOfOueHznB")...)
+ tps = append(tps,
+ // Access
+ `'access_token': 'eyJ0eXAioiJKV1slS3oASx=='`,
+
+ // API
+ `some_api_token_123 = "`+newPlausibleSecret(`[a-zA-Z0-9]{60}`)+`"`,
+
+ // Auth
+ `"user_auth": "am9obmRvZTpkMDY5NGIxYi1jMTcxLTQ4ODYt+TMyYS0wMmUwOWQ1/mIwNjc="`,
+
+ // Credentials
+ `"credentials" : "0afae57f3ccfd9d7f5767067bc48b30f719e271ba470488056e37ab35d4b6506"`,
+ `creds = `+newPlausibleSecret(`[a-zA-Z0-9]{30}`),
+
+ // Key
+ `private-key: `+newPlausibleSecret(`[a-zA-Z0-9\-_.=]{100}`),
+
+ // Password
+ `passwd = `+newPlausibleSecret(`[a-zA-Z0-9\-_.=]{30}`),
+ // TODO: `ID=dbuser;password=` + newPlausibleSecret(`[a-zA-Z0-9+/]{30}={0,3}`) + `;"`,
+
+ // Secret
+ `"client_secret" : "6da89121079f83b2eb6acccf8219ea982c3d79bccc3e9c6a85856480661f8fde",`,
+ `mySecretString=`+newPlausibleSecret(`[a-zA-Z0-9]{30}`),
+ `todo_secret_do_not_commit = `+newPlausibleSecret(`[a-zA-Z0-9]{30}`),
+
+ // Token
+ ` utils.GetEnvOrDefault("api_token", "dafa7817-e246-48f3-91a7-e87653d587b8")`,
+ // `"env": {
+ //"API_TOKEN": "Lj2^5O%xi214"`,
+ )
+ fps := []string{
+ // Access
+ `"accessor":"rA1wk0Y45YCufyfq",`,
+ `report_access_id: e8e4df51-2054-49b0-ab1c-516ac95c691d`,
+ `accessibilityYesOptionId = "0736f5ef-7e88-499a-80cc-90c85d2a5180"`,
+ `_RandomAccessIterator>
+_LIBCPP_CONSTEXPR_AFTER_CXX11 `,
+
+ // API
+ `this.ultraPictureBox1.Name = "ultraPictureBox1";`,
+ `rapidstring:marm64-uwp=fail`,
+ `event-bus-message-api:rc0.15.0_20231217_1420-SNAPSHOT'`,
+ `COMMUNICATION_API_VERSION=rc0.13.0_20230412_0712-SNAPSHOT`,
+ `MantleAPI_version=9a038989604e8da62ecddbe2094b16ce1b778be1`,
+ `[DEBUG] org.slf4j.slf4j-api:jar:1.7.8.:compile (version managed from default)`,
+ `[DEBUG] org.neo4j.neo4j-graphdb-api:jar:3.5.12:test`,
+ `apiUrl=apigee.corpint.com`,
+ `X-API-Name": "NRG0-Hermes-INTERNAL-API",`,
+ // TODO: Jetbrains IML files (requires line-level allowlist).
+ // ``
+
+ // Auth
+ `author = "james.fake@ymail.com",`,
+ `X-MS-Exchange-Organization-AuthSource: sm02915.int.contoso.com`,
+ `Authentication-Results: 5h.ca.iphmx.com`,
+
+ // Credentials
+ `withCredentials([usernamePassword(credentialsId: '29f63271-dc2f-4734-8221-5b31b5169bac', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {`,
+ `credentialsId: 'ff083f76-7804-4ef1-80e4-fe975bb9141b'`,
+ `jobCredentialsId: 'f4aeb6bc-2a25-458a-8111-9be9e502c0e7'`,
+ ` "credentialId": "B9mTcFSck2LzJO2S3ols63",`,
+ `environment {
+ CREDENTIALS_ID = "K8S_CRED"
+}`,
+ `dev.credentials.url=dev-lb1.api.f4ke.com:5215`,
+
+ // Key
+ `keyword: "Befaehigung_P2"`,
+ `public_key = "9Cnzj4p4WGeKLs1Pt8QuKUpRKfFLfRYC9AIKjbJTWit"`,
+ `pub const X509_pubkey_st = struct_X509_pubkey_st;`,
+ `|| pIdxKey->default_rc==0`,
+ `monkeys-audio:mx64-uwp=fail`,
+ `primaryKey=` + newPlausibleSecret(`[a-zA-Z0-9\-_.=]{30}`),
+ `foreignKey=` + newPlausibleSecret(`[a-zA-Z0-9\-_.=]{30}`),
+ `key_down_event=` + newPlausibleSecret(`[a-zA-Z0-9\-_.=]{30}`),
+ `issuerKeyHash=` + newPlausibleSecret(`[a-zA-Z0-9\-_.=]{30}`),
+ ``,
+ `minisat-master-keying:x64-uwp=fail`,
+ `IceSSL.KeyFile=s_rsa1024_priv.pem`,
+ `"bucket_key": "SalesResults-1.2"`,
+ ``,
+ // `packageKey":` + newPlausibleSecret(`[a-zA-Z0-9\-_.=]{30}`),
+ `schemaKey = 'DOC_Vector_5_32'`,
+ `sequenceKey = "18"`,
+ `app.keystore.file=env/cert.p12`,
+ `-DKEYTAB_FILE=/tmp/app.keytab`,
+ ` doc.Security.KeySize = PdfEncryptionKeySize.Key128Bit;`,
+ `o.keySelector=n,o.haKey=!1,`,
+ // TODO: Requires line-level allowlists.
+ ` "key_name": "prod5zyxlmy-cmk",`,
+ ` "kms_key_id": "555ea4a3-d53a-4412-9c66-3a7cb667b0d6",`,
+ ` "key_vault_name": "web21prqodx24021",`,
+ ` keyVaultToStoreSecrets: cmp2-qat-1208358310`, // e.g., https://github.com/2uasimojo/community-operators-prod/blob/9e51e4c8e0b5caaa3087e8e18e6fb918b2c36643/operators/azure-service-operator/1.0.59040/manifests/azure.microsoft.com_cosmosdbs.yaml#L50
+ `,apiKey:"6fe4476ee5a1832882e326b506d14126",`,
+ `const validKeyChars = "0123456789abcdefghijklmnopqrstuvwxyz_-."`,
+ `const keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"`,
+ `key_length = XSalsa20.key_length`,
+ `pub const SN_id_Gost28147_89_None_KeyMeshing = "id-Gost28147-89-None-KeyMeshing"`,
+ `KeyPair = X25519.KeyPair`,
+ `BlindKeySignatures = Ed25519.BlindKeySignatures`,
+ `AVEncVideoMaxKeyframeDistance, "2987123a-ba93-4704-b489-ec1e5f25292c"`,
+ ` keyPressed = kVK_Return.u16`,
+ `timezone_mapping = {
+ "Turkey Standard Time": "Europe/Istanbul",
+}`, // https://github.com/gitleaks/gitleaks/issues/1799
+ // ``,
+ //` { key: '9df21e95-3848-409d-8f94-c675cdfee839', value: 'Americas' },`,
+ // ``,
+ // `secret:
+ // secretName: app-decryption-secret
+ // items:
+ // - key: app-k8s.yml
+ // path: app-k8s.yml`,
+
+ // TODO: https://learn.microsoft.com/en-us/windows/apps/design/style/xaml-theme-resources
+ //`#FFBAE4FF`,
+
+ // Password
+ `password combination.
+
+R5: Regulatory--21`,
+ `PuttyPassword=0`,
+
+ // Secret
+ `LLM_SECRET_NAME = "NEXUS-GPT4-API-KEY"`,
+ ` 79a3edd0-2092-40a2-a04d-dcb46d5ca9ed`,
+ `secret_length = X25519.secret_length`,
+ `secretSize must be >= XXH3_SECRET_SIZE_MIN`,
+ `# get build time secret for authentication
+#RUN --mount=type=secret,id=jfrog_secret \
+# JFROG_SECRET = $(cat /run/secrets/jfrog_secret) && \`,
+
+ // Token
+ ` access_token_url='https://github.com/login/oauth/access_token',`,
+ `publicToken = "9Cnzj4p4WGeKLs1Pt8QuKUpRKfFLfRYC9AIKjbJTWit"`,
+ ``,
+ `notes = "Maven - io.jsonwebtoken:jjwt-jackson-0.11.2"`,
+ `csrf-token=Mj2qykJO5rELyHgezQ69nzUX0i3OH67V7+V4eUrLfpuyOuxmiW9rhROG/Whikle15syazJOkrjJa3U2AbhIvUw==`,
+ // TODO: `TOKEN_AUDIENCE = "25872395-ed3a-4703-b647-22ec53f3683c"`,
+
+ // General
+ `clientId = "73082700-1f09-405b-80d0-3131bfd6272d"`,
+ `GITHUB_API_KEY=
+DYNATRACE_API_KEY=`,
+ `snowflake.password=
+jdbc.snowflake.url=`,
+ `import { chain_Anvil1_Key, chain_Anvil2_Key } from '../blockchain-tests/pallets/supported-chains/consts';`,
+
+ // Yocto/BitBake
+ `SRCREV_moby = "43fc912ef59a83054ea7f6706df4d53a7dea4d80"`,
+ `LIC_FILES_CHKSUM = "file://${WORKDIR}/license.html;md5=5c94767cedb5d6987c902ac850ded2c6"`,
+ }
+ return utils.Validate(r, tps, fps)
+}
+
+func newPlausibleSecret(regex string) string {
+ allowList := &config.Allowlist{StopWords: DefaultStopWords}
+ // attempt to generate a random secret,
+ // retrying until it contains at least one digit and no stop words
+ // TODO: currently the DefaultStopWords list contains many short words,
+ // so there is a significant chance of generating a secret that contains a stop word
+ for {
+ secret := secrets.NewSecret(regex)
+ if !regexp.MustCompile(`[1-9]`).MatchString(secret) {
+ continue
+ }
+ if ok, _ := allowList.ContainsStopWord(secret); ok {
+ continue
+ }
+ return secret
+ }
+}
diff --git a/cmd/generate/config/rules/github.go b/cmd/generate/config/rules/github.go
new file mode 100644
index 0000000..58aaf43
--- /dev/null
+++ b/cmd/generate/config/rules/github.go
@@ -0,0 +1,111 @@
+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"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+var githubAllowlist = []*config.Allowlist{
+ {
+ Paths: []*regexp.Regexp{
+ // https://github.com/octokit/auth-token.js/?tab=readme-ov-file#createtokenauthtoken-options
+ regexp.MustCompile(`(?:^|/)@octokit/auth-token/README\.md$`),
+ },
+ },
+}
+
+func GitHubPat() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "github-pat",
+ Description: "Uncovered a GitHub Personal Access Token, potentially leading to unauthorized repository access and sensitive content exposure.",
+ Regex: regexp.MustCompile(`ghp_[0-9a-zA-Z]{36}`),
+ Entropy: 3,
+ Keywords: []string{"ghp_"},
+ Allowlists: githubAllowlist,
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("github", "ghp_"+secrets.NewSecret(utils.AlphaNumeric("36")))
+ fps := []string{
+ "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ }
+ return utils.Validate(r, tps, fps)
+}
+
+func GitHubFineGrainedPat() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "github-fine-grained-pat",
+ Description: "Found a GitHub Fine-Grained Personal Access Token, risking unauthorized repository access and code manipulation.",
+ Regex: regexp.MustCompile(`github_pat_\w{82}`),
+ Entropy: 3,
+ Keywords: []string{"github_pat_"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("github", "github_pat_"+secrets.NewSecret(utils.AlphaNumeric("82")))
+ fps := []string{
+ "github_pat_xxxxxxxxxxxxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ }
+ return utils.Validate(r, tps, fps)
+}
+
+func GitHubOauth() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "github-oauth",
+ Description: "Discovered a GitHub OAuth Access Token, posing a risk of compromised GitHub account integrations and data leaks.",
+ Regex: regexp.MustCompile(`gho_[0-9a-zA-Z]{36}`),
+ Entropy: 3,
+ Keywords: []string{"gho_"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("github", "gho_"+secrets.NewSecret(utils.AlphaNumeric("36")))
+ fps := []string{
+ "gho_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ }
+ return utils.Validate(r, tps, fps)
+}
+
+func GitHubApp() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "github-app-token",
+ Description: "Identified a GitHub App Token, which may compromise GitHub application integrations and source code security.",
+ Regex: regexp.MustCompile(`(?:ghu|ghs)_[0-9a-zA-Z]{36}`),
+ Entropy: 3,
+ Keywords: []string{"ghu_", "ghs_"},
+ Allowlists: githubAllowlist,
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("github", "ghs_"+secrets.NewSecret(utils.AlphaNumeric("36")))
+ tps = append(tps, utils.GenerateSampleSecrets("github", "ghu_"+secrets.NewSecret(utils.AlphaNumeric("36")))...)
+ fps := []string{
+ "ghu_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "ghs_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ }
+ return utils.Validate(r, tps, fps)
+}
+
+func GitHubRefresh() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "github-refresh-token",
+ Description: "Detected a GitHub Refresh Token, which could allow prolonged unauthorized access to GitHub services.",
+ Regex: regexp.MustCompile(`ghr_[0-9a-zA-Z]{36}`),
+ Entropy: 3,
+ Keywords: []string{"ghr_"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("github", "ghr_"+secrets.NewSecret(utils.AlphaNumeric("36")))
+ fps := []string{
+ "ghr_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ }
+ return utils.Validate(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/gitlab.go b/cmd/generate/config/rules/gitlab.go
new file mode 100644
index 0000000..69babe9
--- /dev/null
+++ b/cmd/generate/config/rules/gitlab.go
@@ -0,0 +1,222 @@
+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"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+// overview with all GitLab tokens:
+// https://docs.gitlab.com/ee/security/tokens/index.html#token-prefixes
+
+func GitlabCiCdJobToken() *config.Rule {
+ r := config.Rule{
+ RuleID: "gitlab-cicd-job-token",
+ Description: "Identified a GitLab CI/CD Job Token, potential access to projects and some APIs on behalf of a user while the CI job is running.",
+ Regex: regexp.MustCompile(`glcbt-[0-9a-zA-Z]{1,5}_[0-9a-zA-Z_-]{20}`),
+ Entropy: 3,
+ Keywords: []string{"glcbt-"},
+ }
+ tps := utils.GenerateSampleSecrets("gitlab", "glcbt-"+secrets.NewSecret(utils.AlphaNumeric("5"))+"_"+secrets.NewSecret(utils.AlphaNumeric("20")))
+ return utils.Validate(r, tps, nil)
+}
+
+func GitlabDeployToken() *config.Rule {
+ r := config.Rule{
+ Description: "Identified a GitLab Deploy Token, risking access to repositories, packages and containers with write access.",
+ RuleID: "gitlab-deploy-token",
+ Regex: regexp.MustCompile(`gldt-[0-9a-zA-Z_\-]{20}`),
+ Entropy: 3,
+ Keywords: []string{"gldt-"},
+ }
+ tps := []string{
+ utils.GenerateSampleSecret("gitlab", "gldt-"+secrets.NewSecret(utils.AlphaNumeric("20"))),
+ }
+ return utils.Validate(r, tps, nil)
+}
+
+func GitlabFeatureFlagClientToken() *config.Rule {
+ r := config.Rule{
+ RuleID: "gitlab-feature-flag-client-token",
+ Description: "Identified a GitLab feature flag client token, risks exposing user lists and features flags used by an application.",
+ Regex: regexp.MustCompile(`glffct-[0-9a-zA-Z_\-]{20}`),
+ Entropy: 3,
+ Keywords: []string{"glffct-"},
+ }
+ tps := utils.GenerateSampleSecrets("gitlab", "glffct-"+secrets.NewSecret(utils.AlphaNumeric("20")))
+ return utils.Validate(r, tps, nil)
+}
+
+func GitlabFeedToken() *config.Rule {
+ r := config.Rule{
+ RuleID: "gitlab-feed-token",
+ Description: "Identified a GitLab feed token, risking exposure of user data.",
+ Regex: regexp.MustCompile(`glft-[0-9a-zA-Z_\-]{20}`),
+ Entropy: 3,
+ Keywords: []string{"glft-"},
+ }
+ tps := utils.GenerateSampleSecrets("gitlab", "glft-"+secrets.NewSecret(utils.AlphaNumeric("20")))
+ return utils.Validate(r, tps, nil)
+}
+
+func GitlabIncomingMailToken() *config.Rule {
+ r := config.Rule{
+ RuleID: "gitlab-incoming-mail-token",
+ Description: "Identified a GitLab incoming mail token, risking manipulation of data sent by mail.",
+ Regex: regexp.MustCompile(`glimt-[0-9a-zA-Z_\-]{25}`),
+ Entropy: 3,
+ Keywords: []string{"glimt-"},
+ }
+ tps := utils.GenerateSampleSecrets("gitlab", "glimt-"+secrets.NewSecret(utils.AlphaNumeric("25")))
+ return utils.Validate(r, tps, nil)
+}
+
+func GitlabKubernetesAgentToken() *config.Rule {
+ r := config.Rule{
+ RuleID: "gitlab-kubernetes-agent-token",
+ Description: "Identified a GitLab Kubernetes Agent token, risking access to repos and registry of projects connected via agent.",
+ Regex: regexp.MustCompile(`glagent-[0-9a-zA-Z_\-]{50}`),
+ Entropy: 3,
+ Keywords: []string{"glagent-"},
+ }
+ tps := utils.GenerateSampleSecrets("gitlab", "glagent-"+secrets.NewSecret(utils.AlphaNumeric("50")))
+ return utils.Validate(r, tps, nil)
+}
+
+func GitlabOauthAppSecret() *config.Rule {
+ r := config.Rule{
+ RuleID: "gitlab-oauth-app-secret",
+ Description: "Identified a GitLab OIDC Application Secret, risking access to apps using GitLab as authentication provider.",
+ Regex: regexp.MustCompile(`gloas-[0-9a-zA-Z_\-]{64}`),
+ Entropy: 3,
+ Keywords: []string{"gloas-"},
+ }
+ tps := utils.GenerateSampleSecrets("gitlab", "gloas-"+secrets.NewSecret(utils.AlphaNumeric("64")))
+ return utils.Validate(r, tps, nil)
+}
+
+func GitlabPat() *config.Rule {
+ r := config.Rule{
+ RuleID: "gitlab-pat",
+ Description: "Identified a GitLab Personal Access Token, risking unauthorized access to GitLab repositories and codebase exposure.",
+ Regex: regexp.MustCompile(`glpat-[\w-]{20}`),
+ Entropy: 3,
+ Keywords: []string{"glpat-"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("gitlab", "glpat-"+secrets.NewSecret(utils.AlphaNumeric("20")))
+ fps := []string{
+ "glpat-XXXXXXXXXXX-XXXXXXXX",
+ }
+ return utils.Validate(r, tps, fps)
+}
+
+func GitlabPatRoutable() *config.Rule {
+ r := config.Rule{
+ RuleID: "gitlab-pat-routable",
+ Description: "Identified a GitLab Personal Access Token (routable), risking unauthorized access to GitLab repositories and codebase exposure.",
+ Regex: regexp.MustCompile(`\bglpat-[0-9a-zA-Z_-]{27,300}\.[0-9a-z]{2}[0-9a-z]{7}\b`),
+ Entropy: 4,
+ Keywords: []string{"glpat-"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("gitlab", "glpat-"+secrets.NewSecret(utils.AlphaNumeric("27"))+"."+secrets.NewSecret(utils.AlphaNumeric("2"))+secrets.NewSecret(utils.AlphaNumeric("7")))
+ fps := []string{
+ "glpat-xxxxxxxx-xxxxxxxxxxxxxxxxxx.xxxxxxxxx",
+ }
+ return utils.Validate(r, tps, fps)
+}
+
+func GitlabPipelineTriggerToken() *config.Rule {
+ r := config.Rule{
+ RuleID: "gitlab-ptt",
+ Description: "Found a GitLab Pipeline Trigger Token, potentially compromising continuous integration workflows and project security.",
+ Regex: regexp.MustCompile(`glptt-[0-9a-f]{40}`),
+ Entropy: 3,
+ Keywords: []string{"glptt-"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("gitlab", "glptt-"+secrets.NewSecret(utils.Hex("40")))
+ fps := []string{
+ "glptt-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ }
+ return utils.Validate(r, tps, fps)
+}
+
+func GitlabRunnerRegistrationToken() *config.Rule {
+ r := config.Rule{
+ RuleID: "gitlab-rrt",
+ Description: "Discovered a GitLab Runner Registration Token, posing a risk to CI/CD pipeline integrity and unauthorized access.",
+ Regex: regexp.MustCompile(`GR1348941[\w-]{20}`),
+ Entropy: 3,
+ Keywords: []string{"GR1348941"},
+ }
+
+ tps := utils.GenerateSampleSecrets("gitlab", "GR1348941"+secrets.NewSecret(utils.AlphaNumeric("20")))
+ fps := []string{
+ "GR134894112312312312312312312",
+ "GR1348941XXXXXXXXXXXXXXXXXXXX",
+ }
+ return utils.Validate(r, tps, fps)
+}
+
+func GitlabRunnerAuthenticationToken() *config.Rule {
+ r := config.Rule{
+ RuleID: "gitlab-runner-authentication-token",
+ Description: "Discovered a GitLab Runner Authentication Token, posing a risk to CI/CD pipeline integrity and unauthorized access.",
+ Regex: regexp.MustCompile(`glrt-[0-9a-zA-Z_\-]{20}`),
+ Entropy: 3,
+ Keywords: []string{"glrt-"},
+ }
+
+ tps := utils.GenerateSampleSecrets("gitlab", "glrt-"+secrets.NewSecret(utils.AlphaNumeric("20")))
+ return utils.Validate(r, tps, nil)
+}
+
+func GitlabRunnerAuthenticationTokenRoutable() *config.Rule {
+ r := config.Rule{
+ RuleID: "gitlab-runner-authentication-token-routable",
+ Description: "Discovered a GitLab Runner Authentication Token (Routable), posing a risk to CI/CD pipeline integrity and unauthorized access.",
+ Regex: regexp.MustCompile(`\bglrt-t\d_[0-9a-zA-Z_\-]{27,300}\.[0-9a-z]{2}[0-9a-z]{7}\b`),
+ Entropy: 4,
+ Keywords: []string{"glrt-"},
+ }
+
+ tps := utils.GenerateSampleSecrets("gitlab", "glrt-t"+secrets.NewSecret(utils.Numeric("1"))+"_"+secrets.NewSecret(utils.AlphaNumeric("27"))+"."+secrets.NewSecret(utils.AlphaNumeric("2"))+secrets.NewSecret(utils.AlphaNumeric("7")))
+ fps := []string{
+ "glrt-tx_xxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxx",
+ }
+
+ return utils.Validate(r, tps, fps)
+}
+
+func GitlabScimToken() *config.Rule {
+ r := config.Rule{
+ RuleID: "gitlab-scim-token",
+ Description: "Discovered a GitLab SCIM Token, posing a risk to unauthorized access for a organization or instance.",
+ Regex: regexp.MustCompile(`glsoat-[0-9a-zA-Z_\-]{20}`),
+ Entropy: 3,
+ Keywords: []string{"glsoat-"},
+ }
+
+ tps := utils.GenerateSampleSecrets("gitlab", "glsoat-"+secrets.NewSecret(utils.AlphaNumeric("20")))
+ return utils.Validate(r, tps, nil)
+}
+
+func GitlabSessionCookie() *config.Rule {
+ r := config.Rule{
+ RuleID: "gitlab-session-cookie",
+ Description: "Discovered a GitLab Session Cookie, posing a risk to unauthorized access to a user account.",
+ Regex: regexp.MustCompile(`_gitlab_session=[0-9a-z]{32}`),
+ Entropy: 3,
+ Keywords: []string{"_gitlab_session="},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("gitlab", "_gitlab_session="+secrets.NewSecret(utils.AlphaNumeric("32")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/gitter.go b/cmd/generate/config/rules/gitter.go
new file mode 100644
index 0000000..776264e
--- /dev/null
+++ b/cmd/generate/config/rules/gitter.go
@@ -0,0 +1,25 @@
+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"
+)
+
+func GitterAccessToken() *config.Rule {
+ // define 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: utils.GenerateSemiGenericRegex([]string{"gitter"},
+ utils.AlphaNumericExtendedShort("40"), true),
+
+ Keywords: []string{
+ "gitter",
+ },
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("gitter", secrets.NewSecret(utils.AlphaNumericExtendedShort("40")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/gocardless.go b/cmd/generate/config/rules/gocardless.go
new file mode 100644
index 0000000..87e8150
--- /dev/null
+++ b/cmd/generate/config/rules/gocardless.go
@@ -0,0 +1,25 @@
+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"
+)
+
+func GoCardless() *config.Rule {
+ // define 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: utils.GenerateSemiGenericRegex([]string{"gocardless"}, `live_(?i)[a-z0-9\-_=]{40}`, true),
+
+ Keywords: []string{
+ "live_",
+ "gocardless",
+ },
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("gocardless", "live_"+secrets.NewSecret(utils.AlphaNumericExtended("40")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/grafana.go b/cmd/generate/config/rules/grafana.go
new file mode 100644
index 0000000..27ee4fc
--- /dev/null
+++ b/cmd/generate/config/rules/grafana.go
@@ -0,0 +1,80 @@
+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"
+)
+
+func GrafanaApiKey() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "grafana-api-key",
+ Description: "Identified a Grafana API key, which could compromise monitoring dashboards and sensitive data analytics.",
+ Regex: utils.GenerateUniqueTokenRegex(`eyJrIjoi[A-Za-z0-9]{70,400}={0,3}`, true),
+ Entropy: 3,
+ Keywords: []string{"eyJrIjoi"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("grafana-api-key", "eyJrIjoi"+secrets.NewSecret(utils.AlphaNumeric("70")))
+ return utils.Validate(r, tps, nil)
+}
+
+func GrafanaCloudApiToken() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "grafana-cloud-api-token",
+ Description: "Found a Grafana cloud API token, risking unauthorized access to cloud-based monitoring services and data exposure.",
+ Regex: utils.GenerateUniqueTokenRegex(`glc_[A-Za-z0-9+/]{32,400}={0,3}`, true),
+ Entropy: 3,
+ Keywords: []string{"glc_"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("grafana-cloud-api-token", "glc_"+secrets.NewSecret(utils.AlphaNumeric("32")))
+ tps = append(tps,
+ utils.GenerateSampleSecret("grafana-cloud-api-token",
+ "glc_"+
+ secrets.NewSecret(utils.AlphaNumeric("32"))),
+ `loki_key: glc_eyJvIjoiNzQ0NTg3IiwibiI7InN0YWlrLTQ3NTgzMC1obC13cml0ZS1oYW5kc29uJG9raSIsImsiOiI4M2w3cmdYUlBoMTUyMW1lMU023nl5UDUiLCJtIjp7IOIiOiJ1cyJ9fQ==`,
+ // TODO:
+ //` loki:
+ //endpoint: https://322137:glc_eyJvIjoiNzQ0NTg3IiwibiI7InN0YWlrLTQ3NTgzMC1obC13cml0ZS1oYW5kc29uJG9raSIsImsiOiI4M2w3cmdYUlBoMTUyMW1lMU023nl5UDUiLCJtIjp7IOIiOiJ1cyJ9fQ==@logs-prod4.grafana.net/loki/api/v1/push`,
+ )
+ fps := []string{
+ // Low entropy.
+ `glc_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`,
+ ` API_KEY="glc_111111111111111111111111111111111111111111="`,
+ // Invalid.
+ `static void GLC_CreateLightmapTextureArray(void);
+static void GLC_CreateLightmapTexturesIndividual(void);
+
+void GLC_UploadLightmap(int textureUnit, int lightmapnum);`,
+ `// Alias models
+void GLC_StateBeginUnderwaterAliasModelCaustics(texture_ref base_texture, texture_ref caustics_texture)
+{`,
+ }
+ return utils.Validate(r, tps, fps)
+}
+
+func GrafanaServiceAccountToken() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "grafana-service-account-token",
+ Description: "Discovered a Grafana service account token, posing a risk of compromised monitoring services and data integrity.",
+ Regex: utils.GenerateUniqueTokenRegex(`glsa_[A-Za-z0-9]{32}_[A-Fa-f0-9]{8}`, true),
+ Entropy: 3,
+ Keywords: []string{"glsa_"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("grafana-service-account-token", "glsa_"+secrets.NewSecret(utils.AlphaNumeric("32"))+"_"+secrets.NewSecret(utils.Hex("8")))
+ tps = append(tps,
+ `'Authorization': 'Bearer glsa_pITqMOBIfNH2KL4PkXJqmTyQl0D9QGxF_486f63e1'`,
+ )
+ fps := []string{
+ "glsa_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX_AAAAAAAA",
+ }
+ return utils.Validate(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/harness.go b/cmd/generate/config/rules/harness.go
new file mode 100644
index 0000000..0f78888
--- /dev/null
+++ b/cmd/generate/config/rules/harness.go
@@ -0,0 +1,25 @@
+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"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+func HarnessApiKey() *config.Rule {
+ // Define rule for Harness Personal Access Token (PAT) and Service Account Token (SAT)
+ r := config.Rule{
+ Description: "Identified a Harness Access Token (PAT or SAT), risking unauthorized access to a Harness account.",
+ RuleID: "harness-api-key",
+ Regex: regexp.MustCompile(`(?:pat|sat)\.[a-zA-Z0-9_-]{22}\.[a-zA-Z0-9]{24}\.[a-zA-Z0-9]{20}`),
+ Keywords: []string{"pat.", "sat."},
+ }
+
+ // Generate a sample secret for validation
+ tps := utils.GenerateSampleSecrets("harness", "pat."+secrets.NewSecret(utils.AlphaNumeric("22"))+"."+secrets.NewSecret(utils.AlphaNumeric("24"))+"."+secrets.NewSecret(utils.AlphaNumeric("20")))
+ tps = append(tps, utils.GenerateSampleSecrets("harness", "sat."+secrets.NewSecret(utils.AlphaNumeric("22"))+"."+secrets.NewSecret(utils.AlphaNumeric("24"))+"."+secrets.NewSecret(utils.AlphaNumeric("20")))...)
+
+ // validate the rule
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/hashicorp.go b/cmd/generate/config/rules/hashicorp.go
new file mode 100644
index 0000000..81895bb
--- /dev/null
+++ b/cmd/generate/config/rules/hashicorp.go
@@ -0,0 +1,58 @@
+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"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+func HashiCorpTerraform() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "hashicorp-tf-api-token",
+ Description: "Uncovered a HashiCorp Terraform user/org API token, which may lead to unauthorized infrastructure management and security breaches.",
+ Regex: regexp.MustCompile(`(?i)[a-z0-9]{14}\.(?-i:atlasv1)\.[a-z0-9\-_=]{60,70}`),
+ Entropy: 3.5,
+ Keywords: []string{"atlasv1"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("hashicorpToken", secrets.NewSecret(utils.Hex("14"))+".atlasv1."+secrets.NewSecret(utils.AlphaNumericExtended("60,70")))
+ tps = append(tps,
+ `#token = "hE1hlYILrSqpqh.atlasv1.ARjZuyzl33F71WR55s6ln5GQ1HWIwTDDH3MiRjz7OnpCfaCb1RCF5zGaSncCWmJdcYA"`,
+ )
+ fps := []string{
+ `token = "xxxxxxxxxxxxxx.atlasv1.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"`, // low entropy
+ }
+ return utils.Validate(r, tps, fps)
+}
+
+func HashicorpField() *config.Rule {
+ keywords := []string{"administrator_login_password", "password"}
+ // define rule
+ r := config.Rule{
+ RuleID: "hashicorp-tf-password",
+ Description: "Identified a HashiCorp Terraform password field, risking unauthorized infrastructure configuration and security breaches.",
+ Regex: utils.GenerateSemiGenericRegex(keywords, fmt.Sprintf(`"%s"`, utils.AlphaNumericExtended("8,20")), true),
+ Entropy: 2,
+ Path: regexp.MustCompile(`(?i)\.(?:tf|hcl)$`),
+ Keywords: keywords,
+ }
+
+ tps := map[string]string{
+ // Example from: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/sql_server.html
+ "file.tf": "administrator_login_password = " + `"thisIsDog11"`,
+ // https://registry.terraform.io/providers/petoju/mysql/latest/docs
+ "file.hcl": "password = " + `"rootpasswd"`,
+ }
+ fps := map[string]string{
+ "file.tf": "administrator_login_password = var.db_password",
+ "file.hcl": `password = "${aws_db_instance.default.password}"`,
+ "unrelated.js": "password = " + `"rootpasswd"`,
+ }
+
+ return utils.ValidateWithPaths(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/hashicorp_vault.go b/cmd/generate/config/rules/hashicorp_vault.go
new file mode 100644
index 0000000..c329689
--- /dev/null
+++ b/cmd/generate/config/rules/hashicorp_vault.go
@@ -0,0 +1,67 @@
+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"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+func VaultServiceToken() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "vault-service-token",
+ Description: "Identified a Vault Service Token, potentially compromising infrastructure security and access to sensitive credentials.",
+ Regex: utils.GenerateUniqueTokenRegex(`(?:hvs\.[\w-]{90,120}|s\.(?i:[a-z0-9]{24}))`, false),
+ Entropy: 3.5,
+ Keywords: []string{"hvs.", "s."},
+ Allowlists: []*config.Allowlist{
+ {
+ Regexes: []*regexp.Regexp{
+ // https://github.com/gitleaks/gitleaks/issues/1490#issuecomment-2334166357
+ regexp.MustCompile(`s\.[A-Za-z]{24}`),
+ },
+ },
+ },
+ }
+
+ // validate
+ tps := []string{
+ // Old
+ utils.GenerateSampleSecret("vault", secrets.NewSecret(`s\.[0-9][a-zA-Z0-9]{23}`)),
+ `token: s.ZC9Ecf4M5g9o34Q6RkzGsj0z`,
+ // New
+ utils.GenerateSampleSecret("vault", secrets.NewSecret(`hvs\.[0-9][\w\-]{89}`)),
+ `-vaultToken hvs.CAESIP2jTxc9S2K7Z6CtcFWQv7-044m_oSsxnPE1H3nF89l3GiYKHGh2cy5sQmlIZVNyTWJNcDRsYWJpQjlhYjVlb1cQh6PL8wEYAg"`, // longer than 100 chars
+ }
+
+ fps := []string{
+ // Old
+ ` credentials: new AWS.SharedIniFileCredentials({ profile: '' })`, // word boundary start
+ `INFO 4 --- [ main] o.s.b.f.s.DefaultListableBeanFactory : Overriding bean definition for bean`, // word boundary end
+ `s.xxxxxxxxxxxxxxxxxxxxxxxx`, // low entropy
+ `s.THISSTRINGISALLUPPERCASE`, // uppercase
+ `s.thisstringisalllowercase`, // lowercase
+ `s.AcceptanceTimeoutSeconds `, // pascal-case
+ `s.makeKubeConfigController = args`, // camel-case
+ // New
+ `hvs.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`, // low entropy
+ }
+ return utils.Validate(r, tps, fps)
+}
+
+func VaultBatchToken() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "vault-batch-token",
+ Description: "Detected a Vault Batch Token, risking unauthorized access to secret management services and sensitive data.",
+ Regex: utils.GenerateUniqueTokenRegex(`hvb\.[\w-]{138,300}`, false),
+ Entropy: 4,
+ Keywords: []string{"hvb."},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("vault", "hvb."+secrets.NewSecret(utils.AlphaNumericExtendedShort("138")))
+ tps = append(tps, `hvb.AAAAAQJgxDgqsGNorpoOR7hPZ5SU-ynBvCl764jyRP_fnX7WvkdkDzGjbLNGdPdtlY33Als2P36yDZueqzfdGw9RsaTeaYXSH7E4RYSWuRoQ9YRKIw8o7mDDY2ZcT3KOB7RwtW1w1FN2eDqcy_sbCjXPaM1iBVH-mqMSYRmRd2nb5D1SJPeBzIYRqSglLc31wUGN7xEzyrKUczqOKsIcybQA`) // gitleaks:allow
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/heroku.go b/cmd/generate/config/rules/heroku.go
new file mode 100644
index 0000000..436f067
--- /dev/null
+++ b/cmd/generate/config/rules/heroku.go
@@ -0,0 +1,45 @@
+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"
+)
+
+func Heroku() *config.Rule {
+ // define rule
+ r := config.Rule{
+ Description: "Detected a Heroku API Key, potentially compromising cloud application deployments and operational security.",
+ RuleID: "heroku-api-key",
+ Regex: utils.GenerateSemiGenericRegex([]string{"heroku"}, utils.Hex8_4_4_4_12(), true),
+
+ Keywords: []string{"heroku"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("heroku", secrets.NewSecret(utils.Hex8_4_4_4_12()))
+ tps = append(tps,
+ `const HEROKU_KEY = "12345678-ABCD-ABCD-ABCD-1234567890AB"`, // gitleaks:allow
+ `heroku_api_key = "832d2129-a846-4e27-99f4-7004b6ad53ef"`, // gitleaks:allow
+ )
+ return utils.Validate(r, tps, nil)
+}
+
+func HerokuV2() *config.Rule {
+ // define rule
+ r := config.Rule{
+ Description: "Detected a Heroku API Key, potentially compromising cloud application deployments and operational security.",
+ RuleID: "heroku-api-key-v2",
+ Regex: utils.GenerateUniqueTokenRegex(`(HRKU-AA[0-9a-zA-Z_-]{58})`, false),
+ Entropy: 4,
+ Keywords: []string{"HRKU-AA"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("heroku", secrets.NewSecret(`\b(HRKU-AA[0-9a-zA-Z_-]{58})\b`))
+ tps = append(tps,
+ `const KEY = "HRKU-AAlQ1aVoHDujJ9QsDHdHlHO0hbzhoERRSO45ZQusSYHg_____w4_hLrAym_u""`,
+ `API_Key = "HRKU-AAy9Ppr_HD2pPuTyIiTYInO0hbzhoERRSO93ZQusSYHgaD7_WQ07FnF7L9FX"`,
+ )
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/hubspot.go b/cmd/generate/config/rules/hubspot.go
new file mode 100644
index 0000000..1c26f49
--- /dev/null
+++ b/cmd/generate/config/rules/hubspot.go
@@ -0,0 +1,26 @@
+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"
+)
+
+func HubSpot() *config.Rule {
+ // define 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: 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"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("hubspot", secrets.NewSecret(utils.Hex8_4_4_4_12()))
+ tps = append(tps,
+ `const hubspotKey = "12345678-ABCD-ABCD-ABCD-1234567890AB"`, // gitleaks:allow
+ )
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/huggingface.go b/cmd/generate/config/rules/huggingface.go
new file mode 100644
index 0000000..09cbac7
--- /dev/null
+++ b/cmd/generate/config/rules/huggingface.go
@@ -0,0 +1,116 @@
+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"
+)
+
+// Reference: https://huggingface.co/docs/hub/security-tokens
+//
+// Old tokens have the prefix `api_`, however, I am not sure it's worth detecting them as that would be high noise.
+// https://huggingface.co/docs/api-inference/quicktour
+func HuggingFaceAccessToken() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "huggingface-access-token",
+ Description: "Discovered a Hugging Face Access token, which could lead to unauthorized access to AI models and sensitive data.",
+ Regex: utils.GenerateUniqueTokenRegex("hf_(?i:[a-z]{34})", false),
+ Entropy: 2,
+ Keywords: []string{
+ "hf_",
+ },
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("huggingface", "hf_"+secrets.NewSecret("[a-zA-Z]{34}"))
+ tps = append(tps,
+ `huggingface-cli login --token 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`,
+ `huggingface-cli login --token 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`,
+ `huggingface-cli login --token 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`,
+ `huggingface-cli login --token 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`,
+ `huggingface-cli login --token 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`,
+ `huggingface-cli login --token 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`,
+ `huggingface-cli login --token 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`,
+ `huggingface-cli login --token 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`,
+ `-H "Authorization: Bearer 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"`,
+ `DEV=1 HF_TOKEN=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 poetry run python app.py`,
+ `use_auth_token='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')`,
+ `CI_HUB_USER_TOKEN = "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"`,
+ `- Change line 5 and add your Hugging Face token, that is, instead of 'hf_token = "ADD_YOUR_HUGGING_FACE_TOKEN_HERE"', you will need to change it to something like'hf_token = "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"'`,
+ //TODO: ` " hf_token = \"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\"\n",`,
+ `# Not critical, only usable on the sandboxed CI instance.
+ TOKEN = "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"`,
+ ` parser.add_argument("--hf_token", type=str, default='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', help="Hugging Face Access Token to access PyAnnote gated models")`,
+ )
+ fps := []string{
+ `- (id)hf_requiredCharacteristicTypesForDisplayMetadata;`,
+ `amazon.de#@#div[data-cel-widget="desktop-rhf_SponsoredProductsRemoteRHFSearchEXPSubsK2ClickPagination"]`,
+ ` _kHMSymptomhf_generatedByHomeAppForDebuggingPurposesKey,`,
+ ` #define OSCHF_DebugGetExpectedAverageCrystalAmplitude NOROM_OSCHF_DebugGetExpectedAverageCrystalAmplitude`,
+ ` M_UINT (ServingCellPriorityParametersDescription_t, H_PRIO, 2, &hf_servingcellpriorityparametersdescription_h_prio),`,
+ `+HWI-ST565_0092:4:1101:5508:5860#ACTTGA/1
+ bb_eeeeegfgffhiiiiiiiiiiihiiiiicgafhf_eefghihhiiiifhifhhdhifhiiiihifdgdhggf\bbceceedbcd
+ @HWI-ST565_0092:4:1101:7621:5770#ACTTGA/1`,
+ `y{}x|~|}{~}}~|~}||�~|�{��|{}{|~z{}{{|{||{|}|{}{~|y}vjoePbUBJ7&;"; <; :;?!!;<7%$IACa_ecghbfbaebejhahfbhf_ddbficghbgfbhhcghdghfhigiifhhehhdggcgfchf_fgcei^[[.40&54"5666 6`,
+ ` change_dir(cwd)
+ subdirs = glob.glob('HF_CAASIMULIAComputeServicesBuildTime.HF*.Linux64')
+ if len(subdirs) == 1:`,
+ ` os.environ.get("HF_AUTH_TOKEN",
+ "hf_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"),`,
+ `# HuggingFace API Token https://huggingface.co/settings/tokens
+ HUGGINGFACE_API_TOKEN=hf_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,`,
+ }
+ return utils.Validate(r, tps, fps)
+}
+
+// Will be deprecated Aug 1st, 2023.
+func HuggingFaceOrganizationApiToken() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "huggingface-organization-api-token",
+ Description: "Uncovered a Hugging Face Organization API token, potentially compromising AI organization accounts and associated data.",
+ Regex: utils.GenerateUniqueTokenRegex("api_org_(?i:[a-z]{34})", false),
+
+ Entropy: 2,
+ Keywords: []string{
+ "api_org_",
+ },
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("huggingface", "api_org_"+secrets.NewSecret("[a-zA-Z]{34}"))
+ tps = append(tps,
+ `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`,
+ "`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`",
+ `\'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'\`,
+ //TODO: `\"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\"`,
+ //TODO: `,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,`,
+ //TODO: `(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)`,
+ //TODO: `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`,
+ `def test_private_space(self):
+ hf_token = "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" # Intentionally revealing this key for testing purposes
+ io = gr.load(`,
+ `hf_token = "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" # Intentionally revealing this key for testing purposes`,
+ `"news_train_dataset = datasets.load_dataset('nlpHakdang/aihub-news30k', data_files = \"train_news_text.csv\", use_auth_token='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')\n",`,
+ `os.environ['HUGGINGFACEHUB_API_TOKEN'] = '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'`,
+ fmt.Sprintf("api_org_%s", secrets.NewSecret(`[a-zA-Z]{34}`)),
+ )
+ fps := []string{
+ `public static final String API_ORG_EXIST = "APIOrganizationExist";`,
+ `const api_org_controller = require('../../controllers/api/index').organizations;`,
+ `API_ORG_CREATE("https://qyapi.weixin.qq.com/cgi-bin/department/create?access_token=ACCESS_TOKEN"),`,
+ `def test_internal_api_org_inclusion_with_href(api_name, href, expected, monkeypatch, called_with):
+ monkeypatch.setattr("requests.sessions.Session.request", called_with)`,
+ ` def _api_org_96726c78_4ae3_402f_b08b_7a78c6903d2a(self, method, url, body, headers):
+ body = self.fixtures.load("api_org_96726c78_4ae3_402f_b08b_7a78c6903d2a.xml")
+ return httplib.OK, body, headers, httplib.responses[httplib.OK]`,
+ `You should see a token hf_xxxxx (old tokens are api_XXXXXXXX or api_org_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX).
`,
+ ` From Hugging Face docs:
+ 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 utils.Validate(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/infracost.go b/cmd/generate/config/rules/infracost.go
new file mode 100644
index 0000000..fba2355
--- /dev/null
+++ b/cmd/generate/config/rules/infracost.go
@@ -0,0 +1,42 @@
+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"
+)
+
+func InfracostAPIToken() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "infracost-api-token",
+ Description: "Detected an Infracost API Token, risking unauthorized access to cloud cost estimation tools and financial data.",
+ Regex: utils.GenerateUniqueTokenRegex(`ico-[a-zA-Z0-9]{32}`, false),
+ Entropy: 3,
+ Keywords: []string{"ico-"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("ico", "ico-"+secrets.NewSecret("[A-Za-z0-9]{32}"))
+ tps = append(tps,
+ ` variable {
+ name = "INFRACOST_API_KEY"
+ secret_value = "ico-mlCr1Mn3SRcRiZMObUZOTHLcgtH2Lpgt"
+ is_secret = true
+ }`,
+ // TODO: New format with longer keys?
+ // ` headers = {
+ //'X-Api-Key': 'ico-EeDdSfctrmjD14f45f45te5gJ7l6lw4o6M36sXT62a6',
+ //'Content-Type': 'application/json',
+ //}`,
+ )
+ fps := []string{
+ // Low entropy
+ `ico-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX`,
+ // Invalid
+ `http://assets.r7.com/assets/media_box_tv_tres_colunas/video_box.ico-7a388b69018576d24b59331fd60aab0c.png`,
+ `https://explosivelab.notion.site/Pianificazione-Nerdz-Ng-pubblico-1bc826ecc0994dd8915be97fc3489cde?pvs=74`,
+ `http://ece252-2.uwaterloo.ca:2540/image?q=gAAAAABdHkoqb9ZaJ3q4dlzEvTgG9WYwKcD9Aw7OUXeFicO-5M5IdNDjHBpKw7KBK3nCVqtuga4yzUaFEpJn8BqA1LzZprIJBw==`,
+ }
+ return utils.Validate(r, tps, fps)
+}
diff --git a/cmd/generate/config/rules/intercom.go b/cmd/generate/config/rules/intercom.go
new file mode 100644
index 0000000..9a0eda2
--- /dev/null
+++ b/cmd/generate/config/rules/intercom.go
@@ -0,0 +1,22 @@
+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"
+)
+
+func Intercom() *config.Rule {
+ // define rule
+ r := config.Rule{
+ Description: "Identified an Intercom API Token, which could compromise customer communication channels and data privacy.",
+ RuleID: "intercom-api-key",
+ Regex: utils.GenerateSemiGenericRegex([]string{"intercom"}, utils.AlphaNumericExtended("60"), true),
+
+ Keywords: []string{"intercom"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("intercom", secrets.NewSecret(utils.AlphaNumericExtended("60")))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/intra42.go b/cmd/generate/config/rules/intra42.go
new file mode 100644
index 0000000..da6c61b
--- /dev/null
+++ b/cmd/generate/config/rules/intra42.go
@@ -0,0 +1,31 @@
+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"
+)
+
+func Intra42ClientSecret() *config.Rule {
+ // define 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: utils.GenerateUniqueTokenRegex(`s-s4t2(?:ud|af)-(?i)[abcdef0123456789]{64}`, false),
+ Entropy: 3,
+ Keywords: []string{
+ "intra",
+ "s-s4t2ud-",
+ "s-s4t2af-",
+ },
+ }
+
+ // validate
+ tps := []string{
+ "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 utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/jfrog.go b/cmd/generate/config/rules/jfrog.go
new file mode 100644
index 0000000..db76e2e
--- /dev/null
+++ b/cmd/generate/config/rules/jfrog.go
@@ -0,0 +1,64 @@
+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"
+)
+
+func JFrogAPIKey() *config.Rule {
+ keywords := []string{"jfrog", "artifactory", "bintray", "xray"}
+
+ // Define Rule
+ r := config.Rule{
+ // Human readable description of the rule
+ Description: "Found a JFrog API Key, posing a risk of unauthorized access to software artifact repositories and build pipelines.",
+
+ // Unique ID for the rule
+ RuleID: "jfrog-api-key",
+
+ // Regex capture group for the actual secret
+
+ // Regex used for detecting secrets. See regex section below for more details
+ 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(utils.AlphaNumeric("73"))),
+ }
+ return utils.Validate(r, tps, nil)
+}
+
+func JFrogIdentityToken() *config.Rule {
+ keywords := []string{"jfrog", "artifactory", "bintray", "xray"}
+
+ // Define Rule
+ r := config.Rule{
+ // Human readable description of the rule
+ Description: "Discovered a JFrog Identity Token, potentially compromising access to JFrog services and sensitive software artifacts.",
+
+ // Unique ID for the rule
+ RuleID: "jfrog-identity-token",
+
+ // Regex capture group for the actual secret
+
+ // Regex used for detecting secrets. See regex section below for more details
+ Regex: utils.GenerateSemiGenericRegex(keywords, utils.AlphaNumeric("64"), true),
+
+ // Keywords used for string matching on fragments (think of this as a prefilter)
+ Keywords: keywords,
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("jfrog", secrets.NewSecret(utils.AlphaNumeric("64")))
+ tps = append(tps, utils.GenerateSampleSecrets("artifactory", secrets.NewSecret(utils.AlphaNumeric("64")))...)
+ tps = append(tps, utils.GenerateSampleSecrets("bintray", secrets.NewSecret(utils.AlphaNumeric("64")))...)
+ tps = append(tps, utils.GenerateSampleSecrets("xray", secrets.NewSecret(utils.AlphaNumeric("64")))...)
+ tps = append(tps, fmt.Sprintf("\"artifactory\", \"%s\"", secrets.NewSecret(utils.AlphaNumeric("64"))))
+ return utils.Validate(r, tps, nil)
+}
diff --git a/cmd/generate/config/rules/jwt.go b/cmd/generate/config/rules/jwt.go
new file mode 100644
index 0000000..0e93702
--- /dev/null
+++ b/cmd/generate/config/rules/jwt.go
@@ -0,0 +1,194 @@
+package rules
+
+import (
+ b64 "encoding/base64"
+ "fmt"
+
+ "github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils"
+ "github.com/zricethezav/gitleaks/v8/cmd/generate/secrets"
+ "github.com/zricethezav/gitleaks/v8/config"
+ "github.com/zricethezav/gitleaks/v8/regexp"
+)
+
+func JWT() *config.Rule {
+ // define 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: utils.GenerateUniqueTokenRegex(`ey[a-zA-Z0-9]{17,}\.ey[a-zA-Z0-9\/\\_-]{17,}\.(?:[a-zA-Z0-9\/\\_-]{10,}={0,2})?`, false),
+ Entropy: 3,
+ Keywords: []string{"ey"},
+ }
+
+ // validate
+ tps := utils.GenerateSampleSecrets("jwt", secrets.NewSecret(`ey[a-zA-Z0-9]{17,}\.ey[a-zA-Z0-9\/\\_-]{17,}\.(?:[a-zA-Z0-9\/\\_-]{10,}={0,2})?`))
+ tps = append(tps,
+ `eyJhbGciOieeeiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwic3ViZSI6IjEyMzQ1Njc4OTAiLCJuYW1lZWEiOiJKb2huIERvZSIsInN1ZmV3YWZiIjoiMTIzNDU2Nzg5MCIsIm5hbWVmZWF3ZnciOiJKb2huIERvZSIsIm5hbWVhZmV3ZmEiOiJKb2huIERvZSIsInN1ZndhZndlYWIiOiIxMjM0NTY3ODkwIiwibmFtZWZ3YWYiOiJKb2huIERvZSIsInN1YmZ3YWYiOiIxMjM0NTY3ODkwIiwibmFtZndhZSI6IkpvaG4gRG9lIiwiaWZ3YWZhYXQiOjE1MTYyMzkwMjJ9.a_5icKBDo-8EjUlrfvz2k2k-FYaindQ0DEYNrlsnRG0==`, // gitleaks:allow
+ `JWT := eyJhbGciOieeeiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwic3ViZSI6IjEyMzQ1Njc4OTAiLCJuYW1lZWEiOiJKb2huIERvZSIsInN1ZmV3YWZiIjoiMTIzNDU2Nzg5MCIsIm5hbWVmZWF3ZnciOiJKb2huIERvZSIsIm5hbWVhZmV3ZmEiOiJKb2huIERvZSIsInN1ZndhZndlYWIiOiIxMjM0NTY3ODkwIiwibmFtZWZ3YWYiOiJKb2huIERvZSIsInN1YmZ3YWYiOiIxMjM0NTY3ODkwIiwibmFtZndhZSI6IkpvaG4gRG9lIiwiaWZ3YWZhYXQiOjE1MTYyMzkwMjJ9.a_5icKBDo-8EjUlrfvz2k2k-FYaindQ0DEYNrlsnRG0`, // gitleaks:allow
+ `"access_token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiJRMzFDVlMxUFNDSjRPVEsyWVZFTSIsImF0X2hhc2giOiI4amItZFE2OXRtZEVueUZaMUttNWhnIiwiYXVkIjoiZXhhbXBsZS1hcHAiLCJlbWFpbCI6ImFkbWluQGV4YW1wbGUuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImV4cCI6IjE1OTQ2MDAxODIiLCJpYXQiOjE1OTQ1ODkzODQsImlzcyI6Imh0dHA6Ly8xMjcuMC4wLjE6NTU1Ni9kZXgiLCJuYW1lIjoiYWRtaW4iLCJzdWIiOiJDaVF3T0dFNE5qZzBZaTFrWWpnNExUUmlOek10T1RCaE9TMHpZMlF4TmpZeFpqVTBOallTQld4dlkyRnMifQ.nrbzIJz99Om7TvJ04jnSTmhvlM7aR9hMM1Aqjp2ONJ1UKYCvegBLrTu6cYR968_OpmnAGJ8vkd7sIjUjtR4zbw"`, // gitleaks:allow
+ `https://dai2-playlistserver.aws.syncbak.com/cpl/20980038/dai2v5/1.0/7b2264657669636554797065223a387d/master.m3u8?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IkdyYXkyMDE2MDgyOSJ9.eyJtaWQiOiIyMDk4MDAzOCIsImNpZCI6MjE5MDMsInNpZCI6MTU4LCJtZDUiOiIwN2QxMmRjNjAwOTM2MGI0MmY3NjNkNTRiMWIwZjI1NCIsImlhdCI6MTY2MDkxMzU2MCwiZXhwIjoxNjkyNDQ5NTYwLCJpc3MiOiJTeW5jYmFrIChURykifQ.JrWVgwzIn_RcNuWhkzIjr1i4qjXU1v4n0KFrSzoTQvQ`, // gitleaks:allow `
+ `"SessionToken": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiI2TjJCQUxYN0VMTzgyN0RYUzNHSyIsImFjciI6IjAiLCJhdWQiOiJhY2NvdW50IiwiYXV0aF90aW1lIjoxNTY5OTEwNTUyLCJhenAiOiJhY2NvdW50IiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJleHAiOjE1Njk5MTQ1NTQsImlhdCI6MTU2OTkxMDk1NCwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgxL2F1dGgvcmVhbG1zL2RlbW8iLCJqdGkiOiJkOTk4YTBlZS01NDk2LTQ4OWYtYWJlMi00ZWE5MjJiZDlhYWYiLCJuYmYiOjAsInBvbGljeSI6InJlYWR3cml0ZSIsInByZWZlcnJlZF91c2VybmFtZSI6Im5ld3VzZXIxIiwic2Vzc2lvbl9zdGF0ZSI6IjJiYTAyYTI2LWE5MTUtNDUxNC04M2M1LWE0YjgwYjc4ZTgxNyIsInN1YiI6IjY4ZmMzODVhLTA5MjItNGQyMS04N2U5LTZkZTdhYjA3Njc2NSIsInR5cCI6IklEIn0._UG_-ZHgwdRnsp0gFdwChb7VlbPs-Gr_RNUz9EV7TggCD59qjCFAKjNrVHfOSVkKvYEMe0PvwfRKjnJl3A_mBA",`, // gitleaks:allow
+ `2020/11/04 21:08:40 Access Token:
+ "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiYTAwYzI3ZDEtYjVhYS00NjU0LWFmMTYtYjExNzNkZTY1NjI5Iiwicm9sZXMiOlsiYWRtaW4iXSwiaWF0IjoxNjA0NTE2OTIwLCJleHAiOjE2MDQ1MTc4MjAsImp0aSI6IjYzNmVmMDc0LTE2MzktNGJhZi1hNGNiLTQ4ZDM4NGMxMzliYSIsImlzcyI6Im15YXBwIn0.T9B0zG0AHShO5JfQgrMQBlToH33KHgp8nLMPFpN6QmM"`, // gitleaks:allow
+ `"idToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ik56azVNREl5TVRnNFJqWTBORGswT0VJM1JrRXpORGN4UmtVMU1FWXdNemczT1VKQlFqRTBNZyJ9.eyJuaWNrbmFtZSI6InRlc3QtaW50ZXJhY3RpdmUtY2xpIiwibmFtZSI6IlRlc3RpbmcgSW50ZXJhY3RpdmUgQ2xpIiwicGljdHVyZSI6Imh0dHBzOi8vaW50ZXJhdGNpdmUuY2xpL3Rlc3RpbmcucG5nIiwidXBkYXRlZF9hdCI6IjIwMTktMDktMTZUMTU6MTg6NDMuOTk5WiIsImVtYWlsIjoidGVzdGluZ0BpbnRlcmFjdGl2ZS5jbGkiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaXNzIjoiaHR0cHM6Ly9zZXJ2ZXJsZXNzaW5jLmF1dGgwLmNvbS8iLCJzdWIiOiJ0ZXN0LWludGVyYWN0aXZlLWNsaSIsImF1ZCI6IlhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYIiwiaWF0IjoxNTYwMDAwMDAwLCJleHAiOjMwMDAwMDAwMDB9.GcNQtWSxv9CHTABw-HIjYSvRxTEapDUDqIIWRGmz01XmShQxRGOHRuUg1NKU4w9MpOlB6txHKs8UWd2eZkzw_Z4QmIuLyAVhVklpWP2-xeysPLUyqVTgqAg8kgIUAwdKjmrdpQqHhGd-Q1BIX62-E-qKKx8prmADSw_hgmuvlMuSCa1ajCnfyUXycQxDmbFrvjd24lJER0FSpB2nWWW3KxZ_UBX-TuVmiEtRXg9GYeSv6oIU78PrIhYgJ0QjERRF1yAYamIXNRs-KZ7Z4YiFNC4uKzFH1524pZkS4Q0-pweIvBrrsjekz-vEYcbaVG1zAxDu_yNrYPk5phCy8MHTrQ",`, // gitleaks:allow
+ `TokenIssuer1WithAzp = "eyJhbGciOiJSUzI1NiIsImtpZCI6InRUX3c5TFJOclk3d0phbEdzVFlTdDdydXRaaTg2R3Z5YzBFS1I0Q2FRQXciLCJ0eXAiOiJKV1QifQ.eyJhenAiOiJiYXIiLCJleHAiOjQ3MzQxMjU0NTMsImlhdCI6MTU4MDUyNTQ1MywiaXNzIjoidGVzdC1pc3N1ZXItMUBpc3Rpby5pbyIsInN1YiI6InN1Yi0xIn0.SO4qjRJPYItkpGGpCDfEhaUfdthO8L9b_aawao4dJKyqqXN0uYdsJau_JZzyPQ1emAmJP7VyjwELrlszA6xV65na_O-eny23iwhEoroChQMpcr9DWqSUBUfpbHSPFAjUv38SUbQfLgar0HrMxQlTAzB0vyzn2g6-cukP469ZlOUmzvi9b4UpolTLp_WPgEHKjZw8CL56CcuJqBIKgfn0M7ta2bY_qx-UrsEW0CqnXol7vhXuDAfMeWZYKuDP8qc2VH1T6wpO2JnZ0EaNDuZfQLOWFYKsFGlaYcus9j462AfJQBSFQTbkIjkvKMK6aI_rMEesAnJr2eei1UYi14JYiQ"`, // gitleaks:allow
+ `eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjM1MzczOTExMDQsImdyb3VwcyI6WyJncm91cDEiLCJncm91cDIiXSwiaWF0IjoxNTM3MzkxMTA0LCJpc3MiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyIsInNjb3BlIjpbInNjb3BlMSIsInNjb3BlMiJdLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyJ9.EdJnEZSH6X8hcyEii7c8H5lnhgjB5dwo07M5oheC8Xz8mOllyg--AHCFWHybM48reunF--oGaG6IXVngCEpVF0_P5DwsUoBgpPmK1JOaKN6_pe9sh0ZwTtdgK_RP01PuI7kUdbOTlkuUi2AO-qUyOm7Art2POzo36DLQlUXv8Ad7NBOqfQaKjE9ndaPWT7aexUsBHxmgiGbz1SyLH879f7uHYPbPKlpHU6P9S-DaKnGLaEchnoKnov7ajhrEhGXAQRukhDPKUHO9L30oPIr5IJllEQfHYtt6IZvlNUGeLUcif3wpry1R5tBXRicx2sXMQ7LyuDremDbcNy_iE76Upg`, // gitleaks:allow
+ `python examples/cli.py eyJhbGciOiJIUzI1NiJ9.eyJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkJhZFNlY3JldHMiLCJleHAiOjE1OTMxMzM0ODMsImlhdCI6MTQ2NjkwMzA4M30.ovqRikAo_0kKJ0GVrAwQlezymxrLGjcEiW_s3UJMMCo`, // gitleaks:allow
+ `"Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VybmFtZTpib2IifQ.HcfCW67Uda-0gz54ZWTqmtgJnZeNem0Q757eTa9EZuw"`, // gitleaks:allow
+ `"value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODk1ODU1NjN9.PtfDS1niGoZ7pV6kplI-_q1fVKLnknQ3IwcrLZhoVCU",`, // gitleaks:allow
+ `// authorization: 'eyJhbGciOiJIUzUxMiIsImlhdCI6MTU3Njk5Njc5OSwiZXhwIjoxNTg0ODU5MTk5fQ.eyJ1aWQiOjQ1NzQyN30.0ei5UE6OgLBzN2_IS7xUIbIfW_S1Wzl42q2UeusbboxuzvctO_4Mz6YRr6f0PBLUVZMETxt8F0_4-yqIJ3_kUQ',`, // gitleaks:allow
+ `eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJpc3Rpby1jbmktdG9rZW4tcGpwYnciLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiaXN0aW8tY25pIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiZmY2MDY0ODAtY2MxMC0xMWU4LTkxYzctMDAwYWY3MGE5YmE4Iiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmlzdGlvLWNuaSJ9.0YHfuEwYn6tbtgy1YOhOjEtuQ8TnvmA_1RkuggfVGigMpCMGoOkIWwxpeDVXZm7dNwRmQVwLhchA3MeXz0QGRmStLa-VncedkmPOGSC-FyPvPybhZI53w3nhIVU3Vkh9_s-E2H2zFTwRQthxlDAlldNqEHpM9fINIVs0Z3bAogz2DYHwerSOtfZU-6d8b5nn73gnNhl6zBJ_0qg22SZjc6TrDYk--WwjUbU5_OIW6YxEmFnNVqfSeCrpg18IiJCsB0XRkixgu46Ev63jsrJ1vi41PVvBN79X7F-SiNNwTqwACRZvlX1zRw_GV7o4iPvnKn685WLOyMfoB5K6hSxrpQ`, // gitleaks:allow
+ `const TestKubernetesJWT_A = "eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImFkbWluLXRva2VuLXFsejQyIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiNzM4YmMyNTEtNjUzMi0xMWU5LWI2N2YtNDhlNmM4YjhlY2I1Iiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlZmF1bHQ6YWRtaW4ifQ.ixMlnWrAG7NVuTTKu8cdcYfM7gweS3jlKaEsIBNGOVEjPE7rtXtgMkAwjQTdYR08_0QBjkgzy5fQC5ZNyglSwONJ-bPaXGvhoH1cTnRi1dz9H_63CfqOCvQP1sbdkMeRxNTGVAyWZT76rXoCUIfHP4LY2I8aab0KN9FTIcgZRF0XPTtT70UwGIrSmRpxW38zjiy2ymWL01cc5VWGhJqVysmWmYk3wNp0h5N57H_MOrz4apQR4pKaamzskzjLxO55gpbmZFC76qWuUdexAR7DT2fpbHLOw90atN_NlLMY-VrXyW3-Ei5EhYaVreMB9PSpKwkrA4jULITohV-sxpa1LA"`, // gitleaks:allow
+ `string: grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJkZXYtdG8tYW5hbHl0aWMtYXBpLW1hYy10ZXN0QGRldnRvLTE3NTQxOS5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsImF1ZCI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL29hdXRoMi92NC90b2tlbiIsImV4cCI6MTUxOTIyOTAxOSwiaWF0IjoxNTE5MjI4ODk5LCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvYW5hbHl0aWNzLnJlYWRvbmx5In0.V8CSfSS7sKfoE5857jE9WDrGFHF1CyRr3cZpdUv9MjaaTcPRSLuNxB8yrxRP_7hNmlRgx_KdUzBgDJp3M_9tU4rZgFaIC7-bctvz_0rqbnMqSTniHYNGo7w__zO0bRaTpR3ILOfoxCQLcVC-tA4eCIMzRCznkY0VAaoLM7K-hnwQz6fCqSF31fmOwzAdVBPi5qnMETogh_7SiHn4WNUYI0FQf5SFLhcCbBZtORcbANe9hXp9po2P-VTBqs6u9dAZw5kZ2c1l5zbzrjYp5VcYl1XQFQTxP2zgMxhpX3k1UH9ObggOMUxvASyLbPZ7viOPKRlFxkAAHPTN2N1FYbpVeA`, // gitleaks:allow
+ `eyJhbGciOiJSUzI1NiIsImtpZCI6IlM1WGxrRnVIclJRaEVDbmg3cndZZFVTRTFpT0lfQzZsZ2NXbHZoOS1pbVUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLWo1a3B2Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJiZTZjZmUwZS0yYzFhLTRkNTYtYmVkMC1jYWRmYjYxNzA1N2YiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZXJuZXRlcy1kYXNoYm9hcmQ6YWRtaW4tdXNlciJ9.LaBPEh6Qantd8tAc0X5DY9dDwUqZpxu38FHnp9TSJw-ghs3TsjrscFulUeEAtp2ng3ElLcU4SbNKPGJflF2dyW9Tmfn-Kt_6Jwq8HQ9GOCwAicEz0JVireHA7EWhATzuT56eO6MTe-2j5bpGnPQRJJtQ8AbtAN3nVK7RPjSzmc8Ppqx1z5i4oCGwiyRlGwqT-FkCtQLbQaQ4XmrASQoN4pJ_OBy5slztUhk32HdGP6pQx5c-nfei-of_4ij_fHrP0xEEfmVVvXqi9WKv1PLkQ3qTiSFDzv8M2sE4T6XmCGBbw7gyHzEGSpOAPZr00bX_YMCUvEF0lyP4YK696xWCBA`, // gitleaks:allow
+ `$ curl "http://admin:password@127.0.0.1:8080/api/v2/token"
+ {"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiQVBJIl0sImV4cCI6MTYxMzMzNTI2MSwianRpIjoiYzBrb2gxZmNkcnBjaHNzMGZwZmciLCJuYmYiOjE2MTMzMzQ2MzEsInBlcm1pc3Npb25zIjpbIioiXSwic3ViIjoiYUJ0SHUwMHNBUmxzZ29yeEtLQ1pZZWVqSTRKVTlXbThHSGNiVWtWVmc1TT0iLCJ1c2VybmFtZSI6ImFkbWluIn0.WiyqvUF-92zCr--y4Q_sxn-tPnISFzGZd_exsG-K7ME","expires_at":"2021-02-14T20:41:01Z"}`, // gitleaks:allow
+ `curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiQVBJIl0sImV4cCI6MTYxMzMzNTI2MSwianRpIjoiYzBrb2gxZmNkcnBjaHNzMGZwZmciLCJuYmYiOjE2MTMzMzQ2MzEsInBlcm1pc3Npb25zIjpbIioiXSwic3ViIjoiYUJ0SHUwMHNBUmxzZ29yeEtLQ1pZZWVqSTRKVTlXbThHSGNiVWtWVmc1TT0iLCJ1c2VybmFtZSI6ImFkbWluIn0.WiyqvUF-92zCr--y4Q_sxn-tPnISFzGZd_exsG-K7ME" "http://127.0.0.1:8080/api/v2/dumpdata?output-data=1"`, // gitleaks:allow
+ `"authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiZ3Vlc3QiLCJzdWIiOiJZV3hwWTJVPSIsIm5iZiI6MTUxNDg1MTEzOSwiZXhwIjoxNjQxMDgxNTM5fQ.K5DnnbbIOspRbpCr2IKXE9cPVatGOCBrBQobQmBmaeU"`, // gitleaks:allow
+ `{"signatures": [ "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmaWxlcyI6W3sibmFtZSI6Ii5tYW5pZmVzdCIsImhhc2giOiJjMjEzMTU0NGM3MTZhMjVhNWUzMWY1MDQzMDBmNTI0MGU4MjM1Y2FkYjlhNTdmMGJkMWI2ZjRiZDc0YjI2NjEyIiwiYWxnb3JpdGhtIjoiU0hBMjU2In0seyJuYW1lIjoicm9sZXMvYmluZGluZ3MvZGF0YS5qc29uIiwiaGFzaCI6IjQyY2ZlNjc2OGI1N2JiNWY3NTAzYzE2NWMyOGRkMDdhYzViODEzNTU0ZWJjODUwZjJjYzM1ODQzZTcxMzdiMWQifV0sImlhdCI6MTU5MjI0ODAyNywiaXNzIjoiSldUU2VydmljZSIsImtleWlkIjoibXlQdWJsaWNLZXkiLCJzY29wZSI6IndyaXRlIn0.ZjtUgXC6USwmhv4XP9gFH6MzZwpZrGpAL_2sTK1P-mg"]}`, // gitleaks:allow
+ `"id_token": "eyJ4NXQiOiJOVEF4Wm1NeE5ETXlaRGczTVRVMVpHTTBNekV6T0RKaFpXSTRORE5sWkRVMU9HRmtOakZpTVEiLCJraWQiOiJOVEF4Wm1NeE5ETXlaRGczTVRVMVpHTTBNekV6T0RKaFpXSTRORE5sWkRVMU9HRmtOakZpTVEiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJQb0VnWFA2dVZPNDVJc0VOUm5nRFhqNUF1NVlhIiwiYXpwIjoiUG9FZ1hQNnVWTzQ1SXNFTlJuZ0RYajVBdTVZYSIsImlzcyI6Imh0dHBzOlwvXC9sb2NhbGhvc3Q6OTQ0M1wvb2F1dGgyXC90b2tlbiIsImV4cCI6MTUzNDg5MTc3OCwiaWF0IjoxNTM0ODg4MTc4LCJqdGkiOiIxODQ0MzI5Yy1kNjVhLTQ4YTMtODIyOC05ZGY3M2ZlODNkNTYifQ.ELZ8ujk2Xp9xTGgMqnCa5ehuimaAPXWlSCW5QeBbTJIT4M5OB_2XEVIV6p89kftjUdKu50oiYe4SbfrxmLm6NGSGd2qxkjzJK3SRKqsrmVWEn19juj8fz1neKtUdXVHuSZu6ws_bMDy4f_9hN2Jv9dFnkoyeNT54r4jSTJ4A2FzN2rkiURheVVsc8qlm8O7g64Az-5h4UGryyXU4zsnjDCBKYk9jdbEpcUskrFMYhuUlj1RWSASiGhHHHDU5dTRqHkVLIItfG48k_fb-ehU60T7EFWH1JBdNjOxM9oN_yb0hGwOjLUyCUJO_Y7xcd5F4dZzrBg8LffFmvJ09wzHNtQ",`, // gitleaks:allow
+ ` # The following default key is generated by the local Supabase start and doesn't change
+ - SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0`, // gitleaks:allow
+ `Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhIjoxLCJiIjoyLCJjIjozfQ.hxhGCCCmGV9nT1slief1WgEsOsfdnlVizNrODxfh1M8`, // gitleaks:allow
+ `--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJhY3RvclR5cGUiOiJVU0VSIiwiYWN0b3JJZCI6ImRhdGFodWIiLCJ0eXBlIjoiUEVSU09OQUwiLCJ2ZXJzaW9uIjoiMSIsImV4cCI6MTY1MDY2MDY1NSwianRpIjoiM2E4ZDY3ZTItOTM5Yi00NTY3LWE0MjYtZDdlMDA1ZGU3NjJjIiwic3ViIjoiZGF0YWh1YiIsImlzcyI6ImRhdGFodWItbWV0YWRhdGEtc2VydmljZSJ9.pp_vW2u1tiiTT7U0nDF2EQdcayOMB8jatiOA8Je4JJA' \`, // gitleaks:allow
+ `"Cookie": "auth-token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NDIxMTEsImlzQWRtaW4iOmZhbHNlLCJnaXRodWJJZCI6ImR5ZXhwbG9kZSIsImFwcFJvbGVzIjpbInVzZXIiXSwicm9sZXMiOnsiNDciOiJzdHVkZW50IiwiNTYiOiJzdHVkZW50In0sImNvdXJzZXNSb2xlcyI6eyI0NyI6WyJzdHVkZW50Il0sIjU2IjpbInN0dWRlbnQiXX0sImNvdXJzZXMiOnsiNDciOnsibWVudG9ySWQiOm51bGwsInN0dWRlbnRJZCI6NjY3OTMsInJvbGVzIjpbInN0dWRlbnQiXX0sIjU2Ijp7Im1lbnRvcklkIjpudWxsLCJzdHVkZW50SWQiOjYzMzk4LCJyb2xlcyI6WyJzdHVkZW50Il19fSwiaWF0IjoxNjQ1MjA5NzI2LCJleHAiOjE2NDUzODI1MjZ9.btpYeSioEDUNMI6bAPqgu5zndA8XR5DT8P9U9kotOEA",`, // gitleaks:allow
+ `
+ 在线演示`, // gitleaks:allow
+ `eyJhbGciOiJSUzI1NiIsImtpZCI6IlM1WGxrRnVIclJRaEVDbmg3cndZZFVTRTFpT0lfQzZsZ2NXbHZoOS1pbVUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLWo1a3B2Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJiZTZjZmUwZS0yYzFhLTRkNTYtYmVkMC1jYWRmYjYxNzA1N2YiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZXJuZXRlcy1kYXNoYm9hcmQ6YWRtaW4tdXNlciJ9.LaBPEh6Qantd8tAc0X5DY9dDwUqZpxu38FHnp9TSJw-ghs3TsjrscFulUeEAtp2ng3ElLcU4SbNKPGJflF2dyW9Tmfn-Kt_6Jwq8HQ9GOCwAicEz0JVireHA7EWhATzuT56eO6MTe-2j5bpGnPQRJJtQ8AbtAN3nVK7RPjSzmc8Ppqx1z5i4oCGwiyRlGwqT-FkCtQLbQaQ4XmrASQoN4pJ_OBy5slztUhk32HdGP6pQx5c-nfei-of_4ij_fHrP0xEEfmVVvXqi9WKv1PLkQ3qTiSFDzv8M2sE4T6XmCGBbw7gyHzEGSpOAPZr00bX_YMCUvEF0lyP4YK696xWCBA`, // gitleaks:allow
+ `eyJhbGciOiJSUzI1NiJ9.eyJ1c2VybmFtZSI6IlRlc3QiLCJsb2dnZWQtaW4tdXNlciI6eyJzY29wZWRQZXJtaXNzaW9uIjpbXSwicGVybWlzc2lvbnMiOlsiQS5hZG1pbl9jdXN0b21lcl9kZWxldGUiLCJBLm5vcm1hbF91c2VyX2FwcCIsIkEubm9ybWFsX3VzZXJfY29uZmlndXJhdGlvbiIsIkEubm9ybWFsX3VzZXJfd2VsY29tZV9jb250cm9scyIsIkEubm9ybWFsX3VzZXJfb3JkZXIiLCJBLm5vcm1hbF91c2VyX3NlYXJjaCIsIkEubm9ybWFsX3VzZXJfc2VhcmNoX3BjIiwiQS5ub3JtYWxfdXNlcl9zZWFyY2hfcHJpdmF0ZSIsIkEubm9ybWFsX3VzZXJfcHJpY2luZyIsIkEubm9ybWFsX3VzZXJfcHJpdmF0ZSIsIkEubm9ybWFsX3VzZXJfY29tbWVyY2lhbCIsIkEubm9ybWFsX3VzZXJfcGMiXSwibmFtZSI6WyJUZXN0Il0sIm1haWwiOlsiVGVzdEBleGFtcGxlLmNvbSJdLCJvcmdhbml6YXRpb24iOlsiWC1YeHh4eHguMTIzNCJdLCJsb2NhdGlvbiI6WyIxMjMyMSJdLCJ1bml0IjpbIjEwMyJdLCJjb3VudHJ5IjpbIkNOIl0sInVzZXJUeXBlIjoiZW1wbG95ZWUifSwiaWRlbnRpdHktaWQiOiJNb2NrIn0.EK5TbwsIgde3mT3n7NK2W7TCvpgQQLzshvPPANRQeUmKOv2AWbo_7vNEDTSkwUlaHRN3-dknv8F95p5MsGTzH6Uva8aOPJG6JdBIoYX_ud3aBN-hY1i2Xpf8pqjeINfY3_gDNAB9gdMznEej2uqhPwUXmZtcuWPdUCCeNqPJbRUAJeVXxLr_JtQzO2jmuwNY_YYp7KaEIANZwG1spvLuIGZ0HA03u8ye9c2lfqYcjgfIkjMrwgWPamR7joZOZPdQSO2EHrF7bUWMjRNY-FF5V7tOjEijkknE_nDq5THcEvx1seHYFdFNwy9LSSGGPVmZMKTKQ3UUlZZyBMXcOpOA9w`, // gitleaks:allow
+ // TODO: Detect newlines or escapes (\)?
+ // https://github.com/mongodb/mongo/blob/1960b792ade4e179ddc6113a3cd400e9492ca11d/src/mongo/crypto/README.JWT.md?plain=1#L115-L117
+ // TODO: Detect empty claims section?
+ // `eyJhbGciOiJFQ0RILUVTIiwiZW5jIjoiQTI1NkdDTSIsImVwayI6eyJrdHkiOiJFQyIsImNydiI6IlAtMzg0Iiwia2V5X29wcyI6W10sImV4dCI6dHJ1ZSwieCI6IllUcEY3bGtTc3JvZVVUVFdCb21LNzBTN0FhVTJyc0ptMURpZ1ZzbjRMY2F5eUxFNFBabldkYmFVcE9jQVV5a1ciLCJ5IjoiLU5pS3loUktjSk52Nm02Z0ZJUWc4cy1Xd1VXUW9uT3A5dkQ4cHpoa2tUU3U2RzFlU2FUTVlhZGltQ2Q4V0ExMSJ9LCJhcHUiOiIiLCJhcHYiOiIifQ`,
+ `String tokenWithNoneAlg = "eyJhbGciOiJub25lIn0.eyJzdWIiOiJ0ZXN0LXVzZXIifQ.";`, // gitleaks:allow
+ `# Req: Invoke-RestMethod -Uri 'http://localhost:8085/users' -Headers @{ 'X-API-KEY' = 'eyJhbGciOiJub25lIn0.eyJ1c2VybmFtZSI6Im1vcnR5Iiwic3ViIjoiMTIzIn0.' }`, // gitleaks:allow
+ )
+ fps := []string{}
+ return utils.Validate(r, tps, fps)
+}
+
+func JWTBase64() *config.Rule {
+ // define rule
+ r := config.Rule{
+ RuleID: "jwt-base64",
+ Description: "Detected a Base64-encoded JSON Web Token, posing a risk of exposing encoded authentication and data exchange information.",
+ Regex: regexp.MustCompile(
+ `\bZXlK(?:(?PaGJHY2lPaU)|(?PaGNIVWlPaU)|(?PaGNIWWlPaU)|(?PaGRXUWlPaU)|(?PaU5qUWlP)|(?PamNtbDBJanBi)|(?PamRIa2lPaU)|(?PbGNHc2lPbn)|(?PbGJtTWlPaU)|(?PcWEzVWlPaU)|(?PcWQyc2lPb)|(?PcGMzTWlPaU)|(?PcGRpSTZJ)|(?PcmFXUWlP)|(?PclpYbGZiM0J6SWpwY)|(?PcmRIa2lPaUp)|(?PdWIyNWpaU0k2)|(?Pd01tTWlP)|(?Pd01uTWlPaU)|(?Pd2NIUWlPaU)|(?PemRXSWlPaU)|(?PemRuUWlP)|(?PMFlXY2lPaU)|(?PMGVYQWlPaUp)|(?PMWNtd2l)|(?P