diff --git a/.dockerignore b/.dockerignore index 468db29..66d18a4 100644 --- a/.dockerignore +++ b/.dockerignore @@ -6,3 +6,4 @@ !gitleaks_config_generator_tests.py !requirements.txt !global_config.toml +!global_config_legacy.toml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b47b3dc..28f9580 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -14,7 +14,7 @@ env: jobs: build: name: Run tests, build, and publish if needed - runs-on: [self-hosted, bear] + runs-on: [self-hosted, bear-ephemeral] steps: @@ -34,7 +34,7 @@ jobs: env: CONTAINER_REGISTRY: ${{ secrets.ECR_REGISTRY }} - - name: Run integration tests (code samples) for global gitleaks config + - name: Run tests (code samples) for global gitleaks config run: make test-gitleaks-config env: CONTAINER_REGISTRY: ${{ secrets.ECR_REGISTRY }} diff --git a/gitleaks_config_generator.py b/gitleaks_config_generator.py index d9a6dff..ff031d1 100644 --- a/gitleaks_config_generator.py +++ b/gitleaks_config_generator.py @@ -15,7 +15,11 @@ def main(): - final_config = get_final_config('global_config.toml', '.gitleaks.toml') + config_file = 'global_config_legacy.toml' # config file for gitleaks versions previous to v8 + if len(sys.argv) >= 2: + config_file = 'global_config.toml' + + final_config = get_final_config(config_file, '.gitleaks.toml') print(toml.dumps(final_config)) diff --git a/gitleaks_config_generator_tests.py b/gitleaks_config_generator_tests.py index dbfb690..095ad32 100644 --- a/gitleaks_config_generator_tests.py +++ b/gitleaks_config_generator_tests.py @@ -6,16 +6,16 @@ class TestGitleaksConfigGenerator(unittest.TestCase): def test_get_final_config_without_local_config(self): final_config = c.get_final_config('global_config.toml', '') - self.assertFalse('*.mp3' in final_config['allowlist']['files']) + self.assertFalse('*.mp3' in final_config['allowlist']['paths']) def test_get_final_config_with_local_config(self): final_config = c.get_final_config('global_config.toml', 'local-config.toml') - self.assertTrue('*.mp3' in final_config['allowlist']['files']) + self.assertTrue('*.mp3' in final_config['allowlist']['paths']) def test_merge_config(self): final_config = c.merge_config('global_config.toml', 'local-config.toml') - self.assertTrue('*.mp3' in final_config['allowlist']['files']) - self.assertTrue(isinstance(final_config['allowlist']['description'], str)) + self.assertTrue('*.mp3' in final_config['allowlist']['paths']) + self.assertTrue(isinstance(final_config['allowlist']['paths'], list)) def test_merge_old_config(self): final_config = c.merge_config('global_config.toml', 'local-config-old.toml') diff --git a/global_config.toml b/global_config.toml index c0c84e8..85de86a 100644 --- a/global_config.toml +++ b/global_config.toml @@ -1,13 +1,14 @@ title = "Global gitleaks config" [allowlist] -description = "Allowlisted files" -files = [ - '''^\.?gitleaks.toml$''', # Ignoring this file +description = "Global allowlisted paths, files, and stopwords" +# TODO: figure out what to do with the old `.gitleaks.toml` files in repos: migrate them? convert them when mergin them? +paths = [ + '''\.gitleaks\.toml$''', # Ignoring the generated configuration file '''(.*?)(jpg|gif|doc|pdf|bin)$''', # Ignoring common binaries - '''^(.*?)_test\.go$''', # Ignoring Go test files - '''^(.*?)\.(spec|test)\.(j|t)s$''', # Ignoring JavaScript and TypeScript test files - '''(go.mod|go.sum)$''', # Ignoring Go manifests + '''(.*?)_test\.go$''', # Ignoring Go test files + '''(.*?)\.(spec|test)\.(j|t)s$''', # Ignoring JavaScript and TypeScript test files + '''go\.(mod|sum)$''', # Ignoring Go manifests '''vendor\.json''', '''Gopkg\.(lock|toml)''', '''package-lock\.json''', # Ignoring Node/JS manifests @@ -18,30 +19,28 @@ files = [ '''Pipfile''', # Ignoring Python manifests '''Pipfile\.lock''', '''poetry\.lock''', + '''node_modules\/''', # Ignoring Node dependencies + '''vendor\/''', # Ignoring Go dependencies + '''test(|s)\/''', # Ignoring test directories ] -paths = [ - "node_modules", # Ignoring Node dependencies - "vendor", # Ignoring Go dependencies - "test", # Ignoring test directories - "tests", -] -regexes = ['''test'''] # Ignoring lines with test +# TODO: change this to "stopwords" +regexes = ['''someFunnyWord'''] # Ignoring lines with test # The following rules, extracted from gitleak's default config, look for credentials with a well-known format, usually from third parties. # These rules evaluate all file types. [[rules]] description = "Adobe Client ID (Oauth Web)" -#id = "adobe-client-id" +id = "adobe-client-id" regex = '''(?i)(?:adobe)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "adobe", ] [[rules]] description = "Adobe Client Secret" -#id = "adobe-client-secret" +id = "adobe-client-secret" regex = '''(?i)\b((p8e-)(?i)[a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' tags = [ "p8e-", @@ -49,7 +48,7 @@ tags = [ [[rules]] description = "Age secret key" -#id = "age secret key" +id = "age secret key" regex = '''AGE-SECRET-KEY-1[QPZRY9X8GF2TVDW0S3JN54KHCE6MUA7L]{58}''' tags = [ "age-secret-key-1", @@ -57,7 +56,7 @@ tags = [ [[rules]] description = "Alibaba AccessKey ID" -#id = "alibaba-access-key-id" +id = "alibaba-access-key-id" regex = '''(?i)\b((LTAI)(?i)[a-z0-9]{20})(?:['|\"|\n|\r|\s|\x60]|$)''' tags = [ "ltai", @@ -65,36 +64,36 @@ tags = [ [[rules]] description = "Alibaba Secret Key" -#id = "alibaba-secret-key" +id = "alibaba-secret-key" regex = '''(?i)(?:alibaba)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{30})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "alibaba", ] [[rules]] description = "Asana Client ID" -#id = "asana-client-id" +id = "asana-client-id" regex = '''(?i)(?:asana)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([0-9]{16})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "asana", ] [[rules]] description = "Asana Client Secret" -#id = "asana-client-secret" +id = "asana-client-secret" regex = '''(?i)(?:asana)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "asana", ] [[rules]] description = "Atlassian API token" -#id = "atlassian-api-token" +id = "atlassian-api-token" regex = '''(?i)(?:atlassian|confluence)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{24})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "atlassian", "confluence", @@ -102,7 +101,7 @@ tags = [ [[rules]] description = "AWS" -#id = "aws-access-token" +id = "aws-access-token" regex = '''(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}''' tags = [ "akia", @@ -117,34 +116,34 @@ tags = [ [[rules]] description = "BitBucket Client ID" -#id = "bitbucket-client-id" +id = "bitbucket-client-id" regex = '''(?i)(?:bitbucket)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "bitbucket", ] [[rules]] description = "BitBucket Client Secret" -#id = "bitbucket-client-secret" +id = "bitbucket-client-secret" regex = '''(?i)(?:bitbucket)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{64})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "bitbucket", ] [[rules]] description = "Beamer API token" -#id = "beamer-api-token" +id = "beamer-api-token" regex = '''(?i)(?:beamer)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(b_[a-z0-9=_\-]{44})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "beamer", ] [[rules]] description = "Clojars API token" -#id = "clojars-api-token" +id = "clojars-api-token" regex = '''(?i)(CLOJARS_)[a-z0-9]{60}''' tags = [ "clojars", @@ -152,16 +151,16 @@ tags = [ [[rules]] description = "Contentful delivery API token" -#id = "contentful-delivery-api-token" +id = "contentful-delivery-api-token" regex = '''(?i)(?:contentful)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{43})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "contentful", ] [[rules]] description = "Databricks API token" -#id = "databricks-api-token" +id = "databricks-api-token" regex = '''(?i)\b(dapi[a-h0-9]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' tags = [ "dapi", @@ -169,43 +168,43 @@ tags = [ [[rules]] description = "Discord API key" -#id = "discord-api-token" +id = "discord-api-token" regex = '''(?i)(?:discord)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{64})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "discord", ] [[rules]] description = "Discord client ID" -#id = "discord-client-id" +id = "discord-client-id" regex = '''(?i)(?:discord)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([0-9]{18})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "discord", ] [[rules]] description = "Discord client secret" -#id = "discord-client-secret" +id = "discord-client-secret" regex = '''(?i)(?:discord)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "discord", ] [[rules]] description = "Dropbox API secret" -#id = "doppler-api-token" +id = "doppler-api-token" regex = '''(?i)(?:dropbox)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{15})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "dropbox", ] [[rules]] description = "Dropbox long lived API token" -#id = "dropbox-long-lived-api-token" +id = "dropbox-long-lived-api-token" regex = '''(?i)(?:dropbox)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{11}(AAAAAAAAAA)[a-z0-9\-_=]{43})(?:['|\"|\n|\r|\s|\x60]|$)''' tags = [ "dropbox", @@ -213,7 +212,7 @@ tags = [ [[rules]] description = "Dropbox short lived API token" -#id = "dropbox-short-lived-api-token" +id = "dropbox-short-lived-api-token" regex = '''(?i)(?:dropbox)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(sl\.[a-z0-9\-=_]{135})(?:['|\"|\n|\r|\s|\x60]|$)''' tags = [ "dropbox", @@ -221,7 +220,7 @@ tags = [ [[rules]] description = "Doppler API token" -#id = "doppler-api-token" +id = "doppler-api-token" regex = '''(dp\.pt\.)(?i)[a-z0-9]{43}''' tags = [ "doppler", @@ -229,7 +228,7 @@ tags = [ [[rules]] description = "Duffel API token" -#id = "duffel-api-token" +id = "duffel-api-token" regex = '''duffel_(test|live)_(?i)[a-z0-9_\-=]{43}''' tags = [ "duffel", @@ -237,7 +236,7 @@ tags = [ [[rules]] description = "Dynatrace API token" -#id = "dynatrace-api-token" +id = "dynatrace-api-token" regex = '''dt0c01\.(?i)[a-z0-9]{24}\.[a-z0-9]{64}''' tags = [ "dynatrace", @@ -245,7 +244,7 @@ tags = [ [[rules]] description = "EasyPost API token" -#id = "easypost-api-token" +id = "easypost-api-token" regex = '''EZAK(?i)[a-z0-9]{54}''' tags = [ "ezak", @@ -253,7 +252,7 @@ tags = [ [[rules]] description = "EasyPost test API token" -#id = "easypost-test-api-token" +id = "easypost-test-api-token" regex = '''EZTK(?i)[a-z0-9]{54}''' tags = [ "eztk", @@ -261,43 +260,43 @@ tags = [ [[rules]] description = "facebook" -#id = "facebook" +id = "facebook" regex = '''(?i)(?:facebook)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "facebook", ] [[rules]] description = "Fastly API key" -#id = "fastly-api-token" +id = "fastly-api-token" regex = '''(?i)(?:fastly)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "fastly", ] [[rules]] description = "Finicity Client Secret" -#id = "finicity-client-secret" +id = "finicity-client-secret" regex = '''(?i)(?:finicity)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{20})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "finicity", ] [[rules]] description = "Finicity API token" -#id = "finicity-api-token" +id = "finicity-api-token" regex = '''(?i)(?:finicity)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "finicity", ] [[rules]] description = "Finicity Public Key" -#id = "flutterwave-public-key" +id = "flutterwave-public-key" regex = '''FLWPUBK_TEST-(?i)[a-h0-9]{32}-X''' tags = [ "flwpubk_test", @@ -305,7 +304,7 @@ tags = [ [[rules]] description = "Finicity Secret Key" -#id = "flutterwave-public-key" +id = "flutterwave-public-key" regex = '''FLWSECK_TEST-(?i)[a-h0-9]{32}-X''' tags = [ "flwseck_test", @@ -313,7 +312,7 @@ tags = [ [[rules]] description = "Finicity Secret Key" -#id = "flutterwave-public-key" +id = "flutterwave-public-key" regex = '''FLWSECK_TEST-(?i)[a-h0-9]{32}-X''' tags = [ "flwseck_test", @@ -321,7 +320,7 @@ tags = [ [[rules]] description = "Frame.io API token" -#id = "frameio-api-token" +id = "frameio-api-token" regex = '''fio-u-(?i)[a-z0-9\-_=]{64}''' tags = [ "fio-u-", @@ -329,9 +328,9 @@ tags = [ [[rules]] description = "GoCardless API token" -#id = "gocardless-api-token" +id = "gocardless-api-token" regex = '''(?i)(?:gocardless)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(live_(?i)[a-z0-9\-_=]{40})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "live_", "gocardless", @@ -339,7 +338,7 @@ tags = [ [[rules]] description = "GitHub Personal Access Token" -#id = "github-pat" +id = "github-pat" regex = '''ghp_[0-9a-zA-Z]{36}''' tags = [ "ghp_", @@ -347,7 +346,7 @@ tags = [ [[rules]] description = "GitHub OAuth Access Token" -#id = "github-oauth" +id = "github-oauth" regex = '''gho_[0-9a-zA-Z]{36}''' tags = [ "gho_", @@ -355,7 +354,7 @@ tags = [ [[rules]] description = "GitHub App Token" -#id = "github-app-token" +id = "github-app-token" regex = '''(ghu|ghs)_[0-9a-zA-Z]{36}''' tags = [ "ghu_", @@ -364,7 +363,7 @@ tags = [ [[rules]] description = "GitHub Refresh Token" -#id = "github-refresh-token" +id = "github-refresh-token" regex = '''ghr_[0-9a-zA-Z]{36}''' tags = [ "ghr_", @@ -372,7 +371,7 @@ tags = [ [[rules]] description = "Gitlab Personal Access Token" -#id = "gitlab-pat" +id = "gitlab-pat" regex = '''glpat-[0-9a-zA-Z\-\_]{20}''' tags = [ "glpat-", @@ -380,7 +379,7 @@ tags = [ [[rules]] description = "HashiCorp Terraform user/org API token" -#id = "hashicorp-tf-api-token" +id = "hashicorp-tf-api-token" regex = '''(?i)[a-z0-9]{14}\.atlasv1\.[a-z0-9\-_=]{60,70}''' tags = [ "atlasv1", @@ -388,34 +387,34 @@ tags = [ [[rules]] description = "Heroku API Key" -#id = "heroku-api-key" +id = "heroku-api-key" regex = '''(?i)(?:heroku)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "heroku", ] [[rules]] description = "HubSpot API Token" -#id = "hubspot-api-key" +id = "hubspot-api-key" regex = '''(?i)(?:hubspot)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "hubspot", ] [[rules]] description = "Intercom API Token" -#id = "intercom-api-key" +id = "intercom-api-key" regex = '''(?i)(?:intercom)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{60})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "intercom", ] [[rules]] description = "Linear API Token" -#id = "linear-api-key" +id = "linear-api-key" regex = '''lin_api_(?i)[a-z0-9]{40}''' tags = [ "lin_api_", @@ -423,18 +422,18 @@ tags = [ [[rules]] description = "Linear Client Secret" -#id = "linear-client-secret" +id = "linear-client-secret" regex = '''(?i)(?:linear)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "linear", ] [[rules]] description = "LinkedIn Client ID" -#id = "linkedin-client-id" +id = "linkedin-client-id" regex = '''(?i)(?:linkedin|linked-in)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{14})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "linkedin", "linked-in", @@ -442,9 +441,9 @@ tags = [ [[rules]] description = "LinkedIn Client secret" -#id = "linkedin-client-secret" +id = "linkedin-client-secret" regex = '''(?i)(?:linkedin|linked-in)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{16})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "linkedin", "linked-in", @@ -452,9 +451,9 @@ tags = [ [[rules]] description = "Lob API Key" -#id = "lob-api-key" +id = "lob-api-key" regex = '''(?i)(?:lob)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}((live|test)_[a-f0-9]{35})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "test_", "live_", @@ -462,9 +461,9 @@ tags = [ [[rules]] description = "Lob Publishable API Key" -#id = "lob-pub-api-key" +id = "lob-pub-api-key" regex = '''(?i)(?:lob)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}((test|live)_pub_[a-f0-9]{31})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "test_pub", "live_pub", @@ -473,54 +472,54 @@ tags = [ [[rules]] description = "Mailchimp API key" -#id = "mailchimp-api-key" +id = "mailchimp-api-key" regex = '''(?i)(?:mailchimp)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32}-us20)(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "mailchimp", ] [[rules]] description = "Mailgun public validation key" -#id = "mailgun-pub-key" +id = "mailgun-pub-key" regex = '''(?i)(?:mailgun)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(pubkey-[a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "mailgun", ] [[rules]] description = "Mailgun private API token" -#id = "mailgun-private-api-token" +id = "mailgun-private-api-token" regex = '''(?i)(?:mailgun)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(key-[a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "mailgun", ] [[rules]] description = "Mailgun webhook signing key" -#id = "mailgun-signing-key" +id = "mailgun-signing-key" regex = '''(?i)(?:mailgun)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-h0-9]{32}-[a-h0-9]{8}-[a-h0-9]{8})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "mailgun", ] [[rules]] description = "MapBox API token" -#id = "mapbox-api-token" +id = "mapbox-api-token" regex = '''(?i)(?:mapbox)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(pk\.[a-z0-9]{60}\.[a-z0-9]{22})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "mapbox", ] [[rules]] description = "MessageBird API token" -#id = "messagebird-api-token" +id = "messagebird-api-token" regex = '''(?i)(?:messagebird|message-bird|message_bird)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{25})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "messagebird", "message-bird", @@ -529,9 +528,9 @@ tags = [ [[rules]] description = "MessageBird client ID" -#id = "messagebird-client-id" +id = "messagebird-client-id" regex = '''(?i)(?:messagebird|message-bird|message_bird)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-h0-9]{8}-[a-h0-9]{4}-[a-h0-9]{4}-[a-h0-9]{4}-[a-h0-9]{12})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "messagebird", "message-bird", @@ -540,18 +539,18 @@ tags = [ [[rules]] description = "New Relic user API Key" -#id = "new-relic-user-api-key" +id = "new-relic-user-api-key" regex = '''(?i)(?:new-relic|newrelic|new_relic)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(NRAK-[a-z0-9]{27})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "nrak", ] [[rules]] description = "New Relic user API ID" -#id = "new-relic-user-api-id" +id = "new-relic-user-api-id" regex = '''(?i)(?:new-relic|newrelic|new_relic)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{64})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "new-relic", "newrelic", @@ -560,52 +559,52 @@ tags = [ [[rules]] description = "New Relic ingest browser API token" -#id = "new-relic-browser-api-token" +id = "new-relic-browser-api-token" regex = '''(?i)(?:new-relic|newrelic|new_relic)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(NRJS-[a-f0-9]{19})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "nrjs-", ] [[rules]] description = "npm access token" -#id = "npm-access-token" +id = "npm-access-token" regex = '''(?i)\b(npm_[a-z0-9]{36})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "npm_", ] [[rules]] description = "PlanetScale password" -#id = "planetscale-password" +id = "planetscale-password" regex = '''(?i)\b(pscale_pw_(?i)[a-z0-9=\-_\.]{43})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "pscale_pw_", ] [[rules]] description = "PlanetScale API token" -#id = "planetscale-api-token" +id = "planetscale-api-token" regex = '''(?i)\b(pscale_tkn_(?i)[a-z0-9=\-_\.]{43})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "pscale_tkn_", ] [[rules]] description = "Postman API token" -#id = "postman-api-token" +id = "postman-api-token" regex = '''(?i)\b(PMAK-(?i)[a-f0-9]{24}\-[a-f0-9]{34})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "pmak-", ] [[rules]] description = "Private Key" -#id = "private-key" +id = "private-key" regex = '''(?i)-----BEGIN[ A-Z0-9_-]{0,100}PRIVATE KEY-----[\s\S-]*KEY----''' tags = [ "-----begin", @@ -613,16 +612,16 @@ tags = [ [[rules]] description = "Pulumi API token" -#id = "pulumi-api-token" +id = "pulumi-api-token" regex = '''(?i)\b(pul-[a-f0-9]{40})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "pul-", ] [[rules]] description = "PyPI upload token" -#id = "pypi-upload-token" +id = "pypi-upload-token" regex = '''pypi-AgEIcHlwaS5vcmc[A-Za-z0-9\-_]{50,1000}''' tags = [ "pypi-ageichlwas5vcmc", @@ -630,43 +629,43 @@ tags = [ [[rules]] description = "Rubygem API token" -#id = "rubygems-api-token" +id = "rubygems-api-token" regex = '''(?i)\b(rubygems_[a-f0-9]{48})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "rubygems_", ] [[rules]] description = "SendGrid API token" -#id = "sendgrid-api-token" +id = "sendgrid-api-token" regex = '''(?i)\b(SG\.(?i)[a-z0-9=_\-\.]{66})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "sg.", ] [[rules]] description = "Sendinblue API token" -#id = "sendinblue-api-token" +id = "sendinblue-api-token" regex = '''(?i)\b(xkeysib-[a-f0-9]{64}\-(?i)[a-z0-9]{16})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "xkeysib-", ] [[rules]] description = "Shippo API token" -#id = "shippo-api-token" +id = "shippo-api-token" regex = '''(?i)\b(shippo_(live|test)_[a-f0-9]{40})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "shippo_", ] [[rules]] description = "Shopify access token" -#id = "shopify-access-token" +id = "shopify-access-token" regex = '''shpat_[a-fA-F0-9]{32}''' tags = [ "shpat_", @@ -674,7 +673,7 @@ tags = [ [[rules]] description = "Shopify custom access token" -#id = "shopify-custom-access-token" +id = "shopify-custom-access-token" regex = '''shpca_[a-fA-F0-9]{32}''' tags = [ "shpca_", @@ -682,7 +681,7 @@ tags = [ [[rules]] description = "Shopify private app access token" -#id = "shopify-private-app-access-token" +id = "shopify-private-app-access-token" regex = '''shppa_[a-fA-F0-9]{32}''' tags = [ "shppa_", @@ -690,7 +689,7 @@ tags = [ [[rules]] description = "Shopify shared secret" -#id = "shopify-shared-secret" +id = "shopify-shared-secret" regex = '''shpss_[a-fA-F0-9]{32}''' tags = [ "shpss_", @@ -698,7 +697,7 @@ tags = [ [[rules]] description = "Slack token" -#id = "slack-access-token" +id = "slack-access-token" regex = '''xox[baprs]-([0-9a-zA-Z]{10,48})''' tags = [ "xoxb", @@ -710,7 +709,7 @@ tags = [ [[rules]] description = "Slack Webhook" -#id = "slack-web-hook" +id = "slack-web-hook" regex = '''https:\/\/hooks.slack.com\/services\/[A-Za-z0-9+\/]{44,46}''' tags = [ "hooks.slack.com", @@ -718,7 +717,7 @@ tags = [ [[rules]] description = "Stripe" -#id = "stripe-access-token" +id = "stripe-access-token" regex = '''(?i)(sk|pk)_(test|live)_[0-9a-z]{10,32}''' tags = [ "sk_test", @@ -729,7 +728,7 @@ tags = [ [[rules]] description = "Twilio API Key" -#id = "twilio-api-key" +id = "twilio-api-key" regex = '''SK[0-9a-fA-F]{32}''' tags = [ "twilio", @@ -737,39 +736,41 @@ tags = [ [[rules]] description = "Twitch API token" -#id = "twitch-api-token" +id = "twitch-api-token" regex = '''(?i)(?:twitch)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{30})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "twitch", ] [[rules]] description = "twitter" -#id = "twitter" +id = "twitter" regex = '''(?i)(?:twitter)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{35,44})(?:['|\"|\n|\r|\s|\x60]|$)''' -#secretGroup = 1 +secretGroup = 1 tags = [ "twitter", ] [[rules]] description = "Typeform API token" -#id = "typeform-api-token" +id = "typeform-api-token" regex = '''(?i)tfp_[a-zA-Z1-9]{40,50}_[a-zA-Z1-9]{8,16}''' -#secretGroup = 1 tags = [ "typeform", ] [[rules]] description = "Authorization Bearer tokens" +id = "authorization-bearer-token" regex = '''(?i)Bearer(?:\s)+(\S{8,})''' -tags = ["key", "HTTP", "bearer"] -[[rules.Entropies]] -Group = "1" -Max = "7" -Min = "3.8" +secretGroup = 1 +entropy = 3.8 +tags = [ + "key", + "HTTP", + "bearer" +] # The following rules look for credentials assigned to variables that its value has an entropy of more than 3 bits. # To achieve this there's a regexp for each language. The regexp checks for a variable with a suspicious name followed @@ -778,79 +779,115 @@ Min = "3.8" [[rules]] description = "Hardcoded credentials in Go files" -file = '''^(.*?)\.go$''' -regex = '''(?i)(?:secret|key|signature|password|pwd|pass|token)(?:\w|\s*?)(?:=|:=)(?:\s*?)[\"'`](.{4,120}?)[\"'`]''' -tags = ["credentials", "hardcoded", "go"] -[[rules.Entropies]] -Group = "1" -Max = "7" -Min = "3" +id = "credentials-go" +path = '''(.*?)\.go$''' +regex = '''(?i)(?:secret|key|password|pwd|pass|token)(?:\w|\s*?)(?:=|:=)(?:\s*?)[\"'\x60](.{4,120}?)[\"'\x60]''' +secretGroup = 1 +entropy = 3 +tags = [ + "credentials", + "hardcoded", + "go", +] [[rules]] description = "Hardcoded credentials in JavaScript or TypeScript files" -file = '''^(.*?)\.(?:j|t)s$''' -regex = '''(?i)(?:secret|key|signature|password|pwd|pass|token)(?:\w|\s*?)(?:=){1}(?:\s{0,10})[\"'`](.*?)[\"'`]''' -tags = ["credentials", "hardcoded", "js"] -[[rules.Entropies]] -Group = "1" -Max = "7" -Min = "3" +id = "credentials-javascript" +path = '''(.*?)\.(?:j|t)s$''' +regex = '''(?i)(?:secret|key|password|pwd|pass|token)(?:\w|\s*?)(?:=){1}(?:\s{0,10})[\"'`](.*?)[\"'`]''' +secretGroup = 1 +entropy = 3 +tags = [ + "credentials", + "hardcoded", + "js", +] [[rules]] description = "Hardcoded credentials in PHP files" -file = '''^(.*?)\.php$''' -regex = '''(?i)(?:secret|key|signature|password|pwd|pass|token)(?:.{0,20})(?:=){1}(?:.{0,10})[\"'`](.{4,120})[\"'`]''' -tags = ["credentials", "hardcoded", "php"] -[[rules.Entropies]] -Group = "1" -Max = "7" -Min = "3" +id = "credentials-php" +path = '''(.*?)\.php$''' +regex = '''(?i)(?:secret|key|password|pwd|pass|token)(?:.{0,20})(?:=){1}(?:.{0,10})[\"'`](.{4,120})[\"'`]''' +secretGroup = 1 +entropy = 3 +tags = [ + "credentials", + "hardcoded", + "php", +] [[rules]] description = "Hardcoded credentials in YAML files as quoted strings" -file = '''^(.*?)\.y(a|)ml$''' -regex = '''(?i)(?:secret|key|signature|password|pwd|pass|token)(?:.{0,20})(?::){1}(?:\s{0,10})(?:[\"'](.{4,120})[\"'])''' -tags = ["credentials", "hardcoded", "yaml"] -[[rules.Entropies]] -Group = "1" -Max = "7" -Min = "3" +id = "credentials-yaml-quoted" +path = '''(.*?)\.y(a|)ml$''' +regex = '''(?i)(?:secret|key|password|pwd|pass|token)(?:.{0,20})(?::){1}(?:\s{0,10})(?:[\"'](.{4,120})[\"'])''' +secretGroup = 1 +entropy = 3 +tags = [ + "credentials", + "hardcoded", + "yaml", +] [rules.allowlist] -description = "Skip YAML Serverless variables, grabbed and concated values, encrypted secrets, and values with jinja2 placeholders" -regexes = ['''\${(?:.)+}''', '''(?i)\(\((?:\s)*?(?:grab|concat)(?:.)*?(?:\s)*?\)\)''', '''(?i)!!enveloped:(?:\S)+''', '''(?:.)*?{{(?:.)*?}}'''] +description = "Skip YAML Serverless variables, grabbed and concatenated values, encrypted secrets, and values with jinja2 placeholders" +regexes = [ + '''\${(?:.)+}''', # Serverless variables + '''(?i)\(\((?:\s)*?(?:grab|concat)(?:.)*?(?:\s)*?\)\)''', # Grabbed and concatenated values + '''(?i)!!enveloped:''', # Encrypted secretes + '''(?:.)*?{{(?:.)*?}}''', # jinja2 placeholders +] [[rules]] description = "Hardcoded credentials in YAML files as unquoted strings" -file = '''^(.*?)\.y(a|)ml$''' -regex = '''(?i)(?:secret|key|signature|password|pwd|pass|token)(?:.{0,20})(?::){1}(?:\s{0,10})(\S{4,120})''' -tags = ["credentials", "hardcoded", "yaml"] -[[rules.Entropies]] -Group = "1" -Max = "7" -Min = "3.5" # A higher entropy is required for this type of match, as unquoted can trigger many false positives +id = "credentials-yaml-unquoted" +path = '''(.*?)\.y(a|)ml$''' +#regex = '''(?i)(?:secret|key|password|pwd|pass|token)(?:\w|\s*?)(?::){1}(?:\s*?)((?:\w|\S)+)(?:|(?:\s*?#.*))$''' +regex = '''(?i)(?:secret|key|password|pwd|pass|token)(?:\w|\s*?)(?::){1}(?:\s*?)((?:\w|\S)+)''' +secretGroup = 1 +entropy = 3.5 # A higher entropy is required for this type of match, as unquoted can trigger many false positives +tags = [ + "credentials", + "hardcoded", + "yaml", +] [rules.allowlist] description = "Skip YAML Serverless variables, grabbed and concated values, encrypted secrets, and values with jinja2 placeholders" -regexes = ['''\${(?:.)+}''', '''(?i)\(\((?:\s)*?(?:grab|concat)(?:.)*?(?:\s)*?\)\)''', '''(?i)!!enveloped:(?:\S)+''', '''(?:.)*?{{(?:.)*?}}'''] +regexes = [ + ''':$''', # It's a YAML key (as in key: value) + '''\${(?:.)+}''', # Serverless variables + '''(?i)\(\((?:\s)*?(?:grab|concat)(?:.)*?(?:\s)*?\)\)''', # Grabbed and concatenated values + '''(?i)!!enveloped:''', # Encrypted secretes + '''(?:.)*?{{(?:.)*?}}''', # jinja2 placeholders + '''={{$''', # jinja2 variable assignation +] [[rules]] description = "Hardcoded credentials in YAML files as multiline strings" -file = '''^(.*?)\.y(a|)ml$''' -regex = '''(?i)(?:secret|key|signature|password|pwd|pass|token)(?:.{0,20})(?::){1}(?:\s{0,10})(?:\|(?:-|))\n(?:\s{0,10})(\S{4,120})''' -tags = ["credentials", "hardcoded", "yaml"] -[[rules.Entropies]] -Group = "1" -Max = "7" -Min = "4" +id = "credentials-yaml-multiline" +path = '''(.*?)\.y(a|)ml$''' +regex = '''(?i)(?:secret|key|password|pwd|pass|token)(?:.{0,20})(?::){1}(?:\s{0,10})(?:\|(?:-|))\n(?:\s{0,10})(\S{4,120})''' +secretGroup = 1 +entropy = 4 +tags = [ + "credentials", + "hardcoded", + "yaml", +] [[rules]] description = "Hardcoded credentials in HCL files (*.tf)" -file = '''^(.*?)\.tf$''' -regex = '''(?i)(?:secret|key|signature|password|pwd|pass|token)(?:.{0,20})(?:=){1}(?:\s)*?"(.{4,120})"''' -tags = ["credentials", "hardcoded", "hcl"] -[[rules.Entropies]] -Group = "1" -Max = "7" -Min = "3" +id = "credentials-terraform" +path = '''(.*?)\.tf$''' +regex = '''(?i)(?:secret|key|password|pwd|pass|token)(?:.{0,20})(?:=){1}(?:\s)*?"(.{4,120})"''' +secretGroup = 1 +entropy = 3 +tags = [ + "credentials", + "hardcoded", + "hcl", +] [rules.allowlist] description = "Skip variable substitution" -regexes = ['''\${(?:.)*?}'''] +regexes = [ + '''\${(?:.)*?}''', +] diff --git a/global_config_legacy.toml b/global_config_legacy.toml new file mode 100644 index 0000000..85de86a --- /dev/null +++ b/global_config_legacy.toml @@ -0,0 +1,893 @@ +title = "Global gitleaks config" + +[allowlist] +description = "Global allowlisted paths, files, and stopwords" +# TODO: figure out what to do with the old `.gitleaks.toml` files in repos: migrate them? convert them when mergin them? +paths = [ + '''\.gitleaks\.toml$''', # Ignoring the generated configuration file + '''(.*?)(jpg|gif|doc|pdf|bin)$''', # Ignoring common binaries + '''(.*?)_test\.go$''', # Ignoring Go test files + '''(.*?)\.(spec|test)\.(j|t)s$''', # Ignoring JavaScript and TypeScript test files + '''go\.(mod|sum)$''', # Ignoring Go manifests + '''vendor\.json''', + '''Gopkg\.(lock|toml)''', + '''package-lock\.json''', # Ignoring Node/JS manifests + '''package\.json''', + '''composer\.json''', + '''composer\.lock''', #Ignoring PHP manifests + '''yarn\.lock''', + '''Pipfile''', # Ignoring Python manifests + '''Pipfile\.lock''', + '''poetry\.lock''', + '''node_modules\/''', # Ignoring Node dependencies + '''vendor\/''', # Ignoring Go dependencies + '''test(|s)\/''', # Ignoring test directories +] +# TODO: change this to "stopwords" +regexes = ['''someFunnyWord'''] # Ignoring lines with test + +# The following rules, extracted from gitleak's default config, look for credentials with a well-known format, usually from third parties. +# These rules evaluate all file types. + +[[rules]] +description = "Adobe Client ID (Oauth Web)" +id = "adobe-client-id" +regex = '''(?i)(?:adobe)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "adobe", +] + +[[rules]] +description = "Adobe Client Secret" +id = "adobe-client-secret" +regex = '''(?i)\b((p8e-)(?i)[a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' +tags = [ + "p8e-", +] + +[[rules]] +description = "Age secret key" +id = "age secret key" +regex = '''AGE-SECRET-KEY-1[QPZRY9X8GF2TVDW0S3JN54KHCE6MUA7L]{58}''' +tags = [ + "age-secret-key-1", +] + +[[rules]] +description = "Alibaba AccessKey ID" +id = "alibaba-access-key-id" +regex = '''(?i)\b((LTAI)(?i)[a-z0-9]{20})(?:['|\"|\n|\r|\s|\x60]|$)''' +tags = [ + "ltai", +] + +[[rules]] +description = "Alibaba Secret Key" +id = "alibaba-secret-key" +regex = '''(?i)(?:alibaba)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{30})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "alibaba", +] + +[[rules]] +description = "Asana Client ID" +id = "asana-client-id" +regex = '''(?i)(?:asana)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([0-9]{16})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "asana", +] + +[[rules]] +description = "Asana Client Secret" +id = "asana-client-secret" +regex = '''(?i)(?:asana)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "asana", +] + +[[rules]] +description = "Atlassian API token" +id = "atlassian-api-token" +regex = '''(?i)(?:atlassian|confluence)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{24})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "atlassian", + "confluence", +] + +[[rules]] +description = "AWS" +id = "aws-access-token" +regex = '''(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}''' +tags = [ + "akia", + "agpa", + "aida", + "aroa", + "aipa", + "anpa", + "anva", + "asia", +] + +[[rules]] +description = "BitBucket Client ID" +id = "bitbucket-client-id" +regex = '''(?i)(?:bitbucket)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "bitbucket", +] + +[[rules]] +description = "BitBucket Client Secret" +id = "bitbucket-client-secret" +regex = '''(?i)(?:bitbucket)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{64})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "bitbucket", +] + +[[rules]] +description = "Beamer API token" +id = "beamer-api-token" +regex = '''(?i)(?:beamer)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(b_[a-z0-9=_\-]{44})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "beamer", +] + +[[rules]] +description = "Clojars API token" +id = "clojars-api-token" +regex = '''(?i)(CLOJARS_)[a-z0-9]{60}''' +tags = [ + "clojars", +] + +[[rules]] +description = "Contentful delivery API token" +id = "contentful-delivery-api-token" +regex = '''(?i)(?:contentful)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{43})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "contentful", +] + +[[rules]] +description = "Databricks API token" +id = "databricks-api-token" +regex = '''(?i)\b(dapi[a-h0-9]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' +tags = [ + "dapi", +] + +[[rules]] +description = "Discord API key" +id = "discord-api-token" +regex = '''(?i)(?:discord)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{64})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "discord", +] + +[[rules]] +description = "Discord client ID" +id = "discord-client-id" +regex = '''(?i)(?:discord)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([0-9]{18})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "discord", +] + +[[rules]] +description = "Discord client secret" +id = "discord-client-secret" +regex = '''(?i)(?:discord)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "discord", +] + +[[rules]] +description = "Dropbox API secret" +id = "doppler-api-token" +regex = '''(?i)(?:dropbox)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{15})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "dropbox", +] + +[[rules]] +description = "Dropbox long lived API token" +id = "dropbox-long-lived-api-token" +regex = '''(?i)(?:dropbox)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{11}(AAAAAAAAAA)[a-z0-9\-_=]{43})(?:['|\"|\n|\r|\s|\x60]|$)''' +tags = [ + "dropbox", +] + +[[rules]] +description = "Dropbox short lived API token" +id = "dropbox-short-lived-api-token" +regex = '''(?i)(?:dropbox)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(sl\.[a-z0-9\-=_]{135})(?:['|\"|\n|\r|\s|\x60]|$)''' +tags = [ + "dropbox", +] + +[[rules]] +description = "Doppler API token" +id = "doppler-api-token" +regex = '''(dp\.pt\.)(?i)[a-z0-9]{43}''' +tags = [ + "doppler", +] + +[[rules]] +description = "Duffel API token" +id = "duffel-api-token" +regex = '''duffel_(test|live)_(?i)[a-z0-9_\-=]{43}''' +tags = [ + "duffel", +] + +[[rules]] +description = "Dynatrace API token" +id = "dynatrace-api-token" +regex = '''dt0c01\.(?i)[a-z0-9]{24}\.[a-z0-9]{64}''' +tags = [ + "dynatrace", +] + +[[rules]] +description = "EasyPost API token" +id = "easypost-api-token" +regex = '''EZAK(?i)[a-z0-9]{54}''' +tags = [ + "ezak", +] + +[[rules]] +description = "EasyPost test API token" +id = "easypost-test-api-token" +regex = '''EZTK(?i)[a-z0-9]{54}''' +tags = [ + "eztk", +] + +[[rules]] +description = "facebook" +id = "facebook" +regex = '''(?i)(?:facebook)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "facebook", +] + +[[rules]] +description = "Fastly API key" +id = "fastly-api-token" +regex = '''(?i)(?:fastly)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "fastly", +] + +[[rules]] +description = "Finicity Client Secret" +id = "finicity-client-secret" +regex = '''(?i)(?:finicity)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{20})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "finicity", +] + +[[rules]] +description = "Finicity API token" +id = "finicity-api-token" +regex = '''(?i)(?:finicity)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "finicity", +] + +[[rules]] +description = "Finicity Public Key" +id = "flutterwave-public-key" +regex = '''FLWPUBK_TEST-(?i)[a-h0-9]{32}-X''' +tags = [ + "flwpubk_test", +] + +[[rules]] +description = "Finicity Secret Key" +id = "flutterwave-public-key" +regex = '''FLWSECK_TEST-(?i)[a-h0-9]{32}-X''' +tags = [ + "flwseck_test", +] + +[[rules]] +description = "Finicity Secret Key" +id = "flutterwave-public-key" +regex = '''FLWSECK_TEST-(?i)[a-h0-9]{32}-X''' +tags = [ + "flwseck_test", +] + +[[rules]] +description = "Frame.io API token" +id = "frameio-api-token" +regex = '''fio-u-(?i)[a-z0-9\-_=]{64}''' +tags = [ + "fio-u-", +] + +[[rules]] +description = "GoCardless API token" +id = "gocardless-api-token" +regex = '''(?i)(?:gocardless)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(live_(?i)[a-z0-9\-_=]{40})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "live_", + "gocardless", +] + +[[rules]] +description = "GitHub Personal Access Token" +id = "github-pat" +regex = '''ghp_[0-9a-zA-Z]{36}''' +tags = [ + "ghp_", +] + +[[rules]] +description = "GitHub OAuth Access Token" +id = "github-oauth" +regex = '''gho_[0-9a-zA-Z]{36}''' +tags = [ + "gho_", +] + +[[rules]] +description = "GitHub App Token" +id = "github-app-token" +regex = '''(ghu|ghs)_[0-9a-zA-Z]{36}''' +tags = [ + "ghu_", + "ghs_", +] + +[[rules]] +description = "GitHub Refresh Token" +id = "github-refresh-token" +regex = '''ghr_[0-9a-zA-Z]{36}''' +tags = [ + "ghr_", +] + +[[rules]] +description = "Gitlab Personal Access Token" +id = "gitlab-pat" +regex = '''glpat-[0-9a-zA-Z\-\_]{20}''' +tags = [ + "glpat-", +] + +[[rules]] +description = "HashiCorp Terraform user/org API token" +id = "hashicorp-tf-api-token" +regex = '''(?i)[a-z0-9]{14}\.atlasv1\.[a-z0-9\-_=]{60,70}''' +tags = [ + "atlasv1", +] + +[[rules]] +description = "Heroku API Key" +id = "heroku-api-key" +regex = '''(?i)(?:heroku)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "heroku", +] + +[[rules]] +description = "HubSpot API Token" +id = "hubspot-api-key" +regex = '''(?i)(?:hubspot)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "hubspot", +] + +[[rules]] +description = "Intercom API Token" +id = "intercom-api-key" +regex = '''(?i)(?:intercom)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{60})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "intercom", +] + +[[rules]] +description = "Linear API Token" +id = "linear-api-key" +regex = '''lin_api_(?i)[a-z0-9]{40}''' +tags = [ + "lin_api_", +] + +[[rules]] +description = "Linear Client Secret" +id = "linear-client-secret" +regex = '''(?i)(?:linear)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "linear", +] + +[[rules]] +description = "LinkedIn Client ID" +id = "linkedin-client-id" +regex = '''(?i)(?:linkedin|linked-in)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{14})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "linkedin", + "linked-in", +] + +[[rules]] +description = "LinkedIn Client secret" +id = "linkedin-client-secret" +regex = '''(?i)(?:linkedin|linked-in)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{16})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "linkedin", + "linked-in", +] + +[[rules]] +description = "Lob API Key" +id = "lob-api-key" +regex = '''(?i)(?:lob)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}((live|test)_[a-f0-9]{35})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "test_", + "live_", +] + +[[rules]] +description = "Lob Publishable API Key" +id = "lob-pub-api-key" +regex = '''(?i)(?:lob)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}((test|live)_pub_[a-f0-9]{31})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "test_pub", + "live_pub", + "_pub", +] + +[[rules]] +description = "Mailchimp API key" +id = "mailchimp-api-key" +regex = '''(?i)(?:mailchimp)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32}-us20)(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "mailchimp", +] + +[[rules]] +description = "Mailgun public validation key" +id = "mailgun-pub-key" +regex = '''(?i)(?:mailgun)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(pubkey-[a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "mailgun", +] + +[[rules]] +description = "Mailgun private API token" +id = "mailgun-private-api-token" +regex = '''(?i)(?:mailgun)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(key-[a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "mailgun", +] + +[[rules]] +description = "Mailgun webhook signing key" +id = "mailgun-signing-key" +regex = '''(?i)(?:mailgun)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-h0-9]{32}-[a-h0-9]{8}-[a-h0-9]{8})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "mailgun", +] + +[[rules]] +description = "MapBox API token" +id = "mapbox-api-token" +regex = '''(?i)(?:mapbox)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(pk\.[a-z0-9]{60}\.[a-z0-9]{22})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "mapbox", +] + +[[rules]] +description = "MessageBird API token" +id = "messagebird-api-token" +regex = '''(?i)(?:messagebird|message-bird|message_bird)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{25})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "messagebird", + "message-bird", + "message_bird", +] + +[[rules]] +description = "MessageBird client ID" +id = "messagebird-client-id" +regex = '''(?i)(?:messagebird|message-bird|message_bird)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-h0-9]{8}-[a-h0-9]{4}-[a-h0-9]{4}-[a-h0-9]{4}-[a-h0-9]{12})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "messagebird", + "message-bird", + "message_bird", +] + +[[rules]] +description = "New Relic user API Key" +id = "new-relic-user-api-key" +regex = '''(?i)(?:new-relic|newrelic|new_relic)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(NRAK-[a-z0-9]{27})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "nrak", +] + +[[rules]] +description = "New Relic user API ID" +id = "new-relic-user-api-id" +regex = '''(?i)(?:new-relic|newrelic|new_relic)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{64})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "new-relic", + "newrelic", + "new_relic", +] + +[[rules]] +description = "New Relic ingest browser API token" +id = "new-relic-browser-api-token" +regex = '''(?i)(?:new-relic|newrelic|new_relic)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(NRJS-[a-f0-9]{19})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "nrjs-", +] + +[[rules]] +description = "npm access token" +id = "npm-access-token" +regex = '''(?i)\b(npm_[a-z0-9]{36})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "npm_", +] + +[[rules]] +description = "PlanetScale password" +id = "planetscale-password" +regex = '''(?i)\b(pscale_pw_(?i)[a-z0-9=\-_\.]{43})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "pscale_pw_", +] + +[[rules]] +description = "PlanetScale API token" +id = "planetscale-api-token" +regex = '''(?i)\b(pscale_tkn_(?i)[a-z0-9=\-_\.]{43})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "pscale_tkn_", +] + +[[rules]] +description = "Postman API token" +id = "postman-api-token" +regex = '''(?i)\b(PMAK-(?i)[a-f0-9]{24}\-[a-f0-9]{34})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "pmak-", +] + +[[rules]] +description = "Private Key" +id = "private-key" +regex = '''(?i)-----BEGIN[ A-Z0-9_-]{0,100}PRIVATE KEY-----[\s\S-]*KEY----''' +tags = [ + "-----begin", +] + +[[rules]] +description = "Pulumi API token" +id = "pulumi-api-token" +regex = '''(?i)\b(pul-[a-f0-9]{40})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "pul-", +] + +[[rules]] +description = "PyPI upload token" +id = "pypi-upload-token" +regex = '''pypi-AgEIcHlwaS5vcmc[A-Za-z0-9\-_]{50,1000}''' +tags = [ + "pypi-ageichlwas5vcmc", +] + +[[rules]] +description = "Rubygem API token" +id = "rubygems-api-token" +regex = '''(?i)\b(rubygems_[a-f0-9]{48})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "rubygems_", +] + +[[rules]] +description = "SendGrid API token" +id = "sendgrid-api-token" +regex = '''(?i)\b(SG\.(?i)[a-z0-9=_\-\.]{66})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "sg.", +] + +[[rules]] +description = "Sendinblue API token" +id = "sendinblue-api-token" +regex = '''(?i)\b(xkeysib-[a-f0-9]{64}\-(?i)[a-z0-9]{16})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "xkeysib-", +] + +[[rules]] +description = "Shippo API token" +id = "shippo-api-token" +regex = '''(?i)\b(shippo_(live|test)_[a-f0-9]{40})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "shippo_", +] + +[[rules]] +description = "Shopify access token" +id = "shopify-access-token" +regex = '''shpat_[a-fA-F0-9]{32}''' +tags = [ + "shpat_", +] + +[[rules]] +description = "Shopify custom access token" +id = "shopify-custom-access-token" +regex = '''shpca_[a-fA-F0-9]{32}''' +tags = [ + "shpca_", +] + +[[rules]] +description = "Shopify private app access token" +id = "shopify-private-app-access-token" +regex = '''shppa_[a-fA-F0-9]{32}''' +tags = [ + "shppa_", +] + +[[rules]] +description = "Shopify shared secret" +id = "shopify-shared-secret" +regex = '''shpss_[a-fA-F0-9]{32}''' +tags = [ + "shpss_", +] + +[[rules]] +description = "Slack token" +id = "slack-access-token" +regex = '''xox[baprs]-([0-9a-zA-Z]{10,48})''' +tags = [ + "xoxb", + "xoxa", + "xoxp", + "xoxr", + "xoxs", +] + +[[rules]] +description = "Slack Webhook" +id = "slack-web-hook" +regex = '''https:\/\/hooks.slack.com\/services\/[A-Za-z0-9+\/]{44,46}''' +tags = [ + "hooks.slack.com", +] + +[[rules]] +description = "Stripe" +id = "stripe-access-token" +regex = '''(?i)(sk|pk)_(test|live)_[0-9a-z]{10,32}''' +tags = [ + "sk_test", + "pk_test", + "sk_live", + "pk_live", +] + +[[rules]] +description = "Twilio API Key" +id = "twilio-api-key" +regex = '''SK[0-9a-fA-F]{32}''' +tags = [ + "twilio", +] + +[[rules]] +description = "Twitch API token" +id = "twitch-api-token" +regex = '''(?i)(?:twitch)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{30})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "twitch", +] + +[[rules]] +description = "twitter" +id = "twitter" +regex = '''(?i)(?:twitter)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{35,44})(?:['|\"|\n|\r|\s|\x60]|$)''' +secretGroup = 1 +tags = [ + "twitter", +] + +[[rules]] +description = "Typeform API token" +id = "typeform-api-token" +regex = '''(?i)tfp_[a-zA-Z1-9]{40,50}_[a-zA-Z1-9]{8,16}''' +tags = [ + "typeform", +] + +[[rules]] +description = "Authorization Bearer tokens" +id = "authorization-bearer-token" +regex = '''(?i)Bearer(?:\s)+(\S{8,})''' +secretGroup = 1 +entropy = 3.8 +tags = [ + "key", + "HTTP", + "bearer" +] + +# The following rules look for credentials assigned to variables that its value has an entropy of more than 3 bits. +# To achieve this there's a regexp for each language. The regexp checks for a variable with a suspicious name followed +# by a value assignation (for example, := in Go, = in JS, etc.). Then, looks for a group of non-space characters enclosed +# between quotes. If that group has an entropy higher than 3 bits the rule will trigger. + +[[rules]] +description = "Hardcoded credentials in Go files" +id = "credentials-go" +path = '''(.*?)\.go$''' +regex = '''(?i)(?:secret|key|password|pwd|pass|token)(?:\w|\s*?)(?:=|:=)(?:\s*?)[\"'\x60](.{4,120}?)[\"'\x60]''' +secretGroup = 1 +entropy = 3 +tags = [ + "credentials", + "hardcoded", + "go", +] + +[[rules]] +description = "Hardcoded credentials in JavaScript or TypeScript files" +id = "credentials-javascript" +path = '''(.*?)\.(?:j|t)s$''' +regex = '''(?i)(?:secret|key|password|pwd|pass|token)(?:\w|\s*?)(?:=){1}(?:\s{0,10})[\"'`](.*?)[\"'`]''' +secretGroup = 1 +entropy = 3 +tags = [ + "credentials", + "hardcoded", + "js", +] + +[[rules]] +description = "Hardcoded credentials in PHP files" +id = "credentials-php" +path = '''(.*?)\.php$''' +regex = '''(?i)(?:secret|key|password|pwd|pass|token)(?:.{0,20})(?:=){1}(?:.{0,10})[\"'`](.{4,120})[\"'`]''' +secretGroup = 1 +entropy = 3 +tags = [ + "credentials", + "hardcoded", + "php", +] + +[[rules]] +description = "Hardcoded credentials in YAML files as quoted strings" +id = "credentials-yaml-quoted" +path = '''(.*?)\.y(a|)ml$''' +regex = '''(?i)(?:secret|key|password|pwd|pass|token)(?:.{0,20})(?::){1}(?:\s{0,10})(?:[\"'](.{4,120})[\"'])''' +secretGroup = 1 +entropy = 3 +tags = [ + "credentials", + "hardcoded", + "yaml", +] +[rules.allowlist] +description = "Skip YAML Serverless variables, grabbed and concatenated values, encrypted secrets, and values with jinja2 placeholders" +regexes = [ + '''\${(?:.)+}''', # Serverless variables + '''(?i)\(\((?:\s)*?(?:grab|concat)(?:.)*?(?:\s)*?\)\)''', # Grabbed and concatenated values + '''(?i)!!enveloped:''', # Encrypted secretes + '''(?:.)*?{{(?:.)*?}}''', # jinja2 placeholders +] + +[[rules]] +description = "Hardcoded credentials in YAML files as unquoted strings" +id = "credentials-yaml-unquoted" +path = '''(.*?)\.y(a|)ml$''' +#regex = '''(?i)(?:secret|key|password|pwd|pass|token)(?:\w|\s*?)(?::){1}(?:\s*?)((?:\w|\S)+)(?:|(?:\s*?#.*))$''' +regex = '''(?i)(?:secret|key|password|pwd|pass|token)(?:\w|\s*?)(?::){1}(?:\s*?)((?:\w|\S)+)''' +secretGroup = 1 +entropy = 3.5 # A higher entropy is required for this type of match, as unquoted can trigger many false positives +tags = [ + "credentials", + "hardcoded", + "yaml", +] +[rules.allowlist] +description = "Skip YAML Serverless variables, grabbed and concated values, encrypted secrets, and values with jinja2 placeholders" +regexes = [ + ''':$''', # It's a YAML key (as in key: value) + '''\${(?:.)+}''', # Serverless variables + '''(?i)\(\((?:\s)*?(?:grab|concat)(?:.)*?(?:\s)*?\)\)''', # Grabbed and concatenated values + '''(?i)!!enveloped:''', # Encrypted secretes + '''(?:.)*?{{(?:.)*?}}''', # jinja2 placeholders + '''={{$''', # jinja2 variable assignation +] + +[[rules]] +description = "Hardcoded credentials in YAML files as multiline strings" +id = "credentials-yaml-multiline" +path = '''(.*?)\.y(a|)ml$''' +regex = '''(?i)(?:secret|key|password|pwd|pass|token)(?:.{0,20})(?::){1}(?:\s{0,10})(?:\|(?:-|))\n(?:\s{0,10})(\S{4,120})''' +secretGroup = 1 +entropy = 4 +tags = [ + "credentials", + "hardcoded", + "yaml", +] + +[[rules]] +description = "Hardcoded credentials in HCL files (*.tf)" +id = "credentials-terraform" +path = '''(.*?)\.tf$''' +regex = '''(?i)(?:secret|key|password|pwd|pass|token)(?:.{0,20})(?:=){1}(?:\s)*?"(.{4,120})"''' +secretGroup = 1 +entropy = 3 +tags = [ + "credentials", + "hardcoded", + "hcl", +] +[rules.allowlist] +description = "Skip variable substitution" +regexes = [ + '''\${(?:.)*?}''', +] diff --git a/test/sample_files/no_secrets/aws-credentials-as-env-vars.go b/sample_files/no_secrets/aws-credentials-as-env-vars.go similarity index 100% rename from test/sample_files/no_secrets/aws-credentials-as-env-vars.go rename to sample_files/no_secrets/aws-credentials-as-env-vars.go diff --git a/test/sample_files/no_secrets/config-with-serverless-variables.yml b/sample_files/no_secrets/config-with-serverless-variables.yml similarity index 100% rename from test/sample_files/no_secrets/config-with-serverless-variables.yml rename to sample_files/no_secrets/config-with-serverless-variables.yml diff --git a/test/sample_files/no_secrets/hardcoded-passwords.spec.js b/sample_files/no_secrets/hardcoded-passwords.spec.js similarity index 100% rename from test/sample_files/no_secrets/hardcoded-passwords.spec.js rename to sample_files/no_secrets/hardcoded-passwords.spec.js diff --git a/test/sample_files/no_secrets/jinja2-variables.yaml b/sample_files/no_secrets/jinja2-variables.yaml similarity index 100% rename from test/sample_files/no_secrets/jinja2-variables.yaml rename to sample_files/no_secrets/jinja2-variables.yaml diff --git a/test/sample_files/no_secrets/k8s-manifest.yaml b/sample_files/no_secrets/k8s-manifest.yaml similarity index 100% rename from test/sample_files/no_secrets/k8s-manifest.yaml rename to sample_files/no_secrets/k8s-manifest.yaml diff --git a/test/sample_files/no_secrets/sender.go b/sample_files/no_secrets/sender.go similarity index 100% rename from test/sample_files/no_secrets/sender.go rename to sample_files/no_secrets/sender.go diff --git a/test/sample_files/no_secrets/terraform-config.tf b/sample_files/no_secrets/terraform-config.tf similarity index 100% rename from test/sample_files/no_secrets/terraform-config.tf rename to sample_files/no_secrets/terraform-config.tf diff --git a/test/sample_files/no_secrets/variable-assignment_test.go b/sample_files/no_secrets/variable-assignment_test.go similarity index 100% rename from test/sample_files/no_secrets/variable-assignment_test.go rename to sample_files/no_secrets/variable-assignment_test.go diff --git a/test/sample_files/no_secrets/variable-comparison.go b/sample_files/no_secrets/variable-comparison.go similarity index 100% rename from test/sample_files/no_secrets/variable-comparison.go rename to sample_files/no_secrets/variable-comparison.go diff --git a/test/sample_files/secrets/hardcoded-password.js b/sample_files/secrets/hardcoded-password.js similarity index 100% rename from test/sample_files/secrets/hardcoded-password.js rename to sample_files/secrets/hardcoded-password.js diff --git a/test/sample_files/secrets/k8s-manifest-not-encrypted-secret.yaml b/sample_files/secrets/k8s-manifest-not-encrypted-secret.yaml similarity index 100% rename from test/sample_files/secrets/k8s-manifest-not-encrypted-secret.yaml rename to sample_files/secrets/k8s-manifest-not-encrypted-secret.yaml diff --git a/test/sample_files/secrets/k8s-manifest.yaml b/sample_files/secrets/k8s-manifest.yaml similarity index 100% rename from test/sample_files/secrets/k8s-manifest.yaml rename to sample_files/secrets/k8s-manifest.yaml diff --git a/test/sample_files/secrets/multiline-secrets.yml b/sample_files/secrets/multiline-secrets.yml similarity index 50% rename from test/sample_files/secrets/multiline-secrets.yml rename to sample_files/secrets/multiline-secrets.yml index 31fe85c..e815407 100644 --- a/test/sample_files/secrets/multiline-secrets.yml +++ b/sample_files/secrets/multiline-secrets.yml @@ -1,4 +1,4 @@ -token: | - H3*2!4%-6s$%Dk)Gga+12.3 +something: | + cmd directory pwd: |- M8!1-O%2j3)*W&a$N%aGsdGH \ No newline at end of file diff --git a/sample_files/secrets/not-quoted-secrets-2.yaml b/sample_files/secrets/not-quoted-secrets-2.yaml new file mode 100644 index 0000000..4d796ab --- /dev/null +++ b/sample_files/secrets/not-quoted-secrets-2.yaml @@ -0,0 +1 @@ +password: $secr3Tp@s$M0RD diff --git a/sample_files/secrets/not-quoted-secrets.yaml b/sample_files/secrets/not-quoted-secrets.yaml new file mode 100644 index 0000000..161a32e --- /dev/null +++ b/sample_files/secrets/not-quoted-secrets.yaml @@ -0,0 +1 @@ +secret: M%nsd&23_3-1las$dyR/wq@eq8 # some comment diff --git a/test/sample_files/secrets/postman-collection.json b/sample_files/secrets/postman-collection.json similarity index 100% rename from test/sample_files/secrets/postman-collection.json rename to sample_files/secrets/postman-collection.json diff --git a/test/sample_files/secrets/quoted-secrets.yaml b/sample_files/secrets/quoted-secrets.yaml similarity index 100% rename from test/sample_files/secrets/quoted-secrets.yaml rename to sample_files/secrets/quoted-secrets.yaml diff --git a/test/sample_files/secrets/terraform-config.tf b/sample_files/secrets/terraform-config.tf similarity index 100% rename from test/sample_files/secrets/terraform-config.tf rename to sample_files/secrets/terraform-config.tf diff --git a/test/sample_files/secrets/variable-assignment.go b/sample_files/secrets/variable-assignment.go similarity index 58% rename from test/sample_files/secrets/variable-assignment.go rename to sample_files/secrets/variable-assignment.go index 0c40496..7719802 100644 --- a/test/sample_files/secrets/variable-assignment.go +++ b/sample_files/secrets/variable-assignment.go @@ -5,9 +5,9 @@ import ( ) func main() { - password := "5FkbcWgU" - pwd := []byte("5FkbcWgU") - var secret = `5FkbcWgU` + password := "5FkbcWgU!" + pwd := []byte("5FkbcWgU!") + var secret = `5FkbcWgU!` fmt.Println(password) fmt.Println(pwd) diff --git a/test/sample_files/secrets/variable-assignment.php b/sample_files/secrets/variable-assignment.php similarity index 80% rename from test/sample_files/secrets/variable-assignment.php rename to sample_files/secrets/variable-assignment.php index b047da5..2ee1a98 100644 --- a/test/sample_files/secrets/variable-assignment.php +++ b/sample_files/secrets/variable-assignment.php @@ -5,6 +5,5 @@ $b = "Hello "; $b .= "There!"; // sets $b to "Hello There!", just like $b = $b . "There!"; -$pwd = "CjbgVD6a"; -$secret = 'CjbgVD6a'; +$pwd = "CjbgV@D6a"; ?> diff --git a/test/local-config.toml b/test/local-config.toml index b1b982a..973deab 100644 --- a/test/local-config.toml +++ b/test/local-config.toml @@ -6,7 +6,7 @@ regexes = [ "AKIALALEMEL33243OLIA", "AKIALALEMEL38243OLIAE", ] -files = [ +paths = [ "*.mp3" ] commits = [ diff --git a/test/sample_files/secrets/not-quoted-secrets.yaml b/test/sample_files/secrets/not-quoted-secrets.yaml deleted file mode 100644 index 6ca7a08..0000000 --- a/test/sample_files/secrets/not-quoted-secrets.yaml +++ /dev/null @@ -1,2 +0,0 @@ -secret: M%nsd&23_3-1las$dyR/wq@eq8 -password: $secr3Tp@s$M0RD diff --git a/test_global_config.sh b/test_global_config.sh index c173c07..460d153 100755 --- a/test_global_config.sh +++ b/test_global_config.sh @@ -2,40 +2,19 @@ set -e GITLEAKS_IMAGE="zricethezav/gitleaks" -GITLEAKS_VERSION="v6.1.2" +GITLEAKS_VERSION="v8.8.8" # Generate configuration -final_config="${PWD}/global_config.toml" -repo_dir="${PWD}/test_repo" - -cleanup () { - echo "Cleaning up..." - rm -f ${repo_dir} -} - -trap cleanup EXIT +gitleaks_config="${PWD}/global_config.toml" # Run gitleaks on each file of the given directory $1 # $2 is the value of the expected exit code of gitleaks execution (i.e. secrets detection expected or not) # $3 is the error message to be shown when gitleaks' exit code is different than expected run_tests () { for f in ${1}/*; do - # Create a new empty repo for each test file - mkdir -p ${repo_dir} - cd ${repo_dir} - git init - cd .. - - # Copy and git commit the test file - cp -r ${f} ${repo_dir} - cd ${repo_dir} - git add . - git -c user.name='Automated Tests' -c user.email='none@somewhere.org' commit -m 'test' - cd .. - - # Run gitleaks on the repo + # Run gitleaks on the file to be tested echo "Scanning ${f}" - run_gitleaks ${final_config} ${repo_dir} + run_gitleaks ${gitleaks_config} ${f} exit_code=$? if [ ${exit_code} -ne ${2} ]; then @@ -43,16 +22,24 @@ run_tests () { tests_failed=1 fi - rm -rf ${repo_dir} done } # Execute gitleaks with a given configuration file $1 in a given repo $2 run_gitleaks () { + config_file_in_container="/tmp/gitleaks_config.toml" + filename=$(basename ${2}) + scan_source="/tmp/${filename}" + gitleaks_cmd="detect \ + --config ${config_file_in_container} \ + --source ${scan_source} \ + --no-git \ + --report-format json \ + --verbose" run_gitleaks="docker container run --rm --name=gitleaks \ - -v ${1}:/tmp/gitleaks_config.toml \ - -v ${2}:/tmp/repo \ - ${GITLEAKS_IMAGE}:${GITLEAKS_VERSION} --config=/tmp/gitleaks_config.toml --repo=/tmp/repo --verbose" + -v ${1}:${config_file_in_container} \ + -v ${2}:${scan_source} \ + ${GITLEAKS_IMAGE}:${GITLEAKS_VERSION} ${gitleaks_cmd}" echo $run_gitleaks $run_gitleaks } @@ -60,11 +47,11 @@ run_gitleaks () { tests_failed=0 set +e # Run tests expecting to detect a secret -code_with_secrets_dir="${PWD}/test/sample_files/secrets" +code_with_secrets_dir="${PWD}/sample_files/secrets" run_tests ${code_with_secrets_dir} 1 "Expecting to detect secrets in" # Run tests expecting to not detect a secret -code_with_no_secrets_dir="${PWD}/test/sample_files/no_secrets" +code_with_no_secrets_dir="${PWD}/sample_files/no_secrets" run_tests ${code_with_no_secrets_dir} 0 "Expecting to not detect secrets in" if [ ${tests_failed} -eq 0 ]; then