From 0f953f59a5db43d7b43172dec8ea2038d92bb5dc Mon Sep 17 00:00:00 2001 From: Mick Grove Date: Tue, 4 Nov 2025 13:55:31 -0500 Subject: [PATCH] =?UTF-8?q?pattern=5Frequirements=20for=20rules=20?= =?UTF-8?q?=E2=80=94=20Post-regex=20character-class=20gating=20to=20cut=20?= =?UTF-8?q?false=20positives=20without=20lookarounds.=20Authors=20can=20no?= =?UTF-8?q?w=20require=20minimum=20counts=20of=20digits,=20uppercase,=20lo?= =?UTF-8?q?wercase,=20and=20special=20characters,=20with=20an=20optional?= =?UTF-8?q?=20custom=20special-char=20set.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Why: Hyperscan doesn’t support lookaheads/behinds, so many “must contain X and Y” checks had to be baked into the regex (hurting readability) or were impossible. pattern_requirements applies lightweight, in-memory checks after a match is found, keeping patterns fast and clean. --- CHANGELOG.md | 2 + data/rules/adobe.yml | 4 +- data/rules/age.yml | 7 +- data/rules/ai21.yml | 4 + data/rules/airbrake.yml | 6 +- data/rules/airtable.yml | 7 +- data/rules/aiven.yml | 5 + data/rules/algolia.yml | 9 +- data/rules/alibaba.yml | 7 +- data/rules/anthropic.yml | 11 +- data/rules/anypoint.yml | 8 +- data/rules/apify.yml | 5 +- data/rules/artifactory.yml | 4 + data/rules/asana.yml | 14 +- data/rules/assemblyai.yml | 3 + data/rules/atlassian.yml | 5 +- data/rules/auth0.yml | 5 +- data/rules/authress.yml | 4 + data/rules/aws.yml | 10 +- data/rules/azure.yml | 2 + data/rules/azuredevops.yml | 2 + data/rules/azureopenai.yml | 3 + data/rules/azuresearchquery.yml | 4 + data/rules/azurestorage.yml | 16 +- data/rules/baremetrics.yml | 4 +- data/rules/baseten.yml | 4 + data/rules/beamer.yml | 7 +- data/rules/bitbucket.yml | 6 +- data/rules/bitly.yml | 4 +- data/rules/blynk.yml | 20 +++ data/rules/buildkite.yml | 4 +- data/rules/cerebras.yml | 4 +- data/rules/circleci.yml | 9 +- data/rules/ciscomeraki.yml | 3 +- data/rules/clarifai.yml | 2 + data/rules/clearbit.yml | 2 + data/rules/clickhouse.yml | 6 +- data/rules/clojars.yml | 6 +- data/rules/cloudflare.yml | 14 +- data/rules/cloudsight.yml | 6 +- data/rules/codacy.yml | 3 + data/rules/codeclimate.yml | 3 + data/rules/codecov.yml | 3 + data/rules/cohere.yml | 3 + data/rules/coinbase.yml | 4 +- data/rules/confluent.yml | 3 + data/rules/contentful.yml | 9 +- data/rules/coze.yml | 13 +- data/rules/crates.io.yml | 2 + data/rules/databricks.yml | 9 +- data/rules/datadog.yml | 8 +- data/rules/deepgram.yml | 4 +- data/rules/deepseek.yml | 4 +- data/rules/dependency_track.yml | 2 + data/rules/diffbot.yml | 2 + data/rules/digitalocean.yml | 4 +- data/rules/discord.yml | 7 +- data/rules/django.yml | 1 - data/rules/docker.yml | 2 + data/rules/dockerhub.yml | 2 + data/rules/doppler.yml | 6 +- data/rules/droneci.yml | 2 + data/rules/dropbox.yml | 5 +- data/rules/duffel.yml | 2 + data/rules/dynatrace.yml | 2 + data/rules/easypost.yml | 4 +- data/rules/elevenlabs.yml | 6 +- data/rules/facebook.yml | 15 +- data/rules/fastly.yml | 2 + data/rules/figma.yml | 6 +- data/rules/fileio.yml | 2 + data/rules/finicity.yml | 2 + data/rules/finnhub.yml | 2 + data/rules/firecrawl.yml | 2 + data/rules/fireworksai.yml | 2 + data/rules/flickr.yml | 6 +- data/rules/flyio.yml | 2 + data/rules/frame.io.yml | 6 +- data/rules/frameio.yml | 3 + data/rules/freshbooks.yml | 2 + data/rules/friendli.yml | 2 + data/rules/gcp.yml | 10 +- data/rules/generic.yml | 21 ++- data/rules/gitalk.yml | 2 + data/rules/github.yml | 14 +- data/rules/gitlab.yml | 16 +- data/rules/gitter.yml | 2 + data/rules/gocardless.yml | 6 +- data/rules/google.yml | 30 +++- data/rules/grafana.yml | 9 +- data/rules/groq.yml | 2 + data/rules/hashes.yml | 11 +- data/rules/hashicorp.yml | 30 ++-- data/rules/heroku.yml | 7 +- data/rules/hubspot.yml | 2 + data/rules/huggingface.yml | 3 +- data/rules/ibm.yml | 5 +- data/rules/infracost.yml | 2 + data/rules/intercom.yml | 3 + data/rules/ionic.yml | 6 +- data/rules/ipstack.yml | 2 + data/rules/jenkins.yml | 5 +- data/rules/jina.yml | 6 +- data/rules/jira.yml | 13 +- data/rules/jwt.yml | 5 +- data/rules/kagi.yml | 4 +- data/rules/kickbox.yml | 2 + data/rules/langchain.yml | 4 + data/rules/launchdarkly.yml | 2 + data/rules/line.yml | 2 + data/rules/linear.yml | 6 +- data/rules/linkedin.yml | 4 + data/rules/lob.yml | 4 + data/rules/mailchimp.yml | 3 + data/rules/mailgun.yml | 8 +- data/rules/mandrill.yml | 6 +- data/rules/mapbox.yml | 6 + data/rules/mattermost.yml | 2 + data/rules/maxmind.yml | 4 +- data/rules/messagebird.yml | 3 + data/rules/microsoft_teams.yml | 2 + data/rules/microsoftteamswebhook.yml | 28 ++-- data/rules/mistral.yml | 2 + data/rules/mongodb.yml | 9 +- data/rules/nasa.yml | 3 + data/rules/netlify.yml | 8 +- data/rules/newrelic.yml | 3 + data/rules/ngrok.yml | 1 - data/rules/notion.yml | 6 +- data/rules/npm.yml | 3 +- data/rules/nuget.yml | 4 +- data/rules/nvidia.yml | 2 + data/rules/nytimes.yml | 2 + data/rules/okta.yml | 4 +- data/rules/ollama.yml | 2 + data/rules/onepassword.yml | 9 +- data/rules/openai.yml | 4 + data/rules/openweathermap.yml | 3 +- data/rules/opsgenie.yml | 3 + data/rules/pagerdutyapikey.yml | 3 +- data/rules/particle.io.yml | 8 +- data/rules/pastebin.yml | 2 + data/rules/paypal.yml | 109 ++++++------- data/rules/pem.yml | 4 + data/rules/perplexity.yml | 2 + data/rules/planetscale.yml | 6 +- data/rules/postman.yml | 2 + data/rules/postmark.yml | 2 + data/rules/prefect.yml | 2 + data/rules/privkey.yml | 8 +- data/rules/psexec.yml | 1 - data/rules/pubnub.yml | 4 + data/rules/pulumi.yml | 2 + data/rules/pypi.yml | 2 + data/rules/rabbitmq.yml | 3 +- data/rules/react.yml | 7 - data/rules/readme.yml | 5 +- data/rules/recaptcha.yml | 3 + data/rules/replicate.yml | 6 +- data/rules/rubygems.yml | 6 +- data/rules/runway.yml | 4 +- data/rules/salesforce.yml | 4 +- data/rules/sauce.yml | 4 +- data/rules/scale.yml | 10 +- data/rules/scalingo.yml | 3 +- data/rules/segment.yml | 6 +- data/rules/sendbird.yml | 4 + data/rules/sendgrid.yml | 3 +- data/rules/sendinblue.yml | 2 + data/rules/sentry.yml | 7 + data/rules/shippo.yml | 2 + data/rules/shodan.yml | 2 + data/rules/shopify.yml | 2 + data/rules/slack.yml | 10 +- data/rules/snyk.yml | 4 +- data/rules/sonarcloud.yml | 2 + data/rules/sonarqube.yml | 5 +- data/rules/sourcegraph.yml | 8 +- data/rules/square.yml | 23 ++- data/rules/stabilityai.yml | 4 +- data/rules/stackhawk.yml | 2 + data/rules/stripe.yml | 12 +- data/rules/supabase.yml | 8 +- data/rules/tailscale.yml | 2 + data/rules/tavily.yml | 2 + data/rules/teamcity.yml | 2 + data/rules/telegram.yml | 2 + data/rules/thingsboard.yml | 20 ++- data/rules/togetherai.yml | 3 + data/rules/travisci.yml | 4 +- data/rules/truenas.yml | 4 + data/rules/twilio.yml | 8 +- data/rules/twitch.yml | 5 + data/rules/twitter.yml | 8 +- data/rules/typeform.yml | 2 + data/rules/vercel.yml | 4 + data/rules/vmware.yml | 1 - data/rules/weightsandbiases.yml | 4 +- data/rules/wireguard.yml | 2 + data/rules/xAI.yml | 4 +- data/rules/zhipu.yml | 2 + docs/RULES.md | 113 ++++++++++++-- src/baseline.rs | 1 + src/matcher.rs | 18 +++ src/reporter.rs | 1 + src/reporter/json_format.rs | 1 + src/rules/rule.rs | 223 +++++++++++++++++++++++++++ testdata/test_char_requirements.yaml | 24 +++ tests/fingerprint_dedup.rs | 1 + 209 files changed, 1267 insertions(+), 299 deletions(-) create mode 100644 testdata/test_char_requirements.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e23102..8555b69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. +## [Unrelease] +- pattern_requirements for rules — Post-regex character-class gating to cut false positives without lookarounds. Authors can now require minimum counts of digits, uppercase, lowercase, and special characters, with an optional custom special-char set. Why? Hyperscan doesn’t support lookaheads/behinds, so many "must contain X and Y" checks had to be baked into the regex (hurting readability) or were impossible. `pattern_requirements` applies lightweight, in-memory checks after a match is found, keeping patterns fast and clean. ## [v1.61.0] - Fixed local filesystem scans to keep `open_path_as_is` enabled when opening Git repositories and only disable it for diff-based scans. - Created Linux and Windows specific installer script diff --git a/data/rules/adobe.yml b/data/rules/adobe.yml index 03b54d0..09ec783 100644 --- a/data/rules/adobe.yml +++ b/data/rules/adobe.yml @@ -6,11 +6,13 @@ rules: \b adobe (?:.|[\n\r]){0,32}? - \b + \b ( [A-F0-9]{32} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 examples: - adobeKey = 1a2b3c4d5e6f7890abcdef1234567890 diff --git a/data/rules/age.yml b/data/rules/age.yml index f296a26..e024a63 100644 --- a/data/rules/age.yml +++ b/data/rules/age.yml @@ -3,11 +3,14 @@ rules: id: kingfisher.age.1 pattern: | (?xi) - \b ( age1[0-9a-z]{58} ) \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.3 confidence: medium examples: @@ -21,11 +24,9 @@ rules: id: kingfisher.age.2 pattern: | (?xi) - \b ( AGE-SECRET-KEY-1[0-9A-Z]{58} ) - \b min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/ai21.yml b/data/rules/ai21.yml index 7a400eb..899e91c 100644 --- a/data/rules/ai21.yml +++ b/data/rules/ai21.yml @@ -19,6 +19,10 @@ rules: [0-9a-f]{12} ) \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.2 confidence: medium examples: diff --git a/data/rules/airbrake.yml b/data/rules/airbrake.yml index d54d261..8a25076 100644 --- a/data/rules/airbrake.yml +++ b/data/rules/airbrake.yml @@ -9,7 +9,11 @@ rules: ( [A-Z0-9-]{40} ) - \b + \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 4.5 confidence: medium examples: diff --git a/data/rules/airtable.yml b/data/rules/airtable.yml index 7b8b037..abb100d 100644 --- a/data/rules/airtable.yml +++ b/data/rules/airtable.yml @@ -10,7 +10,11 @@ rules: \. [a-z0-9]{62,66} ) - \b + \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.3 confidence: medium examples: @@ -37,7 +41,6 @@ rules: id: kingfisher.airtable.2 pattern: | (?xi) - \b ( [A-Z0-9]+\.v1\.[A-Z0-9_-]+\.[a-f0-9]+ ) diff --git a/data/rules/aiven.yml b/data/rules/aiven.yml index 09a7269..de6fdae 100644 --- a/data/rules/aiven.yml +++ b/data/rules/aiven.yml @@ -9,6 +9,11 @@ rules: ( [a-z0-9/+=]{372} ) + \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/algolia.yml b/data/rules/algolia.yml index dd65cf7..150cda9 100644 --- a/data/rules/algolia.yml +++ b/data/rules/algolia.yml @@ -5,11 +5,13 @@ rules: (?xi) algolia (?:.|[\n\r]){0,32}? - \b ( [a-z0-9]{32} ) \b + pattern_requirements: + min_digits: 2 + min_lowercase: 1 min_entropy: 3.5 confidence: medium examples: @@ -38,11 +40,12 @@ rules: (?xi) algolia (?:.|[\n\r]){0,16}? - \b ( [A-Z0-9]{10} ) - \b + \b + pattern_requirements: + min_digits: 2 min_entropy: 2.0 visible: false confidence: medium diff --git a/data/rules/alibaba.yml b/data/rules/alibaba.yml index b4807ec..990ab91 100644 --- a/data/rules/alibaba.yml +++ b/data/rules/alibaba.yml @@ -3,11 +3,14 @@ rules: id: kingfisher.alibabacloud.1 pattern: | (?xi) - \b ( LTAI[a-z0-9]{17,21} ) \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 4.0 confidence: medium visible: false @@ -21,11 +24,9 @@ rules: \b alibaba (?:.|[\n\r]){0,32}? - \b ( [a-z0-9]{30} ) - \b min_entropy: 4.2 confidence: medium examples: diff --git a/data/rules/anthropic.yml b/data/rules/anthropic.yml index 4f51c88..8907056 100644 --- a/data/rules/anthropic.yml +++ b/data/rules/anthropic.yml @@ -10,15 +10,16 @@ rules: - [\w\-]{93} AA - ) - \b + ) + \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.3 confidence: medium examples: - sk-ant-api668-Clm512odot9WDD7itfUU9R880nefA1EtYZDbpE-C9b0XQEWpqFKf9DQUo03vOfXl16oSmyar1CLF1SzV3YzpZJ6bahcpLAA - categories: - - api - - secret references: - https://docs.anthropic.com/claude/reference/authentication validation: diff --git a/data/rules/anypoint.yml b/data/rules/anypoint.yml index 4b3b8ab..d7d420b 100644 --- a/data/rules/anypoint.yml +++ b/data/rules/anypoint.yml @@ -18,8 +18,12 @@ rules: [0-9a-z]{4} - [0-9a-z]{12} - ) - \b + ) + \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/apify.yml b/data/rules/apify.yml index 78c99dd..1cf959c 100644 --- a/data/rules/apify.yml +++ b/data/rules/apify.yml @@ -3,11 +3,14 @@ rules: id: kingfisher.apify.1 pattern: | (?xi) - \b ( apify_api_[A-Z0-9]{34,38} ) \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 confidence: medium min_entropy: 3.5 validation: diff --git a/data/rules/artifactory.yml b/data/rules/artifactory.yml index f53174e..ff172e3 100644 --- a/data/rules/artifactory.yml +++ b/data/rules/artifactory.yml @@ -8,6 +8,10 @@ rules: AKC[A-Z0-9]{64,74} ) \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/asana.yml b/data/rules/asana.yml index 85e30c5..2d43c31 100644 --- a/data/rules/asana.yml +++ b/data/rules/asana.yml @@ -10,7 +10,9 @@ rules: ( [0-9]{16} ) - \b + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: @@ -30,7 +32,11 @@ rules: ( [a-z0-9]{30,40} ) - \b + \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.5 confidence: medium examples: @@ -54,7 +60,9 @@ rules: [a-z0-9]{32,64} )? ) - \b + \b + pattern_requirements: + min_digits: 4 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/assemblyai.yml b/data/rules/assemblyai.yml index 3c81111..38136d0 100644 --- a/data/rules/assemblyai.yml +++ b/data/rules/assemblyai.yml @@ -11,6 +11,9 @@ rules: [0-9a-z]{32} ) \b + pattern_requirements: + min_digits: 2 + min_lowercase: 1 min_entropy: 3.0 confidence: medium examples: diff --git a/data/rules/atlassian.yml b/data/rules/atlassian.yml index 32dccb2..5d198ee 100644 --- a/data/rules/atlassian.yml +++ b/data/rules/atlassian.yml @@ -10,7 +10,10 @@ rules: ( [a-z0-9]{24} ) - \b + \b + pattern_requirements: + min_digits: 2 + min_lowercase: 1 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/auth0.yml b/data/rules/auth0.yml index 39a0b43..f77497f 100644 --- a/data/rules/auth0.yml +++ b/data/rules/auth0.yml @@ -10,7 +10,10 @@ rules: ( [a-z0-9_-]{32,60} ) - \b + \b + pattern_requirements: + min_digits: 2 + min_lowercase: 1 min_entropy: 3.5 confidence: medium visible: false diff --git a/data/rules/authress.yml b/data/rules/authress.yml index 163d979..1df4922 100644 --- a/data/rules/authress.yml +++ b/data/rules/authress.yml @@ -6,6 +6,10 @@ rules: ( (?:sc|ext|scauth|authress)_[a-z0-9]{5,30}\.[a-z0-9]{4,6}\.acc[_-][a-z0-9-]{10,32}\.[a-z0-9+/_=-]{30,120} ) + \b + pattern_requirements: + min_digits: 2 + min_lowercase: 1 confidence: medium min_entropy: 4.0 validation: diff --git a/data/rules/aws.yml b/data/rules/aws.yml index f5fcf4a..6cd938a 100644 --- a/data/rules/aws.yml +++ b/data/rules/aws.yml @@ -3,12 +3,14 @@ rules: id: kingfisher.aws.1 pattern: | (?xi) - \b + \b ( (?:A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA) [2-7A-Z]{16} ) - \b + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.2 visible: false confidence: medium @@ -37,6 +39,8 @@ rules: ([A-Za-z0-9/+]{40}) \b ) + pattern_requirements: + min_digits: 2 min_entropy: 4.5 confidence: medium examples: @@ -60,6 +64,8 @@ rules: - name: AWS Session Token id: kingfisher.aws.4 pattern: '(?i)(?:aws.?session|aws.?session.?token|aws.?token)["''`]?\s{0,30}(?::|=>|=)\s{0,30}["''`]?([a-z0-9/+=]{16,200})[^a-z0-9/+=]' + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/azure.yml b/data/rules/azure.yml index 94a9902..1a1d650 100644 --- a/data/rules/azure.yml +++ b/data/rules/azure.yml @@ -90,6 +90,8 @@ rules: [A-Z0-9+/]{42}\+ACR[A-Z0-9]{6} ) \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 4.0 validation: diff --git a/data/rules/azuredevops.yml b/data/rules/azuredevops.yml index a607bc9..8a21d80 100644 --- a/data/rules/azuredevops.yml +++ b/data/rules/azuredevops.yml @@ -24,6 +24,8 @@ rules: [a-z0-9]{75,76}AZDO[a-z0-9]{4,5} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3 confidence: medium examples: diff --git a/data/rules/azureopenai.yml b/data/rules/azureopenai.yml index 87e8127..51cba8c 100644 --- a/data/rules/azureopenai.yml +++ b/data/rules/azureopenai.yml @@ -14,6 +14,9 @@ rules: [a-f0-9]{32} ) \b + pattern_requirements: + min_digits: 2 + min_lowercase: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/azuresearchquery.yml b/data/rules/azuresearchquery.yml index 45b84b3..6e37d82 100644 --- a/data/rules/azuresearchquery.yml +++ b/data/rules/azuresearchquery.yml @@ -12,6 +12,10 @@ rules: [0-9A-Z]{52} ) \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/azurestorage.yml b/data/rules/azurestorage.yml index aea15a9..75698f4 100644 --- a/data/rules/azurestorage.yml +++ b/data/rules/azurestorage.yml @@ -33,13 +33,25 @@ rules: (?:.|[\n\r]){0,128}? (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) (?:.|[\n\r]){0,128}? + ["':\s=}\]\)] ( - [A-Z0-9+\\/-]{86,88}={0,2} + (?: + [A-Z0-9+\-]{86,88}={1,2} + ) + | + (?: + [A-Z0-9+\-]{86,88}\b + ) ) + pattern_requirements: + min_digits: 2 + min_uppercase: 2 + min_lowercase: 2 min_entropy: 4.0 confidence: medium examples: - - Azure AccountKey=Xy9aB8cD7eF6gH5iJ4kL3mN2oP1qR0sT9uV8wX7yZ6aB5cD4eF3gH2iJ1kL0mN9oP8qR7sT6uV5wX4yZ3aB2cD1eF0gH9iJ8kL7mN6oP5q==\ + - Azure AccountKey=Xy9aB8cD7eF6gH5iJ4kL3mN2oP1qR0sT9uV8wX7yZ6aB5cD4eF3gH2iJ1kL0mN9oP8qR7sT6uV5wX4yZ3aB2cD1q + - Azure AccountKey=Xy9aB8cD7eF6gH5iJ4kL3mN2oP1qR0sT9uV8wX7yZ6aB5cD4eF3gH2iJ1kL0mN9oP8qR7sT6uV5wX4yZ3aB2cD1g==\ validation: type: AzureStorage depends_on_rule: diff --git a/data/rules/baremetrics.yml b/data/rules/baremetrics.yml index ce0f37a..2844cd3 100644 --- a/data/rules/baremetrics.yml +++ b/data/rules/baremetrics.yml @@ -10,7 +10,9 @@ rules: ( [a-z0-9_-]{25} ) - \b + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium references: diff --git a/data/rules/baseten.yml b/data/rules/baseten.yml index 8773d6c..b3ba12c 100644 --- a/data/rules/baseten.yml +++ b/data/rules/baseten.yml @@ -13,6 +13,10 @@ rules: [A-Za-z0-9]{32} ) \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.4 confidence: medium examples: diff --git a/data/rules/beamer.yml b/data/rules/beamer.yml index f051ff2..bbc2029 100644 --- a/data/rules/beamer.yml +++ b/data/rules/beamer.yml @@ -9,7 +9,12 @@ rules: \b ( b_[A-Z0-9=_\\/\\\-+]{44} - ) + ) + \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.0 confidence: medium examples: diff --git a/data/rules/bitbucket.yml b/data/rules/bitbucket.yml index ad7e74a..61370fa 100644 --- a/data/rules/bitbucket.yml +++ b/data/rules/bitbucket.yml @@ -8,9 +8,10 @@ rules: (?:.|[\n\r]){0,16}? (?:client|id) (?:.|[\n\r]){0,16}? - \b ([a-z0-9]{30,40}) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: @@ -43,6 +44,9 @@ rules: ( [a-z0-9+_\-+]{44} ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/bitly.yml b/data/rules/bitly.yml index 3f4ca02..df79eb3 100644 --- a/data/rules/bitly.yml +++ b/data/rules/bitly.yml @@ -8,11 +8,13 @@ rules: (?:.|[\n\r]){0,32}? (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) (?:.|[\n\r]){0,32}? - \b ( [a-f0-9]{40} ) \b + pattern_requirements: + min_digits: 2 + min_lowercase: 2 confidence: medium min_entropy: 3.0 validation: diff --git a/data/rules/blynk.yml b/data/rules/blynk.yml index 4af12c6..1f58e85 100644 --- a/data/rules/blynk.yml +++ b/data/rules/blynk.yml @@ -6,6 +6,10 @@ rules: https://(?:fra1\.|lon1\.|ny3\.|sgp1\.|blr1\.)*blynk\.cloud/external/api/[A-Z0-9/]*\?token= ([A-Z0-9_\-]{32}) & + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.3 confidence: medium examples: @@ -21,6 +25,10 @@ rules: -H\s*"Authorization:\s*Bearer\s* ([A-Z0-9_\-]{40}) " + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.3 confidence: medium examples: @@ -35,6 +43,10 @@ rules: -H\s*"Authorization:\s*Bearer\s* ([A-Z0-9_\-]{40}) "[\s\\]*https://(?:fra1\.|lon1\.|ny3\.|sgp1\.|blr1\.)*blynk\.cloud/api + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.3 confidence: medium examples: @@ -50,6 +62,10 @@ rules: (oa2-client-id_[A-Z0-9_\-]{32}) (?: : | &client_secret= ) ([A-Z0-9_\-]{40}) + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.3 confidence: medium examples: @@ -66,6 +82,10 @@ rules: (oa2-client-id_[A-Z0-9_\-]{32}) :([A-Z0-9_\-]{40}) [\s\\]*https://(fra1\.|lon1\.|ny3\.|sgp1\.|blr1\.)*blynk\.cloud/oauth2 + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/buildkite.yml b/data/rules/buildkite.yml index 3728e98..045fa94 100644 --- a/data/rules/buildkite.yml +++ b/data/rules/buildkite.yml @@ -3,11 +3,13 @@ rules: id: kingfisher.buildkite.1 pattern: | (?xi) - \b ( bkua_[a-z0-9]{40} ) \b + pattern_requirements: + min_digits: 2 + min_lowercase: 1 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/cerebras.yml b/data/rules/cerebras.yml index 73760a6..044506e 100644 --- a/data/rules/cerebras.yml +++ b/data/rules/cerebras.yml @@ -3,11 +3,13 @@ rules: id: kingfisher.cerebras.1 pattern: | (?xi) - \b ( csk-[a-z0-9]{48} ) \b + pattern_requirements: + min_digits: 2 + min_lowercase: 2 confidence: medium min_entropy: 3.0 validation: diff --git a/data/rules/circleci.yml b/data/rules/circleci.yml index f3f2d2a..da20a80 100644 --- a/data/rules/circleci.yml +++ b/data/rules/circleci.yml @@ -20,7 +20,9 @@ rules: _ [a-z0-9]{40} ) - \b + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: @@ -56,7 +58,10 @@ rules: ( [a-f0-9]{40} ) - \b + \b + pattern_requirements: + min_digits: 2 + min_lowercase: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/ciscomeraki.yml b/data/rules/ciscomeraki.yml index a8cc4f1..03f9d3a 100644 --- a/data/rules/ciscomeraki.yml +++ b/data/rules/ciscomeraki.yml @@ -5,11 +5,12 @@ rules: (?xi) meraki (?:.|[\n\r]){0,32}? - \b ( [0-9a-f]{40} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/clarifai.yml b/data/rules/clarifai.yml index d72c9f2..0942f19 100644 --- a/data/rules/clarifai.yml +++ b/data/rules/clarifai.yml @@ -11,6 +11,8 @@ rules: [0-9a-f]{32,36} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.0 confidence: medium examples: diff --git a/data/rules/clearbit.yml b/data/rules/clearbit.yml index caa9e7a..02e4469 100644 --- a/data/rules/clearbit.yml +++ b/data/rules/clearbit.yml @@ -13,6 +13,8 @@ rules: [0-9a-z_]{35} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/clickhouse.yml b/data/rules/clickhouse.yml index 57317b9..9f22697 100644 --- a/data/rules/clickhouse.yml +++ b/data/rules/clickhouse.yml @@ -8,6 +8,8 @@ rules: 4b1d[a-z0-9]{38} ) \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 3.5 examples: @@ -43,11 +45,11 @@ rules: (?:.|[\n\r]){0,16}? (?:ID|USER) (?:.|[\n\r]){0,16}? - \b ( [a-z0-9]{20} ) - \b + pattern_requirements: + min_digits: 2 confidence: medium visible: false min_entropy: 3.0 diff --git a/data/rules/clojars.yml b/data/rules/clojars.yml index 58fb19d..5dfaf53 100644 --- a/data/rules/clojars.yml +++ b/data/rules/clojars.yml @@ -10,9 +10,11 @@ rules: (?:.|[\n\r]){0,16}? \b ( - [a-zA-Z0-9_-]{3,} + [a-z0-9_-]{3,} ) \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 1.5 visible: false @@ -28,6 +30,8 @@ rules: CLOJARS_[a-z0-9]{60} ) \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 4.0 examples: diff --git a/data/rules/cloudflare.yml b/data/rules/cloudflare.yml index 776c1bd..aaf9d34 100644 --- a/data/rules/cloudflare.yml +++ b/data/rules/cloudflare.yml @@ -12,7 +12,11 @@ rules: ( [a-z0-9_-]{38,42} ) - \b + \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.5 confidence: medium examples: @@ -47,8 +51,9 @@ rules: ( v1\.0-[a-z0-9._-]{160,} ) - ["'`]? - \b + \b + pattern_requirements: + min_digits: 2 min_entropy: 4.5 confidence: medium examples: @@ -58,9 +63,6 @@ rules: references: - https://developers.cloudflare.com/api/keys/ - https://developers.cloudflare.com/fundamentals/api/get-started/keys/ - categories: - - api - - secret validation: type: Http content: diff --git a/data/rules/cloudsight.yml b/data/rules/cloudsight.yml index b06e922..f3bd7f6 100644 --- a/data/rules/cloudsight.yml +++ b/data/rules/cloudsight.yml @@ -11,8 +11,10 @@ rules: \b ( [a-z0-9]{20,24} - ) - \b + ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/codacy.yml b/data/rules/codacy.yml index 121dbf4..e0a68d5 100644 --- a/data/rules/codacy.yml +++ b/data/rules/codacy.yml @@ -12,6 +12,9 @@ rules: ( [0-9A-Z]{20,24} ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/codeclimate.yml b/data/rules/codeclimate.yml index 677cbc5..aeaa805 100644 --- a/data/rules/codeclimate.yml +++ b/data/rules/codeclimate.yml @@ -5,10 +5,13 @@ rules: (?xi) (?: CODECLIMATE| CC_TEST_REPORTER_ID) (?:.|[\n\r]){0,64}? + \b ( [a-f0-9]{64} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/codecov.yml b/data/rules/codecov.yml index 1bc5e7a..a2ab1e7 100644 --- a/data/rules/codecov.yml +++ b/data/rules/codecov.yml @@ -8,10 +8,13 @@ rules: (?:.|[\n\r]){0,32}? (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) (?:.|[\n\r]){0,32}? + \b ( [A-Z0-9-]{36} ) \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 3.5 validation: diff --git a/data/rules/cohere.yml b/data/rules/cohere.yml index a362570..f8136f4 100644 --- a/data/rules/cohere.yml +++ b/data/rules/cohere.yml @@ -6,10 +6,13 @@ rules: \b cohere (?:.|[\n\r]){0,16}? + \b ( [A-Z0-9]{40} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/coinbase.yml b/data/rules/coinbase.yml index c5a5763..159dc90 100644 --- a/data/rules/coinbase.yml +++ b/data/rules/coinbase.yml @@ -10,9 +10,11 @@ rules: (?:.|[\n\r]){0,16}? \b ( - [a-zA-Z-0-9]{32} + [a-z-0-9]{32} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 examples: - coinbase_token = 32iAkQCcHHYxXGx20VogBZoj27PC1ouI diff --git a/data/rules/confluent.yml b/data/rules/confluent.yml index 7deda55..96fefe2 100644 --- a/data/rules/confluent.yml +++ b/data/rules/confluent.yml @@ -10,6 +10,8 @@ rules: [A-Z0-9]{16} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3 confidence: medium visible: false @@ -30,6 +32,7 @@ rules: ( [A-Z0-9\+/]{64} ) + \b min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/contentful.yml b/data/rules/contentful.yml index 3846abf..3c91b77 100644 --- a/data/rules/contentful.yml +++ b/data/rules/contentful.yml @@ -10,9 +10,12 @@ rules: (?:.|[\n\r]){0,32}? \b ( - [a-zA-Z0-9_-]{43,45} + [A-Z0-9_-]{43,45} ) \b + pattern_requirements: + min_digits: 2 + min_special_chars: 1 confidence: medium min_entropy: 4.0 validation: @@ -42,11 +45,11 @@ rules: id: kingfisher.contentful.2 pattern: | (?xi) - \b ( CFPAT-[A-Z0-9_-]{43} ) - \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 3.5 validation: diff --git a/data/rules/coze.yml b/data/rules/coze.yml index df3692a..982578b 100644 --- a/data/rules/coze.yml +++ b/data/rules/coze.yml @@ -1,7 +1,18 @@ rules: - name: Coze Personal Access Token id: kingfisher.coze.1 - pattern: '(?i)\b(pat_[a-zA-Z0-9]{64})\b' + pattern: | + (?xi) + \b + coze + (?:.|[\n\r]){0,32}? + \b + ( + pat_[A-Z0-9]{64} + ) + \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 5.0 validation: diff --git a/data/rules/crates.io.yml b/data/rules/crates.io.yml index 7f6b8f2..4aa7ef6 100644 --- a/data/rules/crates.io.yml +++ b/data/rules/crates.io.yml @@ -8,6 +8,8 @@ rules: cio[A-Z0-9]{32} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/databricks.yml b/data/rules/databricks.yml index 9cec5c3..294cb20 100644 --- a/data/rules/databricks.yml +++ b/data/rules/databricks.yml @@ -2,12 +2,17 @@ rules: - name: Databricks API token id: kingfisher.databricks.1 pattern: | - (?xi) + (?xi) + \b ( dapi [a-f0-9]{32} ) - \b + \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/datadog.yml b/data/rules/datadog.yml index 79ff171..6958bf8 100644 --- a/data/rules/datadog.yml +++ b/data/rules/datadog.yml @@ -13,6 +13,8 @@ rules: [a-z0-9]{32} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: @@ -47,11 +49,13 @@ rules: (?:.|[\n\r]){0,64}? (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) (?:.|[\n\r]){0,16}? - \b ( [a-z0-9]{40} ) - \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/deepgram.yml b/data/rules/deepgram.yml index 850afa9..5a474f6 100644 --- a/data/rules/deepgram.yml +++ b/data/rules/deepgram.yml @@ -6,11 +6,13 @@ rules: \b deepgram (?:.|[\n\r]){0,32}? - \b + \b ( [0-9a-f]{40} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/deepseek.yml b/data/rules/deepseek.yml index f303c48..233ae52 100644 --- a/data/rules/deepseek.yml +++ b/data/rules/deepseek.yml @@ -6,8 +6,10 @@ rules: \b ( sk-[a-f0-9]{32} - ) + ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.7 confidence: medium examples: diff --git a/data/rules/dependency_track.yml b/data/rules/dependency_track.yml index e41aa32..10f397c 100644 --- a/data/rules/dependency_track.yml +++ b/data/rules/dependency_track.yml @@ -8,6 +8,8 @@ rules: odt_[A-Z0-9]{32,255} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/diffbot.yml b/data/rules/diffbot.yml index 231109b..01c4114 100644 --- a/data/rules/diffbot.yml +++ b/data/rules/diffbot.yml @@ -11,6 +11,8 @@ rules: [0-9a-z]{32} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.0 examples: - diffbot_key = a7424adbafc4624e61482d0f60e43016 diff --git a/data/rules/digitalocean.yml b/data/rules/digitalocean.yml index b02bb52..b6ca932 100644 --- a/data/rules/digitalocean.yml +++ b/data/rules/digitalocean.yml @@ -9,6 +9,8 @@ rules: [a-f0-9]{64} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: @@ -33,12 +35,10 @@ rules: id: kingfisher.digitalocean.2 pattern: | (?x) - \b ( dor_v1_ [a-f0-9]{64} ) - \b min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/discord.yml b/data/rules/discord.yml index 6b8809b..f350c29 100644 --- a/data/rules/discord.yml +++ b/data/rules/discord.yml @@ -10,6 +10,9 @@ rules: ( [0-9a-z_\-]{68} ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: @@ -32,7 +35,6 @@ rules: id: kingfisher.discord.2 pattern: | (?xi) - \b ( [MNO][A-Z0-9_-]{23}\.[A-Z0-9_-]{6}\.[A-Z0-9_-]{27} ) @@ -61,14 +63,11 @@ rules: id: kingfisher.discord.3 pattern: | (?xi) - \b (?:discord|botid|bot_id) (?:.|[\n\r]){0,64}? - \b ( \d{17,19} ) - \b min_entropy: 3.5 visible: false confidence: medium diff --git a/data/rules/django.yml b/data/rules/django.yml index c335542..c9efa82 100644 --- a/data/rules/django.yml +++ b/data/rules/django.yml @@ -5,7 +5,6 @@ rules: (?x) [DJANGO]\w{0,8}SECRET_KEY .{1,16}? - \b ( [A-Za-z0-9*!$@\#&_%^-]{45,55} ) diff --git a/data/rules/docker.yml b/data/rules/docker.yml index 1d37ab8..1503cd4 100644 --- a/data/rules/docker.yml +++ b/data/rules/docker.yml @@ -12,6 +12,8 @@ rules: \} [^}]*? \} + pattern_requirements: + min_digits: 2 min_entropy: 2.0 confidence: medium examples: diff --git a/data/rules/dockerhub.yml b/data/rules/dockerhub.yml index e26d108..45c740b 100644 --- a/data/rules/dockerhub.yml +++ b/data/rules/dockerhub.yml @@ -8,6 +8,8 @@ rules: dckr_pat_[A-Z0-9_-]{27} ) (?: $ | [^A-Z0-9_-] ) + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/doppler.yml b/data/rules/doppler.yml index c8c302a..fde9282 100644 --- a/data/rules/doppler.yml +++ b/data/rules/doppler.yml @@ -4,8 +4,12 @@ rules: pattern: | (?xi) \b - (dp\.ct\.[A-Z0-9]{40,44}) + ( + dp\.ct\.[A-Z0-9]{40,44} + ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/droneci.yml b/data/rules/droneci.yml index 8e26b66..e6a4bd1 100644 --- a/data/rules/droneci.yml +++ b/data/rules/droneci.yml @@ -15,6 +15,8 @@ rules: [a-f0-9]{32,64} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/dropbox.yml b/data/rules/dropbox.yml index d7d4766..d21eb80 100644 --- a/data/rules/dropbox.yml +++ b/data/rules/dropbox.yml @@ -4,11 +4,12 @@ rules: pattern: | (?xi) \b - sl\. ( - [A-Z0-9\-\_]{130,152} + sl\.[A-Z0-9\-\_]{130,152} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/duffel.yml b/data/rules/duffel.yml index 9b52965..da0a928 100644 --- a/data/rules/duffel.yml +++ b/data/rules/duffel.yml @@ -8,6 +8,8 @@ rules: duffel_(?:test|live)_[a-z0-9_\-=]{43} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.2 confidence: medium examples: diff --git a/data/rules/dynatrace.yml b/data/rules/dynatrace.yml index af8a415..29226f4 100644 --- a/data/rules/dynatrace.yml +++ b/data/rules/dynatrace.yml @@ -12,6 +12,8 @@ rules: [A-Z0-9]{64} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/easypost.yml b/data/rules/easypost.yml index 757a70a..d5f1a42 100644 --- a/data/rules/easypost.yml +++ b/data/rules/easypost.yml @@ -6,9 +6,11 @@ rules: \b ( EZ[AT]K - [A-Za-z0-9]{54} + [A-Z0-9]{54} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/elevenlabs.yml b/data/rules/elevenlabs.yml index ade342c..9378a34 100644 --- a/data/rules/elevenlabs.yml +++ b/data/rules/elevenlabs.yml @@ -2,13 +2,15 @@ rules: - name: ElevenLabs API Key id: kingfisher.elevenlabs.1 pattern: | - (?xi) - \b + (?xi) + \b ( sk_ [0-9a-f]{48} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/facebook.yml b/data/rules/facebook.yml index d3ef582..841cda9 100644 --- a/data/rules/facebook.yml +++ b/data/rules/facebook.yml @@ -11,8 +11,10 @@ rules: \b ( \d{15} - ) - \b + ) + \b + pattern_requirements: + min_digits: 15 min_entropy: 2.0 visible: false confidence: medium @@ -37,6 +39,8 @@ rules: - " var fbApiKey = '0278fc1adf6dc1d82a156f306ce2c5cc';" - ' fbApiKey: "171e84fd57f430fc59afa8fad3dbda2a",' - '"facebook appSecret = "ce3f9f0362bbe5ab01dfc8ee565e4372"' + pattern_requirements: + min_digits: 2 validation: type: Http content: @@ -69,9 +73,12 @@ rules: (?:access_token|access[\s-]token) (?:.|[\n\r]){0,32}? )? + ( + EAACEdEose0cBA[A-Z0-9]{20,} + ) \b - (EAACEdEose0cBA[A-Z0-9]{20,}) - \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/fastly.yml b/data/rules/fastly.yml index 77618a6..07cadce 100644 --- a/data/rules/fastly.yml +++ b/data/rules/fastly.yml @@ -13,6 +13,8 @@ rules: [a-z0-9_-]{32} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/figma.yml b/data/rules/figma.yml index 7cc6f00..b5faf90 100644 --- a/data/rules/figma.yml +++ b/data/rules/figma.yml @@ -8,6 +8,8 @@ rules: figd_[A-Z0-9_-]{38,42} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: @@ -36,14 +38,14 @@ rules: (?xi) figma (?:.|[\n\r]){0,32}? - \b ( [0-9A-F]{4} -[0-9A-F]{8} (?:-[0-9A-F]{4}){3} -[0-9A-F]{12} ) - \b + pattern_requirements: + min_digits: 2 examples: - "--header='X-Figma-Token: 1394-0ca7a5be-8e22-40ee-8c40-778d41ab2313'" references: diff --git a/data/rules/fileio.yml b/data/rules/fileio.yml index 7bf255e..804fcd4 100644 --- a/data/rules/fileio.yml +++ b/data/rules/fileio.yml @@ -14,6 +14,8 @@ rules: \.[A-Z0-9]{20} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/finicity.yml b/data/rules/finicity.yml index 5273fbf..4a29310 100644 --- a/data/rules/finicity.yml +++ b/data/rules/finicity.yml @@ -13,6 +13,8 @@ rules: [a-f0-9]{32} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/finnhub.yml b/data/rules/finnhub.yml index 01e8c0a..3d71fb6 100644 --- a/data/rules/finnhub.yml +++ b/data/rules/finnhub.yml @@ -11,6 +11,8 @@ rules: [a-z0-9]{20} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.0 confidence: medium examples: diff --git a/data/rules/firecrawl.yml b/data/rules/firecrawl.yml index fc729c6..80665b3 100644 --- a/data/rules/firecrawl.yml +++ b/data/rules/firecrawl.yml @@ -8,6 +8,8 @@ rules: fc-[a-f0-9]{32} ) \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 3.0 validation: diff --git a/data/rules/fireworksai.yml b/data/rules/fireworksai.yml index 0933441..f96d251 100644 --- a/data/rules/fireworksai.yml +++ b/data/rules/fireworksai.yml @@ -8,6 +8,8 @@ rules: fw_[A-Z0-9]{24} ) \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 3.5 validation: diff --git a/data/rules/flickr.yml b/data/rules/flickr.yml index d789348..fb104eb 100644 --- a/data/rules/flickr.yml +++ b/data/rules/flickr.yml @@ -13,6 +13,8 @@ rules: [a-f0-9]{32} ) \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 3.0 validation: @@ -43,11 +45,11 @@ rules: (?:.|[\n\r]){0,32}? (?:OAUTH|ACCESS|TOKEN)? (?:.|[\n\r]){0,32}? - \b ( [a-f0-9]{32} ) - \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 3.0 validation: diff --git a/data/rules/flyio.yml b/data/rules/flyio.yml index 98b3a6a..4764279 100644 --- a/data/rules/flyio.yml +++ b/data/rules/flyio.yml @@ -8,6 +8,8 @@ rules: FlyV1\s[A-Za-z0-9=_\-,/+]{100,} ) \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 4.0 validation: diff --git a/data/rules/frame.io.yml b/data/rules/frame.io.yml index a5ef94b..035aefc 100644 --- a/data/rules/frame.io.yml +++ b/data/rules/frame.io.yml @@ -7,7 +7,11 @@ rules: ( fio-u-(?:[A-Z0-9_-]{16}){4} ) - \b + \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/frameio.yml b/data/rules/frameio.yml index 1910965..cfbfe10 100644 --- a/data/rules/frameio.yml +++ b/data/rules/frameio.yml @@ -7,6 +7,9 @@ rules: ( fio-u-[a-z0-9\-_=]{64} ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/freshbooks.yml b/data/rules/freshbooks.yml index 95fadce..d63c14a 100644 --- a/data/rules/freshbooks.yml +++ b/data/rules/freshbooks.yml @@ -11,6 +11,8 @@ rules: [a-z0-9]{64} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/friendli.yml b/data/rules/friendli.yml index ec5f3ec..6881ffc 100644 --- a/data/rules/friendli.yml +++ b/data/rules/friendli.yml @@ -8,6 +8,8 @@ rules: flp_[A-Z0-9]{46} ) \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 3.0 validation: diff --git a/data/rules/gcp.yml b/data/rules/gcp.yml index e23acb4..30d4d1d 100644 --- a/data/rules/gcp.yml +++ b/data/rules/gcp.yml @@ -15,6 +15,8 @@ rules: "auth_provider_x509_cert_url":\s*".+?" (?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})* \} + pattern_requirements: + min_digits: 2 min_entropy: 4.5 confidence: high examples: @@ -48,9 +50,13 @@ rules: [=:] \s{0,8} ["']? - ([0-9a-z]{35,40}) + ( + [0-9a-z]{35,40} + ) ["']? - \b + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/generic.yml b/data/rules/generic.yml index be42e5c..38308f4 100644 --- a/data/rules/generic.yml +++ b/data/rules/generic.yml @@ -5,9 +5,12 @@ rules: (?xi) secret .{0,20} + ( + [0-9a-z]{32,64} + ) \b - ([0-9a-z]{32,64}) - \b + pattern_requirements: + min_digits: 4 min_entropy: 3.3 confidence: low examples: @@ -18,9 +21,12 @@ rules: (?xi) (?: api_key | apikey | access_key | accesskey ) (?:.|[\n\r]){0,8}? + ( + [0-9a-z][0-9a-z\-._/+]{30,62}[0-9a-z] + ) \b - ([0-9a-z][0-9a-z\-._/+]{30,62}[0-9a-z]) - \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: low examples: @@ -31,7 +37,6 @@ rules: pattern: | (?xi) (?: username | user) - \b (?:.|[\n\r]){0,16}? (?: password | pass ) (?:.|[\n\r]){0,16}? @@ -66,7 +71,6 @@ rules: pattern: | (?xi) (?: username | user) - \b (?:.|[\n\r]){0,16}? (?: password | pass ) (?:.|[\n\r]){0,16}? @@ -89,7 +93,6 @@ rules: pattern: | (?xi) password - \b (?:.|[\n\r]){0,16}? ["'] ([^$<%@.,\s'"(){}&/\#\-][^\s'"(){}/]{4,}) (?# password ) @@ -130,7 +133,6 @@ rules: id: kingfisher.generic.6 pattern: | (?xi) - \b ( blink\d{3,6} |correcthorsebatterystaple\d{0,6} @@ -144,7 +146,6 @@ rules: |qwerty\d{3,6} |trustno\d{1,6} ) - \b min_entropy: 1.0 confidence: low examples: @@ -158,7 +159,6 @@ rules: pattern: | (?xi) (?: db_user | db_USERNAME | db_name) - \b (?:.|[\n\r]){0,8}? ["'] ([^"']{5,40}) ["'] (?:.|[\n\r]){0,32}? @@ -197,7 +197,6 @@ rules: id: kingfisher.generic.9 pattern: | (?xi) - \b ( (?P [a-z0-9._-]+ \+ [a-z0-9._-]+ ) : diff --git a/data/rules/gitalk.yml b/data/rules/gitalk.yml index 94574a4..d052855 100644 --- a/data/rules/gitalk.yml +++ b/data/rules/gitalk.yml @@ -7,6 +7,8 @@ rules: new \s+ Gitalk \s* \( \s* \{ \s* clientID: \s* '([a-f0-9]{20})', \s* clientSecret: \s* '([a-f0-9]{40})', + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 3.0 references: diff --git a/data/rules/github.yml b/data/rules/github.yml index 971f10d..88f9a56 100644 --- a/data/rules/github.yml +++ b/data/rules/github.yml @@ -18,6 +18,9 @@ rules: ) ) \b + pattern_requirements: + min_digits: 2 + min_lowercase: 2 min_entropy: 3.5 examples: - "GITHUB_KEY=ghp_XIxB7KMNdAr3zqWtQqhE94qglHqOzn1D1stg" @@ -57,8 +60,9 @@ rules: ( gho_ [A-Z0-9]{36} - ) - \b + ) + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: @@ -90,11 +94,9 @@ rules: id: kingfisher.github.3 pattern: | (?xi) - \b ( (?:ghu|ghs)_[A-Z0-9]{36} ) - \b examples: - ' "token": "ghu_16C7e42F292c69C2E7C10c838347Ae178B4a",' - | @@ -126,11 +128,9 @@ rules: id: kingfisher.github.4 pattern: | (?xi) - \b ( ghr_[A-Z0-9]{76} ) - \b examples: - ' "refresh_token": "ghr_1B4a2e77838347a7E420ce178F2E7c6912E169246c3CE1ccbF66C46812d16D5B1A9Dc86A1498",' references: @@ -210,11 +210,9 @@ rules: id: kingfisher.github.7 pattern: | (?xi) - \b ( github_pat_[0-9A-Z_]{82} ) - \b examples: - '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' validation: diff --git a/data/rules/gitlab.yml b/data/rules/gitlab.yml index 1cdf48c..08ea0ea 100644 --- a/data/rules/gitlab.yml +++ b/data/rules/gitlab.yml @@ -2,12 +2,15 @@ rules: - name: GitLab Private Token id: kingfisher.gitlab.1 pattern: | - (?xi) - \b + (?xi) + \b ( glpat- [0-9A-Z_-]{20} ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: @@ -42,6 +45,8 @@ rules: GR1348941[0-9A-Z_-]{20} ) \b + pattern_requirements: + min_digits: 2 examples: - | sudo gitlab-runner register \ @@ -86,6 +91,8 @@ rules: glptt-[0-9a-f]{40} ) \b + pattern_requirements: + min_digits: 2 examples: - | curl \ @@ -117,11 +124,14 @@ rules: - name: GitLab Private Token - Updated Format id: kingfisher.gitlab.4 pattern: | - (?x) + (?x) \b ( glpat-[A-Za-z0-9_-]{36,38}\.01\.[a-z0-9]{9} ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/gitter.yml b/data/rules/gitter.yml index e2b261c..3da37a3 100644 --- a/data/rules/gitter.yml +++ b/data/rules/gitter.yml @@ -11,6 +11,8 @@ rules: [a-z0-9_-]{40} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.2 confidence: medium examples: diff --git a/data/rules/gocardless.yml b/data/rules/gocardless.yml index e261372..525b20b 100644 --- a/data/rules/gocardless.yml +++ b/data/rules/gocardless.yml @@ -13,7 +13,11 @@ rules: (?:[A-Z0-9=_-]{8}){3} [A-Z0-9=_-]{0,2} ) - \b + \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/google.yml b/data/rules/google.yml index d7d4aed..c338245 100644 --- a/data/rules/google.yml +++ b/data/rules/google.yml @@ -15,9 +15,12 @@ rules: id: kingfisher.google.2 pattern: | (?xi) - \b (GOCSPX-[A-Z0-9_-]{28}) (?:[^A-Z0-9_-] | $) + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.3 confidence: medium examples: @@ -28,9 +31,14 @@ rules: pattern: | (?xi) client.?secret .{0,10} - \b - ([a-z0-9_-]{24}) + ( + [a-z0-9_-]{24} + ) (?: [^a-z0-9_-] |$) + pattern_requirements: + min_digits: 4 + min_uppercase: 3 + min_lowercase: 3 min_entropy: 3.3 confidence: medium examples: @@ -42,9 +50,12 @@ rules: id: kingfisher.google.4 pattern: | (?xi) - \b (ya29\.[0-9A-Z_-]{20,1024}) (?: [^0-9A-Z_-]|$) + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.3 confidence: medium examples: @@ -66,12 +77,10 @@ rules: id: kingfisher.google.6 pattern: | (?xi) - \b ([0-9]+-[a-z0-9_]{32}\.apps\.googleusercontent\.com) (?: (?s).{0,40} ) - \b (?: (GOCSPX-[A-Z0-9_-]{28}) | @@ -80,6 +89,10 @@ rules: ) ) (?:[^A-Z0-9_-] | $) + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.3 confidence: medium examples: @@ -98,11 +111,16 @@ rules: id: kingfisher.google.7 pattern: | (?xi) + \b ( AIza [A-Za-z0-9_-]{35} ) \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/grafana.yml b/data/rules/grafana.yml index 4cb5461..a7c9726 100644 --- a/data/rules/grafana.yml +++ b/data/rules/grafana.yml @@ -8,6 +8,8 @@ rules: eyJrIjoi[a-z0-9]{60,100} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: @@ -20,12 +22,15 @@ rules: id: kingfisher.grafana.2 pattern: | (?xi) - \b + \b ( glc_ [a-z0-9+/]{40,150} ={0,2} ) + pattern_requirements: + min_digits: 2 + min_lowercase: 2 min_entropy: 3.3 confidence: medium examples: @@ -56,6 +61,8 @@ rules: glsa_[A-Z0-9]{32}_[A-F0-9]{8} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/groq.yml b/data/rules/groq.yml index b232ddd..deab409 100644 --- a/data/rules/groq.yml +++ b/data/rules/groq.yml @@ -8,6 +8,8 @@ rules: gsk_[a-zA-Z0-9]{52} ) \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 4.5 validation: diff --git a/data/rules/hashes.yml b/data/rules/hashes.yml index 60b0f4a..bf6f5af 100644 --- a/data/rules/hashes.yml +++ b/data/rules/hashes.yml @@ -7,6 +7,8 @@ rules: - https://unix.stackexchange.com/a/511017 - https://hashcat.net/wiki/doku.php?id=example_hashes - https://passwordvillage.org/salted.html#md5crypt + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: # generated with `openssl passwd -1 -salt 'OKgLCmVl' 'a'` @@ -38,6 +40,8 @@ rules: \$ [./A-Za-z0-9]{8,16} \$ [./A-Za-z0-9]{43} ) + pattern_requirements: + min_digits: 2 references: - https://en.wikipedia.org/wiki/Crypt_(C)#Key_derivation_functions_supported_by_crypt - https://hashcat.net/wiki/doku.php?id=example_hashes @@ -58,6 +62,8 @@ rules: \$ [./A-Za-z0-9]{8,16} \$ [./A-Za-z0-9]{86} ) + pattern_requirements: + min_digits: 2 references: - https://en.wikipedia.org/wiki/Crypt_(C)#Key_derivation_functions_supported_by_crypt - https://hashcat.net/wiki/doku.php?id=example_hashes @@ -76,6 +82,8 @@ rules: \$ [./A-Za-z0-9]{8,16} \$ [./A-Za-z0-9]{43} ) + pattern_requirements: + min_digits: 2 references: - https://en.wikipedia.org/wiki/Crypt_(C)#Key_derivation_functions_supported_by_crypt - https://hashcat.net/wiki/doku.php?id=example_hashes @@ -96,7 +104,8 @@ rules: [0-9a-f]{32} \$ [0-9a-f]{64,} ) - \b + pattern_requirements: + min_digits: 2 references: - https://hashcat.net/wiki/doku.php?id=example_hashes min_entropy: 3.3 diff --git a/data/rules/hashicorp.yml b/data/rules/hashicorp.yml index 20adfc1..b6a0de1 100644 --- a/data/rules/hashicorp.yml +++ b/data/rules/hashicorp.yml @@ -5,16 +5,20 @@ rules: pattern: | (?x) (?i: hashicorp | vault | token | key | secret ) - ["':=\ ]{0,5} + (?:.|[\n\r]){0,32}? \b - (s\.[A-Za-z0-9_-]{24,128}) - (?: [^A-Za-z0-9_-] | $ ) + ( + s\.[A-Za-z0-9_-]{24,128} + ) + \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 3.0 examples: - 'VAULT_CLIENT_TOKEN="s.Z4bTMtngfLeQ18AqVoBBkUAOD1"' - - '`-vaultToken s.CAESIP2jTxc9S3K7Z6CtcFWQv7-044m_oSsxkingfisher.0H3nF89l3GiYKHGh3cy5sQmlIZVNyTWJNcDRsYWJpQjlhYjVlb2cQh6PL8wEYAg"`' + - 'vaultToken="s.CAESIP2jTxc9S3K7Z6CtcFWQv7-044m_oS.0H3nF89l3GiYKHGh3cy5sQmlIZVNyTWJNcDRsYWJpQjlhYjVlb2cQh6PL8wEYAg"`' references: - https://developer.hashicorp.com/vault/docs/concepts/tokens @@ -26,9 +30,10 @@ rules: (?x) (?i: hashicorp | vault | token | key | secret ) ["':=\ ]{0,5} - \b (b\.[A-Za-z0-9_-]{24,500}) (?: [^A-Za-z0-9_-] | $ ) + pattern_requirements: + min_digits: 2 examples: - 'VAULT_CLIENT_TOKEN="b.Z4bTMtngfLeQ18AqVoBBkUAOD1"' @@ -44,9 +49,10 @@ rules: (?x) (?i: hashicorp | vault | token | key | secret ) ["':=\ ]{0,5} - \b (r\.[A-Za-z0-9_-]{24,500}) (?: [^A-Za-z0-9_-] | $ ) + pattern_requirements: + min_digits: 2 examples: - 'VAULT_CLIENT_TOKEN="r.Z4bTMtngfLeQ18AqVoBBkUAOD1"' @@ -62,9 +68,10 @@ rules: pattern: | (?x) - \b (hvs\.[A-Za-z0-9]{24,130}) (?: [^A-Za-z0-9_-] | $ ) + pattern_requirements: + min_digits: 2 examples: - "apikey: hvs.JGbZZaCkOSgsZ56uhGlTK2zyC1j2mwhy0VLp4" @@ -79,9 +86,10 @@ rules: pattern: | (?x) - \b (hvb\.[A-Za-z0-9_-]{24,500}) (?: [^A-Za-z0-9_-] | $ ) + pattern_requirements: + min_digits: 2 examples: - "apikey: hvb.JGbZZaCkOSgsZ56uhGlTK2zyC1j2mwhy0VLp4" @@ -98,9 +106,10 @@ rules: pattern: | (?x) - \b (hvr\.[A-Za-z0-9]{24,130}) (?: [^A-Za-z0-9_-] | $ ) + pattern_requirements: + min_digits: 2 examples: - "apikey: hvr.JGbZZaCkOSgsZ56uhGlTK2zyC1j2mwhy0VLp4" @@ -119,9 +128,10 @@ rules: (?i: unseal ) \b .{1,10} - \b ([a-zA-Z0-9+/]{44}) (?: [^a-zA-Z0-9+/] | $ ) + pattern_requirements: + min_digits: 2 examples: - "Unseal Key 2: 0tZn+7QQCxphpHwTm7/dC3LpP5JGIbYl3PK8Sy81R+P2" diff --git a/data/rules/heroku.yml b/data/rules/heroku.yml index b06d58e..96e94e4 100644 --- a/data/rules/heroku.yml +++ b/data/rules/heroku.yml @@ -5,13 +5,15 @@ rules: (?xi) \b heroku - (?:.|[\n\r]){0,32}? + (?:.|[\n\r]){0,32}? \b ( [0-9a-f]{8}-[0-9a-f]{4}- [0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.0 confidence: medium examples: @@ -35,10 +37,11 @@ rules: id: kingfisher.heroku.2 pattern: | (?xi) - \b ( HRKU-[A-Z0-9_]{60} ) + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 4.0 validation: diff --git a/data/rules/hubspot.yml b/data/rules/hubspot.yml index 2840203..5cb5372 100644 --- a/data/rules/hubspot.yml +++ b/data/rules/hubspot.yml @@ -8,6 +8,8 @@ rules: pat-[a-z0-9]{2,3}-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} ) \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 3.0 validation: diff --git a/data/rules/huggingface.yml b/data/rules/huggingface.yml index d103438..c70b993 100644 --- a/data/rules/huggingface.yml +++ b/data/rules/huggingface.yml @@ -3,7 +3,6 @@ rules: id: kingfisher.huggingface.1 pattern: | (?xi) - \b (?: ( (?:api_org|hf)_ @@ -11,6 +10,8 @@ rules: ) ) \b + pattern_requirements: + min_digits: 2 references: - https://huggingface.co/docs/hub/security-tokens min_entropy: 3.3 diff --git a/data/rules/ibm.yml b/data/rules/ibm.yml index 55a33be..a2e7ec6 100644 --- a/data/rules/ibm.yml +++ b/data/rules/ibm.yml @@ -3,15 +3,16 @@ rules: id: kingfisher.ibm.1 pattern: | (?xi) - \b (?:ibm(?:cloud)?|bx) (?:.|[\n\r]){0,32}? (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) (?:.|[\n\r]){0,32}? - \b ( [0-9A-Z_-]{42,44} ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium diff --git a/data/rules/infracost.yml b/data/rules/infracost.yml index 598b6c3..42dc8d6 100644 --- a/data/rules/infracost.yml +++ b/data/rules/infracost.yml @@ -8,6 +8,8 @@ rules: ico-[a-z0-9]{32} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/intercom.yml b/data/rules/intercom.yml index e521759..d6f159e 100644 --- a/data/rules/intercom.yml +++ b/data/rules/intercom.yml @@ -7,9 +7,12 @@ rules: (?:.|[\n\r]){0,16}? (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) (?:.|[\n\r]){0,16}? + \b ( [0-9A-Z+/]{59}= ) + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium diff --git a/data/rules/ionic.yml b/data/rules/ionic.yml index 1130a38..b37b83b 100644 --- a/data/rules/ionic.yml +++ b/data/rules/ionic.yml @@ -7,8 +7,10 @@ rules: ( ion_ [a-z0-9]{42} - ) - \b + ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/ipstack.yml b/data/rules/ipstack.yml index a70e43e..1dbb576 100644 --- a/data/rules/ipstack.yml +++ b/data/rules/ipstack.yml @@ -13,6 +13,8 @@ rules: (?:[0-9a-f]{16}){2} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.0 confidence: medium examples: diff --git a/data/rules/jenkins.yml b/data/rules/jenkins.yml index f8fbb77..36a1d49 100644 --- a/data/rules/jenkins.yml +++ b/data/rules/jenkins.yml @@ -2,7 +2,8 @@ rules: - name: Jenkins Token or Crumb id: kingfisher.jenkins.1 pattern: '(?i)jenkins.{0,10}(?:crumb)?.{0,10}\b([0-9a-f]{32,36})\b' - categories: [api, fuzzy, secret] + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: @@ -17,8 +18,6 @@ rules: export JENKINS=jenkins-cicd.apps.sno.openshiftlabs.net - | sh "curl -X POST 'http://jenkins.lsfusion.luxsoft.by/job/${Paths.updateParentVersionsJob}/build' --user ${USERPASS} -H 'Jenkins-Crumb:440561953171ba44ace9740562d172bb'" - negative_examples: - - '1. ~~Does not play well with [Build Token Root Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Build+Token+Root+Plugin) URL formats.~~ (added with [this commit](https://github.com/morficus/Parameterized-Remote-Trigger-Plugin/commit/f687dbe75d1c4f39f7e14b68220890384d7c5674) )' references: - https://www.jenkins.io/blog/2018/07/02/new-api-token-system/ - https://www.jenkins.io/doc/book/security/csrf-protection/ \ No newline at end of file diff --git a/data/rules/jina.yml b/data/rules/jina.yml index efe5b10..807f5a7 100644 --- a/data/rules/jina.yml +++ b/data/rules/jina.yml @@ -4,8 +4,12 @@ rules: pattern: | (?x) \b - (jina_[a-zA-Z0-9]{60}) + ( + jina_[a-zA-Z0-9]{60} + ) \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 3.0 examples: diff --git a/data/rules/jira.yml b/data/rules/jira.yml index a555d85..2be3a53 100644 --- a/data/rules/jira.yml +++ b/data/rules/jira.yml @@ -2,11 +2,14 @@ rules: - name: Jira Domain id: kingfisher.jira.1 pattern: | - (?xi) + (?xi) + \b ( [a-z][a-z0-9-]{5,24}\.atlassian\.net ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 visible: false confidence: medium @@ -26,8 +29,12 @@ rules: \b ( [a-z0-9-]{24} - ) - \b + ) + \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/jwt.yml b/data/rules/jwt.yml index b237b4c..b39d991 100644 --- a/data/rules/jwt.yml +++ b/data/rules/jwt.yml @@ -3,7 +3,6 @@ rules: id: kingfisher.jwt.1 pattern: | (?x) - \b ( (?:ey|ewogIC)[A-Za-z0-9_-]{12,} (?# header ) \. @@ -11,7 +10,9 @@ rules: \. [A-Za-z0-9_-]{12,} (?# signature ) ) - (?:[^A-Z0-9_-]|$) (?# this instead of a \b anchor because that doesn't play nicely with `-` ) + (?:[^A-Z0-9_-]|$) + pattern_requirements: + min_digits: 4 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/kagi.yml b/data/rules/kagi.yml index 17732af..b1d311c 100644 --- a/data/rules/kagi.yml +++ b/data/rules/kagi.yml @@ -3,12 +3,12 @@ rules: id: kingfisher.kagi.1 pattern: | (?x)(?s) - \b (?: kagi | KAGI ) .{0,100} - \b ( [a-zA-Z0-9_-]{11}\.[a-zA-Z0-9_-]{43} ) (?: $ | [^a-zA-Z0-9_-] ) + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 3.0 references: diff --git a/data/rules/kickbox.yml b/data/rules/kickbox.yml index 35a4e38..897d25d 100644 --- a/data/rules/kickbox.yml +++ b/data/rules/kickbox.yml @@ -13,6 +13,8 @@ rules: [A-Z0-9_]+[A-Z0-9]{64} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/langchain.yml b/data/rules/langchain.yml index cd853e2..6f4da05 100644 --- a/data/rules/langchain.yml +++ b/data/rules/langchain.yml @@ -8,6 +8,8 @@ rules: lsv2_(?:pt)_[0-9a-f]{32}_[0-9a-f]{10} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 4.0 examples: - "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" @@ -34,6 +36,8 @@ rules: lsv2_sk_[0-9a-f]{32}_[0-9a-f]{10} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 4.0 examples: - "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" diff --git a/data/rules/launchdarkly.yml b/data/rules/launchdarkly.yml index f6d15d5..26a27d3 100644 --- a/data/rules/launchdarkly.yml +++ b/data/rules/launchdarkly.yml @@ -9,6 +9,8 @@ rules: ( [a-z0-9_\-=]{40} ) + pattern_requirements: + min_digits: 2 min_entropy: 3.2 confidence: medium examples: diff --git a/data/rules/line.yml b/data/rules/line.yml index c3b43dd..fc6ec4e 100644 --- a/data/rules/line.yml +++ b/data/rules/line.yml @@ -12,6 +12,8 @@ rules: ( (?:[0-9A-Z+/]{57}){3}=? ) + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/linear.yml b/data/rules/linear.yml index fdaa30d..3b73105 100644 --- a/data/rules/linear.yml +++ b/data/rules/linear.yml @@ -7,8 +7,10 @@ rules: ( lin_api_ (?:[0-9A-Z]{8}){5} - ) - \b + ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/linkedin.yml b/data/rules/linkedin.yml index 7663c28..cd293b7 100644 --- a/data/rules/linkedin.yml +++ b/data/rules/linkedin.yml @@ -10,6 +10,8 @@ rules: (?: id | identifier | key ) .{0,2} \s{0,20} .{0,2} \s{0,20} .{0,2} \b ([a-z0-9]{12,14}) \b + pattern_requirements: + min_digits: 2 references: - https://docs.microsoft.com/en-us/linkedin/shared/api-guide/best-practices/secure-applications min_entropy: 2.5 @@ -44,6 +46,8 @@ rules: (?: key | oauth | sec | secret )? .{0,2} \s{0,20} .{0,2} \s{0,20} .{0,2} \b ([a-z0-9]{16}) \b + pattern_requirements: + min_digits: 2 references: - https://docs.microsoft.com/en-us/linkedin/shared/api-guide/best-practices/secure-applications min_entropy: 3.3 diff --git a/data/rules/lob.yml b/data/rules/lob.yml index 152c445..deb8800 100644 --- a/data/rules/lob.yml +++ b/data/rules/lob.yml @@ -10,6 +10,8 @@ rules: (?:live|test)_[a-f0-9]{35} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: @@ -42,6 +44,8 @@ rules: (?:test|live)_pub_[a-f0-9]{31} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.0 confidence: medium examples: diff --git a/data/rules/mailchimp.yml b/data/rules/mailchimp.yml index ffa5d3a..c3f6962 100644 --- a/data/rules/mailchimp.yml +++ b/data/rules/mailchimp.yml @@ -13,6 +13,9 @@ rules: (?:[0-9a-f]{8}){4} -us\d{1,2} ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/mailgun.yml b/data/rules/mailgun.yml index 06a02c2..5181f3b 100644 --- a/data/rules/mailgun.yml +++ b/data/rules/mailgun.yml @@ -11,7 +11,11 @@ rules: \b ( (?:[0-9A-Z-]{24}){3} - ) + ) + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.5 confidence: medium examples: @@ -41,6 +45,8 @@ rules: key-(?:[0-9a-f]{8}){4} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/mandrill.yml b/data/rules/mandrill.yml index 4abd63d..857fbeb 100644 --- a/data/rules/mandrill.yml +++ b/data/rules/mandrill.yml @@ -11,7 +11,11 @@ rules: \b ( (?:[0-9A-Z_-]{11}){2} - ) + ) + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/mapbox.yml b/data/rules/mapbox.yml index d0253d6..ecbfa29 100644 --- a/data/rules/mapbox.yml +++ b/data/rules/mapbox.yml @@ -2,6 +2,8 @@ rules: - name: Mapbox Public Access Token id: kingfisher.mapbox.1 pattern: '(?i)(?s)mapbox.{0,30}(pk\.[a-z0-9\-+/=]{32,128}\.[a-z0-9\-+/=]{20,30})(?:[^a-z0-9\-+/=]|$)' + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: @@ -27,6 +29,8 @@ rules: - name: Mapbox Secret Access Token id: kingfisher.mapbox.2 pattern: '(?i)(?s)mapbox.{0,30}(sk\.[a-z0-9\-+/=]{32,128}\.[a-z0-9\-+/=]{20,30})(?:[^a-z0-9\-+/=]|$)' + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: @@ -51,6 +55,8 @@ rules: - name: Mapbox Temporary Access Token id: kingfisher.mapbox.3 pattern: '(?i)(?s)mapbox.{0,30}(tk\.[a-z0-9\-+/=]{32,128}\.[a-z0-9\-+/=]{20,30})(?:[^a-z0-9\-+/=]|$)' + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/mattermost.yml b/data/rules/mattermost.yml index 564adb6..ef69c78 100644 --- a/data/rules/mattermost.yml +++ b/data/rules/mattermost.yml @@ -34,6 +34,8 @@ rules: [A-Z0-9]{26} ) \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 4.0 examples: diff --git a/data/rules/maxmind.yml b/data/rules/maxmind.yml index c0839b8..9952118 100644 --- a/data/rules/maxmind.yml +++ b/data/rules/maxmind.yml @@ -8,6 +8,8 @@ rules: [a-z0-9]{6}_[a-z0-9]{29}_mmk ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.8 confidence: medium examples: @@ -42,11 +44,9 @@ rules: (?:.|[\n\r]){0,10}? (?:id|number) (?:.|[\n\r]){0,16}? - \b ( \d{4,8} ) - \b min_entropy: 2.0 confidence: medium visible: false diff --git a/data/rules/messagebird.yml b/data/rules/messagebird.yml index 8ae1a58..4b89531 100644 --- a/data/rules/messagebird.yml +++ b/data/rules/messagebird.yml @@ -6,10 +6,13 @@ rules: \b message[_-]?bird (?:.|[\n\r]){0,32}? + \b ( [a-z0-9]{25} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.4 confidence: medium examples: diff --git a/data/rules/microsoft_teams.yml b/data/rules/microsoft_teams.yml index 37e4030..1f7ac49 100644 --- a/data/rules/microsoft_teams.yml +++ b/data/rules/microsoft_teams.yml @@ -26,6 +26,8 @@ rules: [0-9a-f]{4}- [0-9a-f]{12} ) + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/microsoftteamswebhook.yml b/data/rules/microsoftteamswebhook.yml index 4da1c1d..952f1b9 100644 --- a/data/rules/microsoftteamswebhook.yml +++ b/data/rules/microsoftteamswebhook.yml @@ -3,17 +3,23 @@ rules: id: kingfisher.microsoftteamswebhook.1 pattern: | (?xi) - https://[A-Z0-9]+\.webhook\.office\.com/webhookb2 - / - [A-Z0-9]{8}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{12} - @ - [A-Z0-9]{8}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{12} - / - IncomingWebhook - / - [A-Z0-9]{32} - / - [A-Z0-9]{8}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{12} + \b + ( + https://[A-Z0-9]+\.webhook\.office\.com/webhookb2 + / + [A-Z0-9]{8}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{12} + @ + [A-Z0-9]{8}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{12} + / + IncomingWebhook + / + [A-Z0-9]{32} + / + [A-Z0-9]{8}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{12} + ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/mistral.yml b/data/rules/mistral.yml index 07b1af8..3e451da 100644 --- a/data/rules/mistral.yml +++ b/data/rules/mistral.yml @@ -13,6 +13,8 @@ rules: [A-Z0-9]{32} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.0 confidence: medium examples: diff --git a/data/rules/mongodb.yml b/data/rules/mongodb.yml index dc02e94..28b4031 100644 --- a/data/rules/mongodb.yml +++ b/data/rules/mongodb.yml @@ -11,6 +11,7 @@ rules: .{0,1000}? (?:private|priv|secret|auth|pass|key) (?:.|[\n\r]){0,32}? + \b ( [a-fA-F0-9]{8} - @@ -21,7 +22,12 @@ rules: [a-fA-F0-9]{4} - [a-fA-F0-9]{12} - ) + ) + \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.7 examples: - ATLAS_PRIVATE_KEY=4b18315e-6b7d-4337-b449-5d38f5a189ec @@ -90,7 +96,6 @@ rules: ( mdb_sa_sk_[0-9A-Z_-]{6}[0-9A-Z]{34} ) - \b min_entropy: 3.5 examples: - mdb_sa_sk_BdIX_jLzut2WTgglKzKvSgWMDDj5hEoTqdwOyLOL diff --git a/data/rules/nasa.yml b/data/rules/nasa.yml index efbcc42..1509b2e 100644 --- a/data/rules/nasa.yml +++ b/data/rules/nasa.yml @@ -8,10 +8,13 @@ rules: (?:.|[\n\r]){0,32}? (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) (?:.|[\n\r]){0,32}? + \b ( [A-Z0-9]{40} ) \b + pattern_requirements: + min_digits: 2 examples: - | get('https://api.nasa.gov/planetary/earth/imagery?api_key=fWfSMcDzyHfMuH8BW6jiIUBYaj0hKRyKBRTBqgEQ') diff --git a/data/rules/netlify.yml b/data/rules/netlify.yml index 0a29d25..7fae1eb 100644 --- a/data/rules/netlify.yml +++ b/data/rules/netlify.yml @@ -8,8 +8,12 @@ rules: (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) (?:.|[\n\r]){0,32}? \b - ([a-f0-9]{60,64}) + ( + [a-f0-9]{60,64} + ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 examples: - netlify_token=3cdfad7b885a6daceff3fb820389115750b373763fb30b10ca0382648b55872d @@ -41,6 +45,8 @@ rules: [A-Z0-9_-]{43,45} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/newrelic.yml b/data/rules/newrelic.yml index d9a582c..c208aa0 100644 --- a/data/rules/newrelic.yml +++ b/data/rules/newrelic.yml @@ -14,6 +14,9 @@ rules: - [A-Z0-9_.]{42} ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/ngrok.yml b/data/rules/ngrok.yml index 56f1b62..951cfd5 100644 --- a/data/rules/ngrok.yml +++ b/data/rules/ngrok.yml @@ -7,7 +7,6 @@ rules: (?:.|[\\n\r]){0,32}? (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) (?:.|[\n\r]){0,32}? - \b (?:[a-z0-9]{25,30}_\d[a-z0-9]{20}|(?:cr_|ak_)[a-z0-9]{25,30}) \b min_entropy: 4 diff --git a/data/rules/notion.yml b/data/rules/notion.yml index 642128e..2682c8c 100644 --- a/data/rules/notion.yml +++ b/data/rules/notion.yml @@ -10,6 +10,8 @@ rules: secret_[A-Z0-9]{43} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 4.0 confidence: medium examples: @@ -38,11 +40,9 @@ rules: (?xi) notion (?:.|[\\n\r]){0,32}? - \b ( ntn_[A-Z0-9]{40,55} ) - \b min_entropy: 4.0 confidence: medium references: @@ -74,11 +74,9 @@ rules: (?xi) notion (?:.|[\\n\r]){0,32}? - \b ( nrt_[A-Z0-9_]{40,55} ) - \b min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/npm.yml b/data/rules/npm.yml index 5d2e8c8..e275e14 100644 --- a/data/rules/npm.yml +++ b/data/rules/npm.yml @@ -8,6 +8,8 @@ rules: npm_[A-Z0-9]{36} ) \b + pattern_requirements: + min_digits: 2 references: - https://docs.npmjs.com/about-access-tokens - https://github.com/github/roadmap/issues/557 @@ -35,7 +37,6 @@ rules: id: kingfisher.npm.2 pattern: | (?xi) - \b (?:_authToken|NPM_TOKEN) (?:.|[\n\r]){0,16}? ( diff --git a/data/rules/nuget.yml b/data/rules/nuget.yml index 663a415..3ba909e 100644 --- a/data/rules/nuget.yml +++ b/data/rules/nuget.yml @@ -8,6 +8,8 @@ rules: oy2[a-z0-9]{43} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: @@ -40,11 +42,9 @@ rules: (?:.|[\n\r]){0,32}? (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) (?:.|[\n\r]){0,32}? - \b ( [a-z0-9]{46} ) - \b min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/nvidia.yml b/data/rules/nvidia.yml index 1dc7b31..3143a80 100644 --- a/data/rules/nvidia.yml +++ b/data/rules/nvidia.yml @@ -8,6 +8,8 @@ rules: nvapi-[A-Z0-9_-]{60,70} ) \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 3.5 examples: diff --git a/data/rules/nytimes.yml b/data/rules/nytimes.yml index 3c0d08a..391dd3f 100644 --- a/data/rules/nytimes.yml +++ b/data/rules/nytimes.yml @@ -10,6 +10,8 @@ rules: [a-z0-9_\-=]{32} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.2 confidence: medium examples: diff --git a/data/rules/okta.yml b/data/rules/okta.yml index 65490b4..16511f4 100644 --- a/data/rules/okta.yml +++ b/data/rules/okta.yml @@ -10,6 +10,9 @@ rules: ( 00[a-z0-9_-]{39}[a-z0-9_] ) + \b + pattern_requirements: + min_digits: 4 min_entropy: 3.3 examples: - okta_api_token=00hqNORUpnTcdFWA5WEM4YwOkw6RXeFw21lFDRKmY1 @@ -44,7 +47,6 @@ rules: id: kingfisher.okta.2 pattern: | (?xi) - \b ( [a-z0-9-]{1,40}\.okta(?:preview|-emea)?\.com ) diff --git a/data/rules/ollama.yml b/data/rules/ollama.yml index a2df4ab..ba686c6 100644 --- a/data/rules/ollama.yml +++ b/data/rules/ollama.yml @@ -10,6 +10,8 @@ rules: ( [a-f0-9]{32}\.[a-zA-Z0-9_-]{24} ) + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 3.5 validation: diff --git a/data/rules/onepassword.yml b/data/rules/onepassword.yml index b7cc0bc..e7f6183 100644 --- a/data/rules/onepassword.yml +++ b/data/rules/onepassword.yml @@ -6,7 +6,10 @@ rules: \b ( ops_eyj[A-Za-z0-9_-]{80,500} - )\b + ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 4.0 confidence: medium examples: @@ -37,11 +40,11 @@ rules: id: kingfisher.1password.2 pattern: | (?xi) - \b ( A[0-9]-[A-Z0-9]{6}-[A-Z0-9]{6}-[A-Z0-9]{5}(?:-[A-Z0-9]{5}){3} ) - \b + pattern_requirements: + min_digits: 2 min_entropy: 3.8 confidence: medium examples: diff --git a/data/rules/openai.yml b/data/rules/openai.yml index d0b01cb..b6f90e0 100644 --- a/data/rules/openai.yml +++ b/data/rules/openai.yml @@ -8,6 +8,8 @@ rules: sk-[A-Z0-9]{48} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: @@ -38,6 +40,8 @@ rules: (sk-(?:proj|svcacct|None)-[A-Z0-9_-]{100,}) ) \b + pattern_requirements: + min_digits: 2 min_entropy: 4.0 confidence: medium examples: diff --git a/data/rules/openweathermap.yml b/data/rules/openweathermap.yml index c6b0251..b3fa549 100644 --- a/data/rules/openweathermap.yml +++ b/data/rules/openweathermap.yml @@ -6,7 +6,6 @@ rules: id: kingfisher.openweather.1 pattern: | (?xi) - \b (?:pyowm|openweather|owm\b) (?:.|[\n\r]){0,64}? \b @@ -17,6 +16,8 @@ rules: [a-z0-9]{32} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/opsgenie.yml b/data/rules/opsgenie.yml index 012f296..0e1c620 100644 --- a/data/rules/opsgenie.yml +++ b/data/rules/opsgenie.yml @@ -12,6 +12,9 @@ rules: ( [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 examples: - opsgenie_api_key = '12345678-9abc-def0-1234-56789abcdef0' diff --git a/data/rules/pagerdutyapikey.yml b/data/rules/pagerdutyapikey.yml index b0a3c9b..7bdf1f0 100644 --- a/data/rules/pagerdutyapikey.yml +++ b/data/rules/pagerdutyapikey.yml @@ -3,7 +3,6 @@ rules: id: kingfisher.pagerduty.1 pattern: | (?xi) - \b (?: pd[_-]? | pagerduty[_-]? | @@ -19,6 +18,8 @@ rules: [a-f0-9]{32} # integration / routing key (32 hex, lower case) ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/particle.io.yml b/data/rules/particle.io.yml index c4fdfaf..eb8dd6b 100644 --- a/data/rules/particle.io.yml +++ b/data/rules/particle.io.yml @@ -5,9 +5,12 @@ rules: (?xi) https://api\.particle\.io/v1/[A-Z0-9_\-\s/"\\?]* (?:access_token=|Authorization:\s*Bearer\s*) + ( + [A-Z0-9]{40} + ) \b - ([A-Z0-9]{40}) - \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: @@ -42,7 +45,6 @@ rules: pattern: | (?xi) (?:access_token=|Authorization:\s*Bearer\s*) - \b ([A-Z0-9]{40}) \b [\s"\\]*https://api\.particle\.io/v1 diff --git a/data/rules/pastebin.yml b/data/rules/pastebin.yml index 1ae302e..f19536c 100644 --- a/data/rules/pastebin.yml +++ b/data/rules/pastebin.yml @@ -13,6 +13,8 @@ rules: [A-Z0-9_]{32} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/paypal.yml b/data/rules/paypal.yml index ef65d2d..47fddb1 100644 --- a/data/rules/paypal.yml +++ b/data/rules/paypal.yml @@ -1,56 +1,59 @@ rules: -- name: PayPal OAuth Client ID - id: kingfisher.paypal.1 - pattern: | - (?xi) - paypal - (?:.|[\n\r]){0,8}? - (?:CLIENT|ID|USER) - (?:.|[\n\r]){0,16}? - \b - ( - A[A-Z0-9_-]{78,99} - ) - \b - min_entropy: 3.5 - visible: false - examples: - - paypal_client_id=AZJ6y8Dpr1TYbqAIdhkPzyhjXoY6mIdhkPzyhjXoY6m8GplL7C3zZ3lPrkTIdhkPzyhjXo_Dx3IdhkPzyhjXoY6m + - name: PayPal OAuth Client ID + id: kingfisher.paypal.1 + pattern: | + (?xi) + paypal + (?:.|[\n\r]){0,8}? + (?:CLIENT|ID|USER) + (?:.|[\n\r]){0,16}? + \b + ( + A[A-Z0-9_-]{78,99} + ) + pattern_requirements: + min_digits: 2 + min_entropy: 3.5 + visible: false + examples: + - paypal_client_id=AZJ6y8Dpr1TYbqAIdhkPzyhjXoY6mIdhkPzyhjXoY6m8GplL7C3zZ3lPrkTIdhkPzyhjXo_Dx3IdhkPzyhjXoY6m -- name: PayPal OAuth Secret - id: kingfisher.paypal.2 - pattern: | - (?xi) - paypal - (?:.|[\n\r]){0,16}? - (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) - (?:.|[\n\r]){0,32}? - \b - ( - [A-Z0-9_.-]{78,120} - ) - \b - min_entropy: 3.5 - examples: - - paypal_secret=EP0uwUsACKVPcbDRaXFYerX2ij6nbsha71cSdynuQWoSt1pIy4qtIs7gJQRmHwKXu5Icv3g1YQZzAywf + - name: PayPal OAuth Secret + id: kingfisher.paypal.2 + pattern: | + (?xi) + paypal + (?:.|[\n\r]){0,16}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) + (?:.|[\n\r]){0,32}? + \b + ( + [A-Z0-9_.-]{78,120} + ) + \b + pattern_requirements: + min_digits: 2 + min_entropy: 3.5 + examples: + - paypal_secret=EP0uwUsACKVPcbDRaXFYerX2ij6nbsha71cSdynuQWoSt1pIy4qtIs7gJQRmHwKXu5Icv3g1YQZzAywf - validation: - type: Http - content: - request: - method: POST - url: https://api-m.paypal.com/v1/oauth2/token - headers: - Accept: application/json - Accept-Language: en_US - Content-Type: application/x-www-form-urlencoded - Authorization: | - Basic {{ CLIENTID | append: ':' | append: TOKEN | b64enc }} - body: grant_type=client_credentials - response_matcher: - - report_response: true - - type: StatusMatch - status: [200] - depends_on_rule: - - rule_id: kingfisher.paypal.1 - variable: CLIENTID + validation: + type: Http + content: + request: + method: POST + url: https://api-m.paypal.com/v1/oauth2/token + headers: + Accept: application/json + Accept-Language: en_US + Content-Type: application/x-www-form-urlencoded + Authorization: | + Basic {{ CLIENTID | append: ':' | append: TOKEN | b64enc }} + body: grant_type=client_credentials + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + depends_on_rule: + - rule_id: kingfisher.paypal.1 + variable: CLIENTID diff --git a/data/rules/pem.yml b/data/rules/pem.yml index 00d93c6..0c0d921 100644 --- a/data/rules/pem.yml +++ b/data/rules/pem.yml @@ -8,6 +8,8 @@ rules: ( (?: [a-zA-Z0-9+/=\s"',] | \\r | \\n ) {50,} ) \s* -----END\ .{0,20}\ ?PRIVATE\ KEY\ ?.{0,20}----- + pattern_requirements: + min_digits: 4 min_entropy: 4.5 confidence: high examples: @@ -60,6 +62,8 @@ rules: [a-zA-Z0-9+/=]{50,} ) (?: [^a-zA-Z0-9+/=] | $ ) + pattern_requirements: + min_digits: 4 min_entropy: 4.5 confidence: high examples: diff --git a/data/rules/perplexity.yml b/data/rules/perplexity.yml index 6629372..c9ba476 100644 --- a/data/rules/perplexity.yml +++ b/data/rules/perplexity.yml @@ -8,6 +8,8 @@ rules: pplx-[A-Za-z0-9]{48} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.8 confidence: medium examples: diff --git a/data/rules/planetscale.yml b/data/rules/planetscale.yml index ecbee4f..859531b 100644 --- a/data/rules/planetscale.yml +++ b/data/rules/planetscale.yml @@ -8,6 +8,8 @@ rules: pscale_tkn_[a-z0-9-_]{43} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 4 examples: - pscale_tkn_abcdefghijklmnopqrstuvwxyZ1234567890_ABCDEF @@ -41,11 +43,11 @@ rules: (?:.|[\n\r]){0,16}? (?:USER|ID|NAME) (?:.|[\n\r]){0,16}? - \b ( [a-z0-9]{12} ) - \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 visible: false examples: diff --git a/data/rules/postman.yml b/data/rules/postman.yml index ae7ae7c..8b98b2e 100644 --- a/data/rules/postman.yml +++ b/data/rules/postman.yml @@ -8,6 +8,8 @@ rules: PMAK-[A-Z0-9]{24}-[A-Z0-9]{34} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/postmark.yml b/data/rules/postmark.yml index 6e31071..f48aa57 100644 --- a/data/rules/postmark.yml +++ b/data/rules/postmark.yml @@ -10,6 +10,8 @@ rules: [a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12} ) \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 3.0 examples: diff --git a/data/rules/prefect.yml b/data/rules/prefect.yml index c04c9cb..beba175 100644 --- a/data/rules/prefect.yml +++ b/data/rules/prefect.yml @@ -8,6 +8,8 @@ rules: pnu_[a-z0-9]{36} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.0 confidence: medium examples: diff --git a/data/rules/privkey.yml b/data/rules/privkey.yml index 7b5e551..a936514 100644 --- a/data/rules/privkey.yml +++ b/data/rules/privkey.yml @@ -22,6 +22,8 @@ rules: PRIVATE\sKEY (\sBLOCK)? ----- + pattern_requirements: + min_digits: 2 min_entropy: 4.5 confidence: high examples: @@ -73,7 +75,11 @@ rules: PRIVATE\sKEY (\sBLOCK)? ----- - ) + ) + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 4.5 confidence: high examples: diff --git a/data/rules/psexec.yml b/data/rules/psexec.yml index 57cfd66..3cca3d3 100644 --- a/data/rules/psexec.yml +++ b/data/rules/psexec.yml @@ -8,7 +8,6 @@ rules: -p \s* (\S+) (?# password ) min_entropy: 3.3 confidence: medium - categories: [fuzzy, secret] examples: - 'cmd.exe /C PSEXEC \\10.0.94.120 -u Administrator -p dev_admin CMD /C ECHO' - 'PSEXEC.EXE \\LocalComputerIPAddress -u DOMAIN\my-user -p mypass CMD' diff --git a/data/rules/pubnub.yml b/data/rules/pubnub.yml index f29310a..f759ed7 100644 --- a/data/rules/pubnub.yml +++ b/data/rules/pubnub.yml @@ -8,6 +8,8 @@ rules: pub-c-[a-z0-9]{8}(?:-[a-z0-9]{4}){3}-[a-z0-9]{12} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 examples: - pub-c-12345678-1234-1234-1234-123456789012 @@ -34,6 +36,8 @@ rules: sub-c-[a-z0-9]{8}(?:-[a-z0-9]{4}){3}-[a-z0-9]{12} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/pulumi.yml b/data/rules/pulumi.yml index 2298d1d..81980a1 100644 --- a/data/rules/pulumi.yml +++ b/data/rules/pulumi.yml @@ -8,6 +8,8 @@ rules: pul-[a-f0-9]{40} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 examples: - pul-18e13e3eebebeb94eac318d421ca8ecc5ca78d5f diff --git a/data/rules/pypi.yml b/data/rules/pypi.yml index 85884ed..dd11dd4 100644 --- a/data/rules/pypi.yml +++ b/data/rules/pypi.yml @@ -8,6 +8,8 @@ rules: pypi-AgEIcHlwaS5vcmc[A-Z0-9_-]{50,} ) (?:[^A-Z0-9_-]|$) + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/rabbitmq.yml b/data/rules/rabbitmq.yml index 953f10e..607d5f6 100644 --- a/data/rules/rabbitmq.yml +++ b/data/rules/rabbitmq.yml @@ -3,7 +3,6 @@ rules: id: kingfisher.rabbitmq.1 pattern: | (?xi) - \b (?: amqps? ) @@ -16,6 +15,8 @@ rules: @ [-.%\w\/:]+ \b + pattern_requirements: + min_special_chars: 1 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/react.yml b/data/rules/react.yml index c7d5a40..de22892 100644 --- a/data/rules/react.yml +++ b/data/rules/react.yml @@ -18,9 +18,6 @@ rules: - 'REACT_APP_AUTH_USERNAME=bowie' - ' REACT_APP_AUTH_USERNAME=bowie # some comment' - 'REACT_APP_MAILER_USERNAME=smtp_username # Enter your SMTP email username' - negative_examples: - - 'REACT_APP_FRONTEND_LOGIN_FORGOT_USERNAME=$REACT_APP_MATRIX_BASE_URL/classroom/#/forgot_username' - categories: [fuzzy, identifier] references: - https://create-react-app.dev/docs/adding-custom-environment-variables/ - https://stackoverflow.com/questions/48699820/how-do-i-hide-an-api-key-in-create-react-app @@ -44,10 +41,6 @@ rules: - 'REACT_APP_AUTH_PASSWORD=whiteduke' - ' REACT_APP_AUTH_PASSWORD=whiteduke # some comment' - 'REACT_APP_MAILER_PASSWORD=smtp_password # Enter your SMTP email password' - negative_examples: - - ' const password = process.env.REACT_APP_FIREBASE_DEV_PASSWORD || "not-set"' - - 'REACT_APP_FRONTEND_LOGIN_FORGOT_PASSWORD=$REACT_APP_MATRIX_BASE_URL/classroom/#/forgot_password' - categories: [fuzzy, secret] references: - https://create-react-app.dev/docs/adding-custom-environment-variables/ - https://stackoverflow.com/questions/48699820/how-do-i-hide-an-api-key-in-create-react-app \ No newline at end of file diff --git a/data/rules/readme.yml b/data/rules/readme.yml index 0e415ec..6a4b95d 100644 --- a/data/rules/readme.yml +++ b/data/rules/readme.yml @@ -2,11 +2,14 @@ rules: - name: ReadMe API Key id: kingfisher.readme.1 pattern: | - (?x)(?i) + (?xi) \b ( rdme_(?P[a-z0-9]{70}) ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/recaptcha.yml b/data/rules/recaptcha.yml index e8f62a6..f13db51 100644 --- a/data/rules/recaptcha.yml +++ b/data/rules/recaptcha.yml @@ -9,6 +9,9 @@ rules: ( 6l[c-f][a-z0-9_-].{36} ) + \b + pattern_requirements: + min_digits: 3 min_entropy: 3 confidence: medium examples: diff --git a/data/rules/replicate.yml b/data/rules/replicate.yml index b5f1a47..6eb6ffd 100644 --- a/data/rules/replicate.yml +++ b/data/rules/replicate.yml @@ -2,13 +2,15 @@ rules: - name: Replicate API Token id: kingfisher.replicate.1 pattern: | - (?x) - \b + (?x) + \b ( r8_ [A-Za-z0-9]{37} ) \b + pattern_requirements: + min_digits: 3 min_entropy: 3.0 confidence: medium examples: diff --git a/data/rules/rubygems.yml b/data/rules/rubygems.yml index 93ace54..bb9487c 100644 --- a/data/rules/rubygems.yml +++ b/data/rules/rubygems.yml @@ -8,8 +8,10 @@ rules: ( rubygems_ [a-z0-9]{42,52} - ) - \b + ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium categories: [api, secret] diff --git a/data/rules/runway.yml b/data/rules/runway.yml index 9c816b2..8e899f7 100644 --- a/data/rules/runway.yml +++ b/data/rules/runway.yml @@ -2,13 +2,15 @@ rules: - name: Runway API Key id: kingfisher.runway.1 pattern: | - (?x) + (?x) \b ( key_ [A-Fa-f0-9]{128} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 4.0 confidence: medium examples: diff --git a/data/rules/salesforce.yml b/data/rules/salesforce.yml index d532346..be3b544 100644 --- a/data/rules/salesforce.yml +++ b/data/rules/salesforce.yml @@ -2,7 +2,7 @@ rules: - name: Salesforce Access / Refresh Token id: kingfisher.salesforce.1 pattern: | - (?xi) + (?xi) \b ( 00 @@ -10,6 +10,8 @@ rules: ! [A-Z0-9._-]{90,120} ) + pattern_requirements: + min_digits: 6 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/sauce.yml b/data/rules/sauce.yml index 6c8be24..009f33a 100644 --- a/data/rules/sauce.yml +++ b/data/rules/sauce.yml @@ -25,7 +25,6 @@ rules: id: kingfisher.saucelabs.2 pattern: | (?xi) - \b ( (?:api|ondemand)\.(?:us|eu)-(?:west|east|central)-[0-9]\.saucelabs\.com ) @@ -47,11 +46,12 @@ rules: (?:.|[\n\r]){0,32}? (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) (?:.|[\n\r]){0,32}? - \b ( [a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12} ) \b + pattern_requirements: + min_digits: 4 confidence: medium min_entropy: 3.0 depends_on_rule: diff --git a/data/rules/scale.yml b/data/rules/scale.yml index b0d9b90..81148f2 100644 --- a/data/rules/scale.yml +++ b/data/rules/scale.yml @@ -4,11 +4,13 @@ rules: pattern: | (?x) \b - ( # capture => TOKEN - live_ # live-mode prefix per docs - [0-9a-f]{32} # 32 lowercase hex chars + ( + live_ + [0-9a-f]{32} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.1 confidence: medium examples: @@ -50,6 +52,8 @@ rules: [0-9a-f]{32} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.1 confidence: medium examples: diff --git a/data/rules/scalingo.yml b/data/rules/scalingo.yml index ea39b5a..15351c4 100644 --- a/data/rules/scalingo.yml +++ b/data/rules/scalingo.yml @@ -7,7 +7,8 @@ rules: ( tk-us-[\w-]{48} ) - \b + pattern_requirements: + min_digits: 2 min_entropy: 3.0 confidence: medium examples: diff --git a/data/rules/segment.yml b/data/rules/segment.yml index 1a2518f..234955d 100644 --- a/data/rules/segment.yml +++ b/data/rules/segment.yml @@ -8,6 +8,8 @@ rules: sgp_[A-Z0-9_-]{60,70} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: @@ -33,7 +35,6 @@ rules: id: kingfisher.segment.2 pattern: | (?xi) - \b (?:segment|sgmt) (?:.|[\n\r]){0,16}? (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) @@ -42,7 +43,8 @@ rules: ( [A-Z0-9_-]{40,50}\.[A-Z0-9_-]{40,50} ) - \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/sendbird.yml b/data/rules/sendbird.yml index 9c36a46..d82ec94 100644 --- a/data/rules/sendbird.yml +++ b/data/rules/sendbird.yml @@ -12,6 +12,8 @@ rules: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} ) \b + pattern_requirements: + min_digits: 2 confidence: medium visible: false min_entropy: 3.0 @@ -31,6 +33,8 @@ rules: [a-f0-9]{40} ) \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 4.0 examples: diff --git a/data/rules/sendgrid.yml b/data/rules/sendgrid.yml index 89145fc..96c5bff 100644 --- a/data/rules/sendgrid.yml +++ b/data/rules/sendgrid.yml @@ -11,7 +11,8 @@ rules: \. [0-9A-Z_-]{39,47} ) - \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/sendinblue.yml b/data/rules/sendinblue.yml index 9b53d07..f57a613 100644 --- a/data/rules/sendinblue.yml +++ b/data/rules/sendinblue.yml @@ -8,6 +8,8 @@ rules: xkeysib-[a-f0-9]{64}-[a-z0-9]{16} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.2 confidence: medium examples: diff --git a/data/rules/sentry.yml b/data/rules/sentry.yml index 8eebda8..8d424ba 100644 --- a/data/rules/sentry.yml +++ b/data/rules/sentry.yml @@ -11,6 +11,8 @@ rules: [a-f0-9]{64} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: @@ -41,6 +43,9 @@ rules: ( sntrys_eyJpYXQiO[a-zA-Z0-9+/]{10,200}(?:LCJyZWdpb25fdXJs|InJlZ2lvbl91cmwi|cmVnaW9uX3VybCI6)[a-zA-Z0-9+/]{10,200}={0,2}_[a-zA-Z0-9+/]{43} ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 4.2 confidence: medium examples: @@ -72,6 +77,8 @@ rules: sntryu_[a-f0-9]{64} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/shippo.yml b/data/rules/shippo.yml index cd769e2..e1bae07 100644 --- a/data/rules/shippo.yml +++ b/data/rules/shippo.yml @@ -8,6 +8,8 @@ rules: shippo_(?:live|test)_[a-f0-9]{40} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/shodan.yml b/data/rules/shodan.yml index 99ab150..76f946c 100644 --- a/data/rules/shodan.yml +++ b/data/rules/shodan.yml @@ -13,6 +13,8 @@ rules: [A-Z0-9]{32} ) \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 4.0 validation: diff --git a/data/rules/shopify.yml b/data/rules/shopify.yml index da340e5..bb92ea4 100644 --- a/data/rules/shopify.yml +++ b/data/rules/shopify.yml @@ -8,6 +8,8 @@ rules: (?:shpat|shpca|shppa|shpss)_[a-f0-9]{30,34} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 examples: - 'shopify_app_secret: "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"' diff --git a/data/rules/slack.yml b/data/rules/slack.yml index 9544d10..0e61776 100644 --- a/data/rules/slack.yml +++ b/data/rules/slack.yml @@ -15,6 +15,8 @@ rules: [0-9a-z]{10,66} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 examples: - xapp-1-A05V64V7F2B-5062360157732-9f01726eebe77df2c096a65e95acdd02107b2c1e92ca341cff27ca271b7251b4 @@ -55,7 +57,10 @@ rules: ( xoxe-\d- [A-Z0-9]{140,150} - )\b + ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 examples: - xoxb-853BAAEE-1B2eDb6A4c75-01bB6Da1CE3E98f6fED5AeC07Dc3E94C @@ -89,7 +94,8 @@ rules: B[a-z0-9_-]{8,12}/ [a-z0-9_-]{20,30} ) - \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 examples: - https://hooks.slack.com/services/TY40v9sZ9/BxIqhIXIi/NGUyXK6nK7HMAqd0ASzXluoV diff --git a/data/rules/snyk.yml b/data/rules/snyk.yml index e6237e3..3ba783f 100644 --- a/data/rules/snyk.yml +++ b/data/rules/snyk.yml @@ -8,10 +8,12 @@ rules: (?:.|[\n\r]){0,32}? (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) (?:.|[\n\r]){0,32}? - \b ( [A-Z0-9]{8}-(?:[A-Z0-9]{4}-){3}[A-Z0-9]{12} ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 examples: - snyk_token = 123e4567-e89b-12d3-a456-426614174000 diff --git a/data/rules/sonarcloud.yml b/data/rules/sonarcloud.yml index f0b874d..c3307e9 100644 --- a/data/rules/sonarcloud.yml +++ b/data/rules/sonarcloud.yml @@ -13,6 +13,8 @@ rules: [0-9a-z]{40} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 2.5 examples: - sonar_api_token=abcdef0123456789abcdef0123456789abcdef23 diff --git a/data/rules/sonarqube.yml b/data/rules/sonarqube.yml index ceddbee..63be8fe 100644 --- a/data/rules/sonarqube.yml +++ b/data/rules/sonarqube.yml @@ -8,6 +8,9 @@ rules: (?:sq[pua]) _[a-z0-9]{40} ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 examples: - sonar.login=sqp_4b78f8494075e310d62dfdcaeb14be2c78fca2fc @@ -35,11 +38,9 @@ rules: (?xi) sonar.{0,8}host (?:.|[\n\r]){0,64}? - \b ( https?://.*?:\d{2,6} ) - \b min_entropy: 3.5 visible: false examples: diff --git a/data/rules/sourcegraph.yml b/data/rules/sourcegraph.yml index 3aed539..cbda95d 100644 --- a/data/rules/sourcegraph.yml +++ b/data/rules/sourcegraph.yml @@ -4,8 +4,12 @@ rules: pattern: | (?xi) \b - sgp_(?:[a-f0-9]{16}_local_)?[a-f0-9]{40} + ( + sgp_(?:[a-f0-9]{16}_local_)?[a-f0-9]{40} + ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 examples: - sgp_210f1131b08e93adcfc3f05faa2d768ff883a61f @@ -41,6 +45,8 @@ rules: (?:sgp_(?:[a-f0-9]{16}_local_)?[a-f0-9]{40}|[a-f0-9]{40}) ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/square.yml b/data/rules/square.yml index d3fd851..c4aa62f 100644 --- a/data/rules/square.yml +++ b/data/rules/square.yml @@ -10,6 +10,9 @@ rules: ( EAAA[a-z0-9\-\+=]{60} ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: @@ -33,7 +36,15 @@ rules: - name: Square Access Token id: kingfisher.square.2 - pattern: '(?i)\b(sq0atp-[a-z0-9_-]{22})\b' + pattern: | + (?xi) + \b + ( + sq0atp-[a-z0-9_-]{22} + ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: @@ -57,7 +68,15 @@ rules: - name: Square OAuth Secret id: kingfisher.square.3 - pattern: '(?i)\b(sq0csp-[a-z0-9_-]{43})\b' + pattern: | + (?xi) + \b + ( + sq0csp-[a-z0-9_-]{43} + ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/stabilityai.yml b/data/rules/stabilityai.yml index 1ac8fd1..8848ce2 100644 --- a/data/rules/stabilityai.yml +++ b/data/rules/stabilityai.yml @@ -2,13 +2,15 @@ rules: - name: Stability AI API Key id: kingfisher.stabilityai.1 pattern: | - (?x) + (?x) \b ( sk- [A-Za-z0-9]{48} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 4.0 confidence: medium examples: diff --git a/data/rules/stackhawk.yml b/data/rules/stackhawk.yml index b8fec69..d001e40 100644 --- a/data/rules/stackhawk.yml +++ b/data/rules/stackhawk.yml @@ -8,6 +8,8 @@ rules: hawk\.[0-9A-Z_-]{20}\.[0-9A-Z_-]{20} ) \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 3.0 examples: diff --git a/data/rules/stripe.yml b/data/rules/stripe.yml index faaa1ab..934dba7 100644 --- a/data/rules/stripe.yml +++ b/data/rules/stripe.yml @@ -8,10 +8,16 @@ rules: (?:.|[\n\r]){0,16}? (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) (?:.|[\n\r]){0,16}? + \b ( pk_live_ (?:[0-9A-Z]{6}){4,30} - ) + ) + \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.3 confidence: medium categories: [api, key] @@ -27,12 +33,16 @@ rules: (?:.|[\n\r]){0,16}? (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) (?:.|[\n\r]){0,16}? + \b ( (?: sk|rk )_live_ (?:[0-9A-Z]{8}){3,25} ) + \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/supabase.yml b/data/rules/supabase.yml index d297514..b2d7c32 100644 --- a/data/rules/supabase.yml +++ b/data/rules/supabase.yml @@ -8,6 +8,8 @@ rules: sbp_[a-z0-9_-]{40} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.5 confidence: medium examples: @@ -37,8 +39,10 @@ rules: sb_secret_[a-z0-9_-]{31} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 4.0 - confidence: high + confidence: medium validation: type: Http content: @@ -67,9 +71,11 @@ rules: id: kingfisher.supabase.3 pattern: (?xi) + \b ( https:\/\/[a-z0-9]{16,32}\.supabase\.co ) + \b confidence: medium min_entropy: 3.0 visible: false diff --git a/data/rules/tailscale.yml b/data/rules/tailscale.yml index 3544b1f..08fa9eb 100644 --- a/data/rules/tailscale.yml +++ b/data/rules/tailscale.yml @@ -8,6 +8,8 @@ rules: tskey-[a-z]{3,10}-[A-Z0-9_-]{20,36} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.0 confidence: medium examples: diff --git a/data/rules/tavily.yml b/data/rules/tavily.yml index a908a21..1775eb4 100644 --- a/data/rules/tavily.yml +++ b/data/rules/tavily.yml @@ -9,6 +9,8 @@ rules: tvly-[a-zA-Z0-9]{32} ) \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 3.0 references: diff --git a/data/rules/teamcity.yml b/data/rules/teamcity.yml index c3bf68b..b475c32 100644 --- a/data/rules/teamcity.yml +++ b/data/rules/teamcity.yml @@ -12,6 +12,8 @@ rules: \. [A-Za-z0-9_-]{48} ) + pattern_requirements: + min_digits: 2 examples: - '' references: diff --git a/data/rules/telegram.yml b/data/rules/telegram.yml index 9b6dc98..8786d64 100644 --- a/data/rules/telegram.yml +++ b/data/rules/telegram.yml @@ -10,6 +10,8 @@ rules: [A-Z0-9_-]{35} ) \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 3.5 validation: diff --git a/data/rules/thingsboard.yml b/data/rules/thingsboard.yml index 562ee25..ce5ed78 100644 --- a/data/rules/thingsboard.yml +++ b/data/rules/thingsboard.yml @@ -3,8 +3,14 @@ rules: id: kingfisher.thingsboard.1 pattern: | (?x) + \b thingsboard\.cloud/api/v1/ - ([a-z0-9]{20}) + ( + [a-z0-9]{20} + ) + \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 3.0 examples: @@ -20,8 +26,10 @@ rules: pattern: | (?x) "provisionDeviceKey"\s*:\s*" - ([a-z0-9]{20}) - " + ( + [a-z0-9]{20} + ) + \b confidence: medium min_entropy: 3.0 examples: @@ -34,8 +42,10 @@ rules: pattern: | (?x) "provisionDeviceSecret"\s*:\s*" - ([a-z0-9]{20}) - " + ( + [a-z0-9]{20} + ) + \b confidence: medium min_entropy: 3.0 examples: diff --git a/data/rules/togetherai.yml b/data/rules/togetherai.yml index ee43097..e3d9b04 100644 --- a/data/rules/togetherai.yml +++ b/data/rules/togetherai.yml @@ -7,6 +7,9 @@ rules: ( tgp_v1_[A-Z0-9_-]{43} ) + \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 3.0 examples: diff --git a/data/rules/travisci.yml b/data/rules/travisci.yml index 73e75c4..1d4b188 100644 --- a/data/rules/travisci.yml +++ b/data/rules/travisci.yml @@ -13,6 +13,8 @@ rules: [A-Z-_0-9]{22} ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.0 confidence: medium examples: @@ -35,10 +37,8 @@ rules: id: kingfisher.travisci.2 pattern: | (?xis) - \b (?:language|env|deploy|script):[\r\n] (?:.|[\\n\r]){0,256}? - \b ( secure:\s*"?[A-Za-z0-9+/=\\]+"?\s* ) diff --git a/data/rules/truenas.yml b/data/rules/truenas.yml index a0a6d96..57ffcff 100644 --- a/data/rules/truenas.yml +++ b/data/rules/truenas.yml @@ -6,6 +6,8 @@ rules: "params"\s*:\s*\[\s*" (\d+-[a-zA-Z0-9]{64}) "\s*\] + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: @@ -36,6 +38,8 @@ rules: Bearer\s* (\d+-[a-zA-Z0-9]{64}) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/twilio.yml b/data/rules/twilio.yml index b3b2d32..14c5b0e 100644 --- a/data/rules/twilio.yml +++ b/data/rules/twilio.yml @@ -8,6 +8,9 @@ rules: (?:SK|AC)[A-F0-9]{32} ) \b + pattern_requirements: + min_digits: 2 + visible: false min_entropy: 3.5 examples: - | @@ -31,7 +34,10 @@ rules: ( [a-z0-9]{32} ) - \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.0 examples: - Twilio_key=Cd2Bd1dE1201aE2DFFEcfeBafCc3c31D diff --git a/data/rules/twitch.yml b/data/rules/twitch.yml index c17c225..1ab6102 100644 --- a/data/rules/twitch.yml +++ b/data/rules/twitch.yml @@ -6,10 +6,15 @@ rules: \b twitch (?:.|[\n\r]){0,32}? + \b ( [a-z0-9]{30} ) \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 3.5 confidence: medium examples: diff --git a/data/rules/twitter.yml b/data/rules/twitter.yml index e75b48e..941d48d 100644 --- a/data/rules/twitter.yml +++ b/data/rules/twitter.yml @@ -13,6 +13,10 @@ rules: A{10,}[A-Za-z0-9_\-]{40,200} ) \b + pattern_requirements: + min_digits: 2 + min_uppercase: 1 + min_lowercase: 1 min_entropy: 4.0 confidence: medium examples: @@ -45,11 +49,9 @@ rules: (?:.|[\n\r]){0,32}? (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) (?:.|[\n\r]){0,32}? - \b ( [A-Z0-9]{25} ) - \b min_entropy: 3.5 visible: false examples: @@ -63,11 +65,9 @@ rules: (?:.|[\n\r]){0,32}? (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) (?:.|[\n\r]){0,32}? - \b ( [A-Z0-9]{50} ) - \b min_entropy: 4.5 examples: - "TWITTER_SECRET=ZGwXeK2DNCqv49Z9ofwYdqlBgeoHDyh8uoAgHju6OeYC7wTQJq" diff --git a/data/rules/typeform.yml b/data/rules/typeform.yml index a91578d..cfbc3ee 100644 --- a/data/rules/typeform.yml +++ b/data/rules/typeform.yml @@ -9,6 +9,8 @@ rules: ( tfp_[a-z0-9_\-=\.]{59} ) + pattern_requirements: + min_digits: 2 min_entropy: 4.0 confidence: medium examples: diff --git a/data/rules/vercel.yml b/data/rules/vercel.yml index 121b5fe..3ace650 100644 --- a/data/rules/vercel.yml +++ b/data/rules/vercel.yml @@ -11,6 +11,10 @@ rules: [A-Z0-9]{24} ) \b + pattern_requirements: + min_digits: 6 + min_uppercase: 1 + min_lowercase: 1 confidence: medium min_entropy: 3.5 validation: diff --git a/data/rules/vmware.yml b/data/rules/vmware.yml index 9332a37..c623ebf 100644 --- a/data/rules/vmware.yml +++ b/data/rules/vmware.yml @@ -8,7 +8,6 @@ rules: -User \s+ (\S{3,30}) \s+ (?# username ) .{0,50} -Password \s+ (\S{3,30}) (?# password ) - examples: - 'Connect-VIServer -Server 192.168.1.51 -User administrator@vSphere.local -Password VMware1!' - | diff --git a/data/rules/weightsandbiases.yml b/data/rules/weightsandbiases.yml index bed9ca5..88bb37b 100644 --- a/data/rules/weightsandbiases.yml +++ b/data/rules/weightsandbiases.yml @@ -3,13 +3,15 @@ rules: id: kingfisher.wandb.1 pattern: | (?xi) - \b (?:wandb|weightsandbiases) (?:.|[\n\r]){0,16}? + \b ( [a-f0-9]{40} ) \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 3.5 examples: diff --git a/data/rules/wireguard.yml b/data/rules/wireguard.yml index 70aa1ae..47223c1 100644 --- a/data/rules/wireguard.yml +++ b/data/rules/wireguard.yml @@ -2,6 +2,8 @@ rules: - name: WireGuard Private Key id: kingfisher.wireguard.1 pattern: PrivateKey\s*=\s*([A-Za-z0-9+/]{43}=) + pattern_requirements: + min_digits: 2 min_entropy: 3.3 confidence: medium examples: diff --git a/data/rules/xAI.yml b/data/rules/xAI.yml index 398ac03..67a04ae 100644 --- a/data/rules/xAI.yml +++ b/data/rules/xAI.yml @@ -6,8 +6,10 @@ rules: \b ( xai-[A-Za-z0-9_-]{70,120} - ) + ) \b + pattern_requirements: + min_digits: 2 min_entropy: 3.8 confidence: medium examples: diff --git a/data/rules/zhipu.yml b/data/rules/zhipu.yml index bc1bffd..3d7ddab 100644 --- a/data/rules/zhipu.yml +++ b/data/rules/zhipu.yml @@ -10,6 +10,8 @@ rules: [A-Z0-9]{16} ) \b + pattern_requirements: + min_digits: 2 confidence: medium min_entropy: 4.0 examples: diff --git a/docs/RULES.md b/docs/RULES.md index 5a2fbfc..3b3e65a 100644 --- a/docs/RULES.md +++ b/docs/RULES.md @@ -38,6 +38,13 @@ rules: - rule_id: kingfisher.aws.id variable: AKID # referenced as {{ AKID }} + pattern_requirements: # (optional) character type requirements + min_digits: 1 # require at least 1 digit + min_uppercase: 1 # require at least 1 uppercase letter + min_lowercase: 1 # require at least 1 lowercase letter + min_special_chars: 1 # require at least 1 special character + special_chars: "!@#$%^&*()" # optional: custom special character set + validation: # (optional) live validation type: Http content: @@ -61,17 +68,18 @@ rules: - type: JsonValid ``` -| Field | What it does | -| ----------------- | -------------------------------------------------------------------- | -| name | Friendly name shown in reports | -| id | Unique text ID (namespace.v#) used internally | -| pattern | Regex used to spot secrets (free‑spacing & flags allowed) | -| min_entropy | Threshold to guard against low‑complexity false positives | -| confidence | Suggests severity: low → high | -| examples | Good matches; used for testing | -| visible | false to hide non‑secret captures (e.g. IDs) | -| depends_on_rule | Chain rules: use captures from one rule in another’s validation | -| validation | Configure HTTP, AWS, GCP, etc. checks to verify live validity | +| Field | What it does | +| ----------------------- | -------------------------------------------------------------------- | +| name | Friendly name shown in reports | +| id | Unique text ID (namespace.v#) used internally | +| pattern | Regex used to spot secrets (free‑spacing & flags allowed) | +| min_entropy | Threshold to guard against low‑complexity false positives | +| confidence | Suggests severity: low → high | +| examples | Good matches; used for testing | +| visible | false to hide non‑secret captures (e.g. IDs) | +| depends_on_rule | Chain rules: use captures from one rule in another's validation | +| pattern_requirements | Require specific character types (digits, uppercase, lowercase, special) | +| validation | Configure HTTP, AWS, GCP, etc. checks to verify live validity | *responser_matcher* variants. Multiple can be used @@ -237,6 +245,89 @@ For example, a rule might match a username, an email address, an AWS Access Key `visible: false` helps keep the scan output focused on actual secrets while still capturing important contextual data needed for comprehensive validation. +## Character Requirements + +The `pattern_requirements` field allows you to specify data type requirements for matched secrets. This is particularly useful when: + +- Your regex pattern must be permissive (due to Hyperscan limitations) +- You want to enforce password complexity requirements +- You need to filter out low-quality matches that lack certain character types + +Kingfisher's regex engine (Hyperscan) does not support lookahead assertions like `(?=.*\d)` to require specific character types. Instead, use the `pattern_requirements` field to filter matches post-detection. + +### Available Requirements + +```yaml +pattern_requirements: + min_digits: 1 # Require at least 1 digit (0-9) + min_uppercase: 1 # Require at least 1 uppercase letter (A-Z) + min_lowercase: 1 # Require at least 1 lowercase letter (a-z) + min_special_chars: 1 # Require at least 1 special character + special_chars: "!@#$%^&*" # Optional: define which characters are "special" +``` + +All fields are optional. If `special_chars` is not specified, the default set includes: `!@#$%^&*()_+-=[]{}|;:'",.<>?/\`~` + +### Example: Secure API Key + +```yaml +rules: + - name: Secure API Key + id: custom.secure_api.1 + pattern: | + (?xi) + api[_-]?key + (?:.|[\n\r]){0,32}? + \b + ([A-Za-z0-9!@#$%^&*]{20,}) + \b + min_entropy: 4.0 + confidence: high + pattern_requirements: + min_digits: 1 # Must contain at least 1 digit + min_uppercase: 1 # Must contain at least 1 uppercase letter + min_lowercase: 1 # Must contain at least 1 lowercase letter + min_special_chars: 1 # Must contain at least 1 special character + examples: + - api_key = "MyS3cur3K3y!2024" + - api-key: "Abc123!@#Token" +``` + +In this example: +- The regex pattern is permissive: `[A-Za-z0-9!@#$%^&*]{20,}` matches any combination of those characters +- The `pattern_requirements` filters out matches that don't have at least one of each required type +- A match like `"abcdefghijklmnopqrst"` would be rejected (no uppercase, no digit, no special) +- A match like `"Abc123!SecureToken"` would be accepted (has all required types) + +### Example: Custom Special Characters + +```yaml +rules: + - name: Token with Custom Special Chars + id: custom.token.1 + pattern: | + (?xi) + token + (?:.|[\n\r]){0,16}? + \b([A-Za-z0-9$%^]{16,})\b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_special_chars: 2 + special_chars: "$%^" # Only these characters count as "special" + examples: + - token = "abc$%defgh123456" +``` + +### How It Works + +1. Hyperscan regex matches a pattern in the input +2. Entropy check filters low-complexity matches (if `min_entropy` is set) +3. **Character requirements check filters matches that don't meet the criteria** +4. Validation checks verify the secret is live (if `validation` is configured) + +Matches that fail the character requirements check are silently dropped with a debug log message. + ## Writing Custom Rules diff --git a/src/baseline.rs b/src/baseline.rs index 6f3dab5..68f5d93 100644 --- a/src/baseline.rs +++ b/src/baseline.rs @@ -147,6 +147,7 @@ mod tests { references: vec![], validation: None, depends_on_rule: vec![], + pattern_requirements: None, })) } diff --git a/src/matcher.rs b/src/matcher.rs index f93576a..7d73b76 100644 --- a/src/matcher.rs +++ b/src/matcher.rs @@ -602,6 +602,18 @@ fn filter_match<'b>( ); continue; } + + // Check character requirements if specified + if let Some(char_reqs) = rule.pattern_requirements() { + if !char_reqs.validate(mi_bytes) { + debug!( + "Skipping match that does not meet character requirements for rule {}", + rule.id() + ); + continue; + } + } + let matching_input_offset_span = OffsetSpan::from_range( (start + matching_input.start())..(start + matching_input.end()), ); @@ -1027,6 +1039,7 @@ mod test { references: vec![], validation: None::, // no HTTP validation needed depends_on_rule: vec![], + pattern_requirements: None, }); let rules_db = RulesDatabase::from_rules(vec![rule]).unwrap(); @@ -1098,6 +1111,7 @@ mod test { variable: "domain".to_string(), }), ], + pattern_requirements: None, })]; let rules_db = RulesDatabase::from_rules(rules)?; let input = "some test data for vectorscan"; @@ -1197,6 +1211,7 @@ mod test { references: vec![], validation: None::, depends_on_rule: vec![], + pattern_requirements: None, }); let rules_db = RulesDatabase::from_rules(vec![rule])?; @@ -1234,6 +1249,7 @@ mod test { references: vec![], validation: None::, depends_on_rule: vec![], + pattern_requirements: None, }); let rules_db = RulesDatabase::from_rules(vec![rule])?; let seen = BlobIdMap::new(); @@ -1266,6 +1282,7 @@ mod test { references: vec![], validation: None::, depends_on_rule: vec![], + pattern_requirements: None, }); let rules_db = RulesDatabase::from_rules(vec![rule])?; let seen = BlobIdMap::new(); @@ -1306,6 +1323,7 @@ line2 references: vec![], validation: None::, depends_on_rule: vec![], + pattern_requirements: None, }); let rules_db = RulesDatabase::from_rules(vec![rule])?; diff --git a/src/reporter.rs b/src/reporter.rs index 9ec0f66..bb96064 100644 --- a/src/reporter.rs +++ b/src/reporter.rs @@ -840,6 +840,7 @@ mod tests { references: vec![], validation: None, depends_on_rule: vec![], + pattern_requirements: None, })); let blob_id = BlobId::new(b"blob-data"); diff --git a/src/reporter/json_format.rs b/src/reporter/json_format.rs index 26d1b27..11c5b30 100644 --- a/src/reporter/json_format.rs +++ b/src/reporter/json_format.rs @@ -196,6 +196,7 @@ mod tests { references: vec![], validation: None, depends_on_rule: vec![], + pattern_requirements: None, }; let rule = Arc::new(Rule::new(syntax)); Match { diff --git a/src/rules/rule.rs b/src/rules/rule.rs index dbf52ef..399bd73 100644 --- a/src/rules/rule.rs +++ b/src/rules/rule.rs @@ -52,6 +52,73 @@ pub struct DependsOnRule { pub variable: String, } +/// Specifies character type requirements for matched secrets. +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)] +pub struct PatternRequirements { + /// Minimum number of digits required (0-9) + #[serde(default)] + pub min_digits: Option, + /// Minimum number of uppercase letters required (A-Z) + #[serde(default)] + pub min_uppercase: Option, + /// Minimum number of lowercase letters required (a-z) + #[serde(default)] + pub min_lowercase: Option, + /// Minimum number of special characters required + #[serde(default)] + pub min_special_chars: Option, + /// Custom set of characters to consider as "special" (defaults to common punctuation) + #[serde(default)] + pub special_chars: Option, +} + +impl PatternRequirements { + /// Default special characters if none are specified + const DEFAULT_SPECIAL_CHARS: &'static str = "!@#$%^&*()_+-=[]{}|;:'\",.<>?/\\`~"; + + /// Validates whether the given byte slice meets the character requirements. + /// Returns true if all requirements are met, false otherwise. + pub fn validate(&self, input: &[u8]) -> bool { + // Convert to string (lossy for non-UTF8) + let s = String::from_utf8_lossy(input); + + // Check digit requirement + if let Some(min_digits) = self.min_digits { + let digit_count = s.chars().filter(|c| c.is_ascii_digit()).count(); + if digit_count < min_digits { + return false; + } + } + + // Check uppercase requirement + if let Some(min_uppercase) = self.min_uppercase { + let uppercase_count = s.chars().filter(|c| c.is_ascii_uppercase()).count(); + if uppercase_count < min_uppercase { + return false; + } + } + + // Check lowercase requirement + if let Some(min_lowercase) = self.min_lowercase { + let lowercase_count = s.chars().filter(|c| c.is_ascii_lowercase()).count(); + if lowercase_count < min_lowercase { + return false; + } + } + + // Check special character requirement + if let Some(min_special) = self.min_special_chars { + let special_chars = self.special_chars.as_deref().unwrap_or(Self::DEFAULT_SPECIAL_CHARS); + let special_count = s.chars().filter(|c| special_chars.contains(*c)).count(); + if special_count < min_special { + return false; + } + } + + true + } +} + /// Configuration for HTTP validation. This contains a request configuration /// and an optional multipart configuration. #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)] @@ -283,6 +350,9 @@ pub struct RuleSyntax { /// Optional dependencies on other rules. #[serde(default)] pub depends_on_rule: Vec>, + /// Optional character type requirements for matched secrets. + #[serde(default)] + pub pattern_requirements: Option, } lazy_static! { @@ -333,6 +403,7 @@ impl RuleSyntax { /// visible: true, /// validation: None, /// depends_on_rule: vec![], + /// pattern_requirements: None, /// }; /// assert_eq!(r.as_anchored_regex().unwrap().as_str(), r"hello\s*world$"); /// ``` @@ -436,4 +507,156 @@ impl Rule { pub fn confidence(&self) -> Confidence { self.syntax.confidence } + + /// Returns the character requirements for this rule, if any. + pub fn pattern_requirements(&self) -> Option<&PatternRequirements> { + self.syntax.pattern_requirements.as_ref() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_pattern_requirements_digits() { + let reqs = PatternRequirements { + min_digits: Some(2), + min_uppercase: None, + min_lowercase: None, + min_special_chars: None, + special_chars: None, + }; + + // Should pass: has 3 digits + assert!(reqs.validate(b"abc123def")); + + // Should fail: only 1 digit + assert!(!reqs.validate(b"abc1def")); + + // Should fail: no digits + assert!(!reqs.validate(b"abcdef")); + } + + #[test] + fn test_pattern_requirements_uppercase() { + let reqs = PatternRequirements { + min_digits: None, + min_uppercase: Some(2), + min_lowercase: None, + min_special_chars: None, + special_chars: None, + }; + + // Should pass: has 3 uppercase + assert!(reqs.validate(b"ABCdef")); + + // Should fail: only 1 uppercase + assert!(!reqs.validate(b"Adef")); + + // Should fail: no uppercase + assert!(!reqs.validate(b"abcdef")); + } + + #[test] + fn test_pattern_requirements_lowercase() { + let reqs = PatternRequirements { + min_digits: None, + min_uppercase: None, + min_lowercase: Some(2), + min_special_chars: None, + special_chars: None, + }; + + // Should pass: has 3 lowercase + assert!(reqs.validate(b"ABCdef")); + + // Should fail: only 1 lowercase + assert!(!reqs.validate(b"ABCd")); + + // Should fail: no lowercase + assert!(!reqs.validate(b"ABC123")); + } + + #[test] + fn test_pattern_requirements_special_chars() { + let reqs = PatternRequirements { + min_digits: None, + min_uppercase: None, + min_lowercase: None, + min_special_chars: Some(2), + special_chars: None, // uses default + }; + + // Should pass: has 2 special chars + assert!(reqs.validate(b"abc!@def")); + + // Should fail: only 1 special char + assert!(!reqs.validate(b"abc!def")); + + // Should fail: no special chars + assert!(!reqs.validate(b"abcdef")); + } + + #[test] + fn test_pattern_requirements_custom_special_chars() { + let reqs = PatternRequirements { + min_digits: None, + min_uppercase: None, + min_lowercase: None, + min_special_chars: Some(2), + special_chars: Some("$%^".to_string()), + }; + + // Should pass: has 2 custom special chars + assert!(reqs.validate(b"abc$%def")); + + // Should fail: has special chars but not the custom ones + assert!(!reqs.validate(b"abc!@def")); + + // Should fail: only 1 custom special char + assert!(!reqs.validate(b"abc$def")); + } + + #[test] + fn test_pattern_requirements_combined() { + let reqs = PatternRequirements { + min_digits: Some(1), + min_uppercase: Some(1), + min_lowercase: Some(1), + min_special_chars: Some(1), + special_chars: None, + }; + + // Should pass: has all requirements + assert!(reqs.validate(b"Abc1!")); + + // Should fail: missing digit + assert!(!reqs.validate(b"Abc!")); + + // Should fail: missing uppercase + assert!(!reqs.validate(b"abc1!")); + + // Should fail: missing lowercase + assert!(!reqs.validate(b"ABC1!")); + + // Should fail: missing special + assert!(!reqs.validate(b"Abc1")); + } + + #[test] + fn test_pattern_requirements_none() { + let reqs = PatternRequirements { + min_digits: None, + min_uppercase: None, + min_lowercase: None, + min_special_chars: None, + special_chars: None, + }; + + // Should pass: no requirements + assert!(reqs.validate(b"anything")); + assert!(reqs.validate(b"123")); + assert!(reqs.validate(b"!@#")); + } } diff --git a/testdata/test_char_requirements.yaml b/testdata/test_char_requirements.yaml new file mode 100644 index 0000000..f1f9801 --- /dev/null +++ b/testdata/test_char_requirements.yaml @@ -0,0 +1,24 @@ +rules: + - name: Secure API Key with Character Requirements + id: test.char_requirements.1 + pattern: | + (?xi) + api[_-]?key + (?:.|[\n\r]){0,32}? + \b + ([A-Za-z0-9!@#$%^&*]{16,}) + \b + min_entropy: 3.0 + confidence: high + pattern_requirements: + min_digits: 1 + min_uppercase: 1 + min_lowercase: 1 + min_special_chars: 1 + examples: + - api_key = "Abc123!SecureToken" + - api-key: "MyK3y!WithSpecial" + negative_examples: + - api_key = "abcdefghijklmnop" # no uppercase, no digit, no special + - api_key = "ABCDEFGHIJKLMNOP" # no lowercase, no digit, no special + - api_key = "abc123defghijklm" # no uppercase, no special diff --git a/tests/fingerprint_dedup.rs b/tests/fingerprint_dedup.rs index f458e7d..5771cc4 100644 --- a/tests/fingerprint_dedup.rs +++ b/tests/fingerprint_dedup.rs @@ -33,6 +33,7 @@ fn make_match(fp: u64) -> Match { references: vec![], validation: None, depends_on_rule: vec![], + pattern_requirements: None, }; let rule = Arc::new(Rule::new(syntax)); Match {