From 6d44e2c1b62e4ac1a360495ea1ade109f7c4160b Mon Sep 17 00:00:00 2001 From: Mick Grove Date: Sat, 7 Mar 2026 21:28:37 -0800 Subject: [PATCH] added new rules --- CHANGELOG.md | 2 + crates/kingfisher-rules/data/rules/AGENTS.md | 78 ++++++++++++++++++ crates/kingfisher-rules/data/rules/ably.yml | 39 +++++++++ .../data/rules/abstractapi.yml | 41 ++++++++++ .../kingfisher-rules/data/rules/abuseipdb.yml | 39 +++++++++ .../data/rules/aviationstack.yml | 40 +++++++++ .../data/rules/betterstack.yml | 42 ++++++++++ crates/kingfisher-rules/data/rules/brevo.yml | 33 ++++++++ .../kingfisher-rules/data/rules/clearout.yml | 42 ++++++++++ crates/kingfisher-rules/data/rules/clerk.yml | 39 +++++++++ .../data/rules/cloudinary.yml | 82 +++++++++++++++++++ .../kingfisher-rules/data/rules/coinlayer.yml | 41 ++++++++++ .../data/rules/contentstack.yml | 62 ++++++++++++++ .../data/rules/currencylayer.yml | 41 ++++++++++ crates/kingfisher-rules/data/rules/daily.yml | 43 ++++++++++ crates/kingfisher-rules/data/rules/fixer.yml | 41 ++++++++++ .../kingfisher-rules/data/rules/geoapify.yml | 38 +++++++++ .../kingfisher-rules/data/rules/hunterio.yml | 40 +++++++++ crates/kingfisher-rules/data/rules/mux.yml | 59 +++++++++++++ .../kingfisher-rules/data/rules/newsapi.yml | 40 +++++++++ .../kingfisher-rules/data/rules/numverify.yml | 41 ++++++++++ .../kingfisher-rules/data/rules/onesignal.yml | 42 ++++++++++ .../kingfisher-rules/data/rules/pinecone.yml | 39 +++++++++ .../kingfisher-rules/data/rules/pingdom.yml | 42 ++++++++++ .../data/rules/positionstack.yml | 40 +++++++++ .../kingfisher-rules/data/rules/railway.yml | 44 ++++++++++ crates/kingfisher-rules/data/rules/render.yml | 39 +++++++++ .../kingfisher-rules/data/rules/rollbar.yml | 42 ++++++++++ .../kingfisher-rules/data/rules/salesloft.yml | 39 +++++++++ crates/kingfisher-rules/data/rules/sanity.yml | 39 +++++++++ .../data/rules/statuscake.yml | 41 ++++++++++ .../kingfisher-rules/data/rules/storyblok.yml | 38 +++++++++ .../data/rules/uptimerobot.yml | 38 +++++++++ .../kingfisher-rules/data/rules/urlscan.yml | 39 +++++++++ .../data/rules/virustotal.yml | 42 ++++++++++ .../data/rules/weatherapi.yml | 40 +++++++++ .../kingfisher-rules/data/rules/webflow.yml | 39 +++++++++ .../data/rules/zerobounce.yml | 38 +++++++++ 38 files changed, 1604 insertions(+) create mode 100644 crates/kingfisher-rules/data/rules/AGENTS.md create mode 100644 crates/kingfisher-rules/data/rules/ably.yml create mode 100644 crates/kingfisher-rules/data/rules/abstractapi.yml create mode 100644 crates/kingfisher-rules/data/rules/abuseipdb.yml create mode 100644 crates/kingfisher-rules/data/rules/aviationstack.yml create mode 100644 crates/kingfisher-rules/data/rules/betterstack.yml create mode 100644 crates/kingfisher-rules/data/rules/brevo.yml create mode 100644 crates/kingfisher-rules/data/rules/clearout.yml create mode 100644 crates/kingfisher-rules/data/rules/clerk.yml create mode 100644 crates/kingfisher-rules/data/rules/cloudinary.yml create mode 100644 crates/kingfisher-rules/data/rules/coinlayer.yml create mode 100644 crates/kingfisher-rules/data/rules/contentstack.yml create mode 100644 crates/kingfisher-rules/data/rules/currencylayer.yml create mode 100644 crates/kingfisher-rules/data/rules/daily.yml create mode 100644 crates/kingfisher-rules/data/rules/fixer.yml create mode 100644 crates/kingfisher-rules/data/rules/geoapify.yml create mode 100644 crates/kingfisher-rules/data/rules/hunterio.yml create mode 100644 crates/kingfisher-rules/data/rules/mux.yml create mode 100644 crates/kingfisher-rules/data/rules/newsapi.yml create mode 100644 crates/kingfisher-rules/data/rules/numverify.yml create mode 100644 crates/kingfisher-rules/data/rules/onesignal.yml create mode 100644 crates/kingfisher-rules/data/rules/pinecone.yml create mode 100644 crates/kingfisher-rules/data/rules/pingdom.yml create mode 100644 crates/kingfisher-rules/data/rules/positionstack.yml create mode 100644 crates/kingfisher-rules/data/rules/railway.yml create mode 100644 crates/kingfisher-rules/data/rules/render.yml create mode 100644 crates/kingfisher-rules/data/rules/rollbar.yml create mode 100644 crates/kingfisher-rules/data/rules/salesloft.yml create mode 100644 crates/kingfisher-rules/data/rules/sanity.yml create mode 100644 crates/kingfisher-rules/data/rules/statuscake.yml create mode 100644 crates/kingfisher-rules/data/rules/storyblok.yml create mode 100644 crates/kingfisher-rules/data/rules/uptimerobot.yml create mode 100644 crates/kingfisher-rules/data/rules/urlscan.yml create mode 100644 crates/kingfisher-rules/data/rules/virustotal.yml create mode 100644 crates/kingfisher-rules/data/rules/weatherapi.yml create mode 100644 crates/kingfisher-rules/data/rules/webflow.yml create mode 100644 crates/kingfisher-rules/data/rules/zerobounce.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 62a7490..fa20dd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file. ## [v1.87.0] - Hardened Perplexity API key validation to reject auth failures (`401`/`403`) and avoid false "Active Credential" results from error payloads. - Fixed Yelp API key validation false positives by switching to an auth-enforcing endpoint (`/v3/businesses/search`) and adding explicit auth error guards. +- Added 37 new provider detection + HTTP validation rules: Ably, AbstractAPI, AbuseIPDB, AviationStack, Better Stack, Brevo, Clearout, Clerk, Cloudinary, Coinlayer, Contentstack, Currencylayer, Daily, Fixer, Geoapify, Hunter.io, Mux, NewsAPI, Numverify, OneSignal, Pinecone, Pingdom, Positionstack, Railway, Render, Rollbar, Salesloft, Sanity, StatusCake, Storyblok, UptimeRobot, urlscan.io, VirusTotal, WeatherAPI, Webflow, and ZeroBounce. +- Tightened regex specificity for newly added rules by replacing broad variable-length token captures with explicit fixed formats/lengths and aligned examples to pass `rules check`. ## [v1.86.0] - GitLab scanning: honor OS-trusted internal CAs without requiring `SSL_CERT_FILE`, and preserve custom GitLab API ports in repository enumeration and artifact fetching. diff --git a/crates/kingfisher-rules/data/rules/AGENTS.md b/crates/kingfisher-rules/data/rules/AGENTS.md new file mode 100644 index 0000000..80a9522 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/AGENTS.md @@ -0,0 +1,78 @@ +# AGENTS.md + +Rule-authoring instructions for this directory. + +## Scope +- Applies to `crates/kingfisher-rules/data/rules/` and all files under it. +- This file overrides broader AGENTS guidance for rule-writing tasks in this subtree. + +## Goal +- Add or update YAML detection rules with high precision, low false positives, and safe remediation support. + +## Rule File Conventions +- Keep provider rules in provider-named files (for example `github.yml`, `openai.yml`). +- Prefer lowercase filenames with `.yml`. +- Keep rule IDs stable and unique. Prefer `kingfisher..` unless a descriptive suffix is already established for that provider. +- Reuse nearby provider patterns/styles instead of inventing new structure. + +## Required Rule Shape +Each rule entry should define: +- `name` +- `id` +- `pattern` +- `min_entropy` (default to 3.0) +- `confidence` (default to medium) +- `examples` (at least one realistic positive example) + +Strongly recommended fields: +- `pattern_requirements` (for extra filtering) +- `references` + +## Pattern Quality Rules +- Prefer specific anchors/prefixes and provider context over broad generic regex. +- Use `pattern_requirements` to enforce quality constraints (`min_digits`, `min_uppercase`, `min_lowercase`, `min_special_chars`, `ignore_if_contains`, `checksum`). +- Use checksum validation in `pattern_requirements.checksum` when token formats support it. +- Use `visible: false` for helper/non-secret captures used only by dependent rules. +- Use `depends_on_rule` for multi-part credential validation (for example ID + secret). + +## Validation Policy (Important) +- Default: define validation logic in YAML under `validation:`. +- Do not move validation logic into Rust unless YAML cannot reliably express it. +- Code-backed validation types (for example AWS, GCP, Coinbase, MongoDB) are notable exceptions and should remain rare. +- For new rules, first attempt `Http`/`Grpc` YAML validation before considering exception paths. + +## Revocation Policy +- If a rule has validation and the provider API safely supports revocation, add `revocation:` in the same YAML rule. +- Prefer explicit success criteria in `response_matcher`. +- Use `HttpMultiStep` revocation when API workflows require pre-fetch/extraction steps. +- If revocation is intentionally not supported, document why with an inline YAML comment. + +## Authoring Workflow +1. Choose the target provider file (or add a new provider file if no suitable file exists). +2. Copy a structurally similar rule from this directory. +3. Implement/adjust `pattern`, `examples`, and filtering (`pattern_requirements`, `min_entropy`). +4. Add YAML `validation` (default path). +5. Add YAML `revocation` when supported. +6. Add `references` for token format/API behavior. +7. Verify locally (below). + +## Local Verification Checklist +- Syntax/load checks: + - `cargo test -p kingfisher-rules` +- Broader regression check: + - `cargo test --workspace --all-targets` +- Behavioral check against sample content: + - `kingfisher scan ./testdata --rule --rule-stats` +- Validation check (when validation is present): + - `kingfisher validate --rule ` + +## Documentation +Read these before complex edits: +- `docs/RULES.md` (schema, pattern requirements, checksum, Liquid, validation/revocation) +- `docs/MULTI_STEP_REVOCATION.md` +- `docs/TOKEN_REVOCATION_SUPPORT.md` + +## Change Discipline +- Keep changes scoped to the specific provider/rule request. +- Do not refactor unrelated rules in the same PR unless explicitly asked. +- Preserve existing YAML style and indentation conventions in this directory. diff --git a/crates/kingfisher-rules/data/rules/ably.yml b/crates/kingfisher-rules/data/rules/ably.yml new file mode 100644 index 0000000..44f1615 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/ably.yml @@ -0,0 +1,39 @@ +rules: + - name: Ably API Key + id: kingfisher.ably.1 + pattern: | + (?xi) + \b + ably + (?:.|[\n\r]){0,32}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN|API) + (?:.|[\n\r]){0,32}? + \b + ( + [A-Za-z0-9_-]{8}\.[A-Za-z0-9_-]{8}:[A-Za-z0-9_-]{24} + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - ABLY_API_KEY=abc12345.xyz78901:secretkeyvalue1234567890 + - ably_key = "appid123.keyid987:AbCdEfGhIjKlMnOpQrStUvWx" + references: + - https://ably.com/docs/auth/basic + - https://ably.com/docs/api/rest-api + validation: + type: Http + content: + request: + method: GET + url: https://rest.ably.io/channels?limit=1 + headers: + Authorization: "Basic {{ TOKEN | append: ':' | b64enc }}" + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/abstractapi.yml b/crates/kingfisher-rules/data/rules/abstractapi.yml new file mode 100644 index 0000000..0619b94 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/abstractapi.yml @@ -0,0 +1,41 @@ +rules: + - name: AbstractAPI API Key + id: kingfisher.abstractapi.1 + pattern: | + (?xi) + \b + abstractapi + (?:.|[\n\r]){0,16}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) + (?:.|[\n\r]){0,16}? + \b + ( + [A-Za-z0-9]{32} + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - abstractapi_api_key = "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" + - ABSTRACTAPI_KEY=abcdef1234567890abcdef1234567890 + references: + - https://docs.abstractapi.com/api/ip-geolocation + - https://abstractapi.com/docs + validation: + type: Http + content: + request: + method: GET + url: https://ipgeolocation.abstractapi.com/v1/?api_key={{ TOKEN }} + headers: + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: StatusMatch + status: [401, 403] + negative: true + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/abuseipdb.yml b/crates/kingfisher-rules/data/rules/abuseipdb.yml new file mode 100644 index 0000000..8853324 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/abuseipdb.yml @@ -0,0 +1,39 @@ +rules: + - name: AbuseIPDB API Key + id: kingfisher.abuseipdb.1 + pattern: | + (?xi) + \b + abuseipdb + (?:.|[\n\r]){0,16}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) + (?:.|[\n\r]){0,16}? + \b + ( + [A-Za-z0-9]{80} + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - abuseipdb_api_key = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" + - ABUSEIPDB_KEY=1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef + references: + - https://docs.abuseipdb.com/#introduction + - https://www.abuseipdb.com/api + validation: + type: Http + content: + request: + method: GET + url: https://api.abuseipdb.com/api/v2/check?ipAddress=127.0.0.1 + headers: + Key: "{{ TOKEN }}" + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/aviationstack.yml b/crates/kingfisher-rules/data/rules/aviationstack.yml new file mode 100644 index 0000000..eaf380e --- /dev/null +++ b/crates/kingfisher-rules/data/rules/aviationstack.yml @@ -0,0 +1,40 @@ +rules: + - name: AviationStack API Key + id: kingfisher.aviationstack.1 + pattern: | + (?xi) + \b + aviationstack + (?:.|[\n\r]){0,16}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) + (?:.|[\n\r]){0,16}? + \b + ( + [A-Za-z0-9]{32} + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - AVIATIONSTACK_ACCESS_KEY=abc123def456ghi789jkl012mno345pq + - aviationstack_access_key = "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" + references: + - https://aviationstack.com/documentation + validation: + type: Http + content: + request: + method: GET + url: https://api.aviationstack.com/v1/flights?access_key={{ TOKEN }} + headers: + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: StatusMatch + status: [401] + negative: true + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/betterstack.yml b/crates/kingfisher-rules/data/rules/betterstack.yml new file mode 100644 index 0000000..72e49ec --- /dev/null +++ b/crates/kingfisher-rules/data/rules/betterstack.yml @@ -0,0 +1,42 @@ +rules: + - name: Better Stack API Token + id: kingfisher.betterstack.1 + pattern: | + (?xi) + \b + betterstack + (?:.|[\n\r]){0,16}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) + (?:.|[\n\r]){0,16}? + \b + ( + [A-Za-z0-9_-]{24} + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - betterstack_api_token = "a1b2c3d4e5f6g7h8i9j0k1l2" + - BETTERSTACK_TOKEN=abcdef1234567890abcdef12 + references: + - https://betterstack.com/docs/uptime/api/getting-started-with-uptime-api/ + - https://betterstack.com/docs/uptime/api/list-all-existing-monitors + validation: + type: Http + content: + request: + method: GET + url: https://uptime.betterstack.com/api/v2/monitors + headers: + Authorization: "Bearer {{ TOKEN }}" + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: StatusMatch + status: [401, 403] + negative: true + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/brevo.yml b/crates/kingfisher-rules/data/rules/brevo.yml new file mode 100644 index 0000000..471f5f6 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/brevo.yml @@ -0,0 +1,33 @@ +rules: + - name: Brevo API Token + id: kingfisher.brevo.1 + pattern: | + (?x) + \b + ( + xkeysib-[a-fA-F0-9]{64}-[a-zA-Z0-9]{16} + ) + \b + pattern_requirements: + min_digits: 2 + min_entropy: 3.2 + confidence: medium + examples: + - BREVO_API_KEY=xkeysib-abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd-1234567890abcd12 + - '"brevo": "xkeysib-1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef-ab12cd34ef56gh78"' + references: + - https://developers.brevo.com/docs/api-key-authentication + - https://developers.brevo.com/docs/how-it-works + validation: + type: Http + content: + request: + method: GET + url: https://api.brevo.com/v3/account + headers: + api-key: "{{ TOKEN }}" + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] diff --git a/crates/kingfisher-rules/data/rules/clearout.yml b/crates/kingfisher-rules/data/rules/clearout.yml new file mode 100644 index 0000000..e3290f3 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/clearout.yml @@ -0,0 +1,42 @@ +rules: + - name: Clearout API Token + id: kingfisher.clearout.1 + pattern: | + (?xi) + \b + clearout + (?:.|[\n\r]){0,16}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) + (?:.|[\n\r]){0,16}? + \b + ( + [A-Za-z0-9]{28} + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - clearout_api_token = "a1b2c3d4e5f6g7h8i9j0k1l2m3n4" + - CLEAROUT_TOKEN=abcdef1234567890abcdef123456 + references: + - https://docs.clearout.io/api-overview.html + - https://docs.clearout.io/email-verifier-api.html + validation: + type: Http + content: + request: + method: GET + url: https://api.clearout.io/v2/email_verify/getcredits + headers: + Authorization: "Bearer {{ TOKEN }}" + Content-Type: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: StatusMatch + status: [401] + negative: true + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/clerk.yml b/crates/kingfisher-rules/data/rules/clerk.yml new file mode 100644 index 0000000..1960f54 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/clerk.yml @@ -0,0 +1,39 @@ +rules: + - name: Clerk Secret Key + id: kingfisher.clerk.1 + pattern: | + (?xi) + \b + clerk + (?:.|[\n\r]){0,32}? + (?:SECRET|PRIVATE|API|KEY|TOKEN) + (?:.|[\n\r]){0,16}? + \b + ( + sk_(?:test|live)_[A-Za-z0-9]{32} + ) + \b + pattern_requirements: + min_digits: 2 + min_entropy: 3.3 + confidence: medium + examples: + - CLERK_SECRET_KEY=sk_live_abcdefghijklmnopqrstuvwxyz123456 + - clerk_secret = sk_test_4pX9kL2mN8qR5sT7vY1zA3bC6dE0fG2h + references: + - https://clerk.com/docs/deployments/clerk-environment-variables + - https://clerk.com/docs/guides/development/machine-auth/api-keys + validation: + type: Http + content: + request: + method: GET + url: https://api.clerk.com/v1/users?limit=1 + headers: + Authorization: "Bearer {{ TOKEN }}" + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/cloudinary.yml b/crates/kingfisher-rules/data/rules/cloudinary.yml new file mode 100644 index 0000000..65488ca --- /dev/null +++ b/crates/kingfisher-rules/data/rules/cloudinary.yml @@ -0,0 +1,82 @@ +rules: + - name: Cloudinary Cloud Name + id: kingfisher.cloudinary.3 + pattern: | + (?xi) + \b + cloudinary + (?:.|[\n\r]){0,32}? + (?:CLOUD[_\s]?NAME|CLOUD) + (?:.|[\n\r]){0,16}? + \b + ( + [a-z0-9_-]{3,32} + ) + \b + min_entropy: 2.5 + confidence: medium + visible: false + examples: + - CLOUDINARY_CLOUD_NAME=demo + - name: Cloudinary API Key + id: kingfisher.cloudinary.2 + pattern: | + (?xi) + \b + cloudinary + (?:.|[\n\r]){0,32}? + (?:API[_\s]?KEY|KEY) + (?:.|[\n\r]){0,16}? + \b + ( + [0-9]{15} + ) + \b + min_entropy: 3.0 + confidence: medium + visible: false + examples: + - CLOUDINARY_API_KEY=123456789012345 + - name: Cloudinary API Secret + id: kingfisher.cloudinary.1 + pattern: | + (?xi) + \b + cloudinary + (?:.|[\n\r]){0,32}? + (?:SECRET|PRIVATE|API[_\s]?SECRET) + (?:.|[\n\r]){0,32}? + \b + ( + [A-Za-z0-9]{32} + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - CLOUDINARY_API_SECRET=abcdefghijklmnopqrstuvwxyz123456 + - cloudinary_secret = "aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW" + references: + - https://cloudinary.com/documentation/developer_onboarding_faq_find_credentials + - https://cloudinary.com/documentation/image_upload_api_reference + validation: + type: Http + content: + request: + method: GET + url: "https://api.cloudinary.com/v1_1/{{ CLOUDNAME }}/usage" + headers: + Authorization: "Basic {{ APIKEY | append: ':' | append: TOKEN | b64enc }}" + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: JsonValid + depends_on_rule: + - rule_id: kingfisher.cloudinary.2 + variable: APIKEY + - rule_id: kingfisher.cloudinary.3 + variable: CLOUDNAME diff --git a/crates/kingfisher-rules/data/rules/coinlayer.yml b/crates/kingfisher-rules/data/rules/coinlayer.yml new file mode 100644 index 0000000..405f57f --- /dev/null +++ b/crates/kingfisher-rules/data/rules/coinlayer.yml @@ -0,0 +1,41 @@ +rules: + - name: Coinlayer API Key + id: kingfisher.coinlayer.1 + pattern: | + (?xi) + \b + coinlayer + (?:.|[\n\r]){0,16}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) + (?:.|[\n\r]){0,16}? + \b + ( + [A-Za-z0-9]{32} + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - COINLAYER_ACCESS_KEY=abc123def456ghi789jkl012mno345pq + - coinlayer_access_key = "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" + references: + - https://coinlayer.com/documentation + - https://coinlayer.com/signup/free + validation: + type: Http + content: + request: + method: GET + url: https://api.coinlayer.com/live?access_key={{ TOKEN }} + headers: + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: StatusMatch + status: [401] + negative: true + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/contentstack.yml b/crates/kingfisher-rules/data/rules/contentstack.yml new file mode 100644 index 0000000..90774fb --- /dev/null +++ b/crates/kingfisher-rules/data/rules/contentstack.yml @@ -0,0 +1,62 @@ +rules: + - name: Contentstack API Key + id: kingfisher.contentstack.2 + pattern: | + (?xi) + \b + contentstack + (?:.|[\n\r]){0,32}? + (?:API[_\s]?KEY|STACK[_\s]?API[_\s]?KEY) + (?:.|[\n\r]){0,16}? + \b + ( + blt[a-f0-9]{10} + ) + \b + min_entropy: 3.0 + confidence: medium + visible: false + examples: + - CONTENTSTACK_API_KEY=blt1234567890 + - name: Contentstack Management Token + id: kingfisher.contentstack.1 + pattern: | + (?xi) + \b + contentstack + (?:.|[\n\r]){0,32}? + (?:MANAGEMENT[_\s]?TOKEN|AUTH[_\s]?TOKEN|TOKEN) + (?:.|[\n\r]){0,32}? + \b + ( + cs[a-f0-9]{32} + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - CONTENTSTACK_MANAGEMENT_TOKEN=cs1234567890abcdef1234567890abcdef + - contentstack_token = "csa1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4" + references: + - https://www.contentstack.com/docs/developers/create-tokens/overview-of-tokens + - https://www.contentstack.com/docs/developers/apis/content-management-api + validation: + type: Http + content: + request: + method: GET + url: "https://api.contentstack.io/v3/stacks" + headers: + api_key: "{{ APIKEY }}" + authorization: "Bearer {{ TOKEN }}" + Content-Type: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: JsonValid + depends_on_rule: + - rule_id: kingfisher.contentstack.2 + variable: APIKEY diff --git a/crates/kingfisher-rules/data/rules/currencylayer.yml b/crates/kingfisher-rules/data/rules/currencylayer.yml new file mode 100644 index 0000000..0c631c7 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/currencylayer.yml @@ -0,0 +1,41 @@ +rules: + - name: Currencylayer API Key + id: kingfisher.currencylayer.1 + pattern: | + (?xi) + \b + currencylayer + (?:.|[\n\r]){0,16}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) + (?:.|[\n\r]){0,16}? + \b + ( + [A-Za-z0-9]{32} + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - CURRENCYLAYER_ACCESS_KEY=abc123def456ghi789jkl012mno345pq + - currencylayer_access_key = "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" + references: + - https://currencylayer.com/documentation + - https://currencylayer.com/api-access + validation: + type: Http + content: + request: + method: GET + url: https://api.currencylayer.com/live?access_key={{ TOKEN }} + headers: + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: StatusMatch + status: [401] + negative: true + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/daily.yml b/crates/kingfisher-rules/data/rules/daily.yml new file mode 100644 index 0000000..c4a2b88 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/daily.yml @@ -0,0 +1,43 @@ +rules: + - name: Daily API Key + id: kingfisher.daily.1 + pattern: | + (?xi) + \b + daily + (?:.|[\n\r]){0,32}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN|API) + (?:.|[\n\r]){0,32}? + \b + ( + [A-Za-z0-9]{64} + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - DAILY_API_KEY=abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890 + - daily_api_key = "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6a7b8c9d0e1f2a3b4c5d6a7b8c9d0e1f2" + references: + - https://docs.daily.co/reference/rest-api + - https://docs.daily.co/reference/rest-api/rooms/list-rooms + validation: + type: Http + content: + request: + method: GET + url: https://api.daily.co/v1/rooms?limit=1 + headers: + Authorization: "Bearer {{ TOKEN }}" + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: WordMatch + words: + - '"data"' + - '"total_count"' + match_all_words: true diff --git a/crates/kingfisher-rules/data/rules/fixer.yml b/crates/kingfisher-rules/data/rules/fixer.yml new file mode 100644 index 0000000..3c309b1 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/fixer.yml @@ -0,0 +1,41 @@ +rules: + - name: Fixer.io API Key + id: kingfisher.fixer.1 + pattern: | + (?xi) + \b + fixer + (?:.|[\n\r]){0,16}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) + (?:.|[\n\r]){0,16}? + \b + ( + [A-Za-z0-9]{32} + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - FIXER_ACCESS_KEY=abc123def456ghi789jkl012mno345pq + - fixer_access_key = "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" + references: + - https://fixer.io/documentation + - https://fixer.io/api-key + validation: + type: Http + content: + request: + method: GET + url: https://data.fixer.io/api/latest?access_key={{ TOKEN }} + headers: + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: StatusMatch + status: [401] + negative: true + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/geoapify.yml b/crates/kingfisher-rules/data/rules/geoapify.yml new file mode 100644 index 0000000..7d3dfd0 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/geoapify.yml @@ -0,0 +1,38 @@ +rules: + - name: Geoapify API Key + id: kingfisher.geoapify.1 + pattern: | + (?xi) + \b + geoapify + (?:.|[\n\r]){0,16}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) + (?:.|[\n\r]){0,16}? + \b + ( + [A-Za-z0-9]{32} + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - geoapify_api_key = "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" + - GEOAPIFY_KEY=abcdef1234567890abcdef1234567890 + references: + - https://apidocs.geoapify.com/docs/geocoding/api/api + - https://apidocs.geoapify.com/docs/ip-geolocation + validation: + type: Http + content: + request: + method: GET + url: https://api.geoapify.com/v1/ipinfo?apiKey={{ TOKEN }} + headers: + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/hunterio.yml b/crates/kingfisher-rules/data/rules/hunterio.yml new file mode 100644 index 0000000..3f68ba7 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/hunterio.yml @@ -0,0 +1,40 @@ +rules: + - name: Hunter.io API Key + id: kingfisher.hunterio.1 + pattern: | + (?xi) + \b + hunter + (?:.|[\n\r]){0,16}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) + (?:.|[\n\r]){0,16}? + \b + ( + [A-Za-z0-9]{40} + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + ignore_if_contains: + - test-api-key + examples: + - hunter_api_key = "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6a7b8c9d0" + - HUNTER_KEY=abcdef1234567890abcdef1234567890abcdef12 + references: + - https://hunter.io/api/docs + - https://hunter.io/api-keys + validation: + type: Http + content: + request: + method: GET + url: https://api.hunter.io/v2/account?api_key={{ TOKEN }} + headers: + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/mux.yml b/crates/kingfisher-rules/data/rules/mux.yml new file mode 100644 index 0000000..9148726 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/mux.yml @@ -0,0 +1,59 @@ +rules: + - name: Mux Access Token ID + id: kingfisher.mux.2 + pattern: | + (?xi) + \b + mux + (?:.|[\n\r]){0,32}? + (?:TOKEN[_\s]?ID|ACCESS[_\s]?TOKEN[_\s]?ID) + (?:.|[\n\r]){0,16}? + \b + ( + [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} + ) + \b + min_entropy: 3.0 + confidence: medium + visible: false + examples: + - MUX_TOKEN_ID=44c819de-4add-4c9f-b2e9-384a0a71bede + - name: Mux Access Token Secret + id: kingfisher.mux.1 + pattern: | + (?xi) + \b + mux + (?:.|[\n\r]){0,32}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) + (?:.|[\n\r]){0,32}? + \b + ( + [A-Za-z0-9+/=]{75} + ) + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - MUX_TOKEN_SECRET=INKxCoZ+cX6l1yrR6vqzYHVaeFEcqvZShznWM1U/No8KsV7h6Jxu1XXuTUQ91sdiGONK3H7NE7H + references: + - https://docs.mux.com/core/make-api-requests + - https://docs.mux.com/api-reference/video/video/v1/assets + validation: + type: Http + content: + request: + method: GET + url: https://api.mux.com/video/v1/assets?limit=1 + headers: + Authorization: "Basic {{ MUXID | append: ':' | append: TOKEN | b64enc }}" + Content-Type: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: JsonValid + depends_on_rule: + - rule_id: kingfisher.mux.2 + variable: MUXID diff --git a/crates/kingfisher-rules/data/rules/newsapi.yml b/crates/kingfisher-rules/data/rules/newsapi.yml new file mode 100644 index 0000000..fae9010 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/newsapi.yml @@ -0,0 +1,40 @@ +rules: + - name: NewsAPI API Key + id: kingfisher.newsapi.1 + pattern: | + (?xi) + \b + newsapi + (?:.|[\n\r]){0,16}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) + (?:.|[\n\r]){0,16}? + \b + ( + [A-Za-z0-9]{32} + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - NEWSAPI_API_KEY=abc123def456ghi789jkl012mno345pq + - newsapi_key = "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" + references: + - https://newsapi.org/docs/authentication + validation: + type: Http + content: + request: + method: GET + url: https://newsapi.org/v2/everything?q=test&apiKey={{ TOKEN }} + headers: + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: StatusMatch + status: [401] + negative: true + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/numverify.yml b/crates/kingfisher-rules/data/rules/numverify.yml new file mode 100644 index 0000000..3460aa5 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/numverify.yml @@ -0,0 +1,41 @@ +rules: + - name: Numverify API Key + id: kingfisher.numverify.1 + pattern: | + (?xi) + \b + numverify + (?:.|[\n\r]){0,16}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) + (?:.|[\n\r]){0,16}? + \b + ( + [A-Za-z0-9]{32} + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - NUMVERIFY_ACCESS_KEY=abc123def456ghi789jkl012mno345pq + - numverify_access_key = "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" + references: + - https://numverify.com/documentation + - https://numverify.com/faq + validation: + type: Http + content: + request: + method: GET + url: https://apilayer.net/api/validate?access_key={{ TOKEN }}&number=14155551234 + headers: + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: StatusMatch + status: [401] + negative: true + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/onesignal.yml b/crates/kingfisher-rules/data/rules/onesignal.yml new file mode 100644 index 0000000..7595cb3 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/onesignal.yml @@ -0,0 +1,42 @@ +rules: + - name: OneSignal REST API Key + id: kingfisher.onesignal.1 + pattern: | + (?xi) + \b + onesignal + (?:.|[\n\r]){0,16}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) + (?:.|[\n\r]){0,16}? + \b + ( + [A-Za-z0-9]{32} + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - onesignal_rest_api_key = "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" + - ONESIGNAL_REST_API_KEY=abcdef1234567890abcdef1234567890 + references: + - https://documentation.onesignal.com/reference/rest-api-overview + - https://documentation.onesignal.com/docs/keys-and-ids + validation: + type: Http + content: + request: + method: GET + url: https://api.onesignal.com/apps + headers: + Authorization: "Key {{ TOKEN }}" + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: StatusMatch + status: [401, 403] + negative: true + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/pinecone.yml b/crates/kingfisher-rules/data/rules/pinecone.yml new file mode 100644 index 0000000..0c0c995 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/pinecone.yml @@ -0,0 +1,39 @@ +rules: + - name: Pinecone API Key + id: kingfisher.pinecone.1 + pattern: | + (?xi) + \b + pinecone + (?:.|[\n\r]){0,32}? + (?:SECRET|PRIVATE|API|KEY|TOKEN) + (?:.|[\n\r]){0,16}? + \b + ( + [0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12} + ) + \b + pattern_requirements: + min_digits: 2 + min_entropy: 3.0 + confidence: medium + examples: + - PINECONE_API_KEY=62b0dbfe-3489-4b79-b850-34d911527c88 + - pinecone_key = "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + references: + - https://docs.pinecone.io/reference/api/authentication + - https://docs.pinecone.io/reference/api/2025-10/control-plane/list_indexes + validation: + type: Http + content: + request: + method: GET + url: https://api.pinecone.io/indexes + headers: + Api-Key: "{{ TOKEN }}" + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/pingdom.yml b/crates/kingfisher-rules/data/rules/pingdom.yml new file mode 100644 index 0000000..ba75aa4 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/pingdom.yml @@ -0,0 +1,42 @@ +rules: + - name: Pingdom API Token + id: kingfisher.pingdom.1 + pattern: | + (?xi) + \b + pingdom + (?:.|[\n\r]){0,16}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) + (?:.|[\n\r]){0,16}? + \b + ( + [A-Za-z0-9_-]{64} + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - pingdom_api_token = "ofOhK18Ca6w4S_XmInGv0QPkqly-rbRBBoHsp_2FEH5QnIbH0VZhRPO3tlvrjMIK" + - PINGDOM_TOKEN=abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890 + references: + - https://docs.pingdom.com/api/ + - https://pingdom.com/resources/pingdom-api + validation: + type: Http + content: + request: + method: GET + url: https://api.pingdom.com/api/3.1/checks + headers: + Authorization: "Bearer {{ TOKEN }}" + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: StatusMatch + status: [401, 403] + negative: true + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/positionstack.yml b/crates/kingfisher-rules/data/rules/positionstack.yml new file mode 100644 index 0000000..0bb58a2 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/positionstack.yml @@ -0,0 +1,40 @@ +rules: + - name: Positionstack API Key + id: kingfisher.positionstack.1 + pattern: | + (?xi) + \b + positionstack + (?:.|[\n\r]){0,16}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) + (?:.|[\n\r]){0,16}? + \b + ( + [A-Za-z0-9]{32} + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - positionstack_access_key = "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" + - POSITIONSTACK_KEY=1234567890abcdef1234567890abcdef + references: + - https://positionstack.com/documentation + validation: + type: Http + content: + request: + method: GET + url: https://api.positionstack.com/v1/forward?access_key={{ TOKEN }}&query=London + headers: + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: StatusMatch + status: [401, 403] + negative: true + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/railway.yml b/crates/kingfisher-rules/data/rules/railway.yml new file mode 100644 index 0000000..2392d69 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/railway.yml @@ -0,0 +1,44 @@ +rules: + - name: Railway API Token + id: kingfisher.railway.1 + pattern: | + (?xi) + \b + railway + (?:.|[\n\r]){0,32}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN|API) + (?:.|[\n\r]){0,32}? + \b + ( + (?:[A-Za-z0-9]{32}|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}) + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - RAILWAY_API_TOKEN=abcdef1234567890abcdef1234567890 + - railway_token = "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + references: + - https://docs.railway.com/guides/public-api + - https://docs.railway.com/reference/oauth/login-and-tokens + validation: + type: Http + content: + request: + method: POST + url: https://backboard.railway.com/graphql/v2 + headers: + Authorization: "Bearer {{ TOKEN }}" + Content-Type: application/json + body: '{"query":"query { me { name email } }"}' + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: WordMatch + words: + - '"data"' + - '"me"' + match_all_words: true diff --git a/crates/kingfisher-rules/data/rules/render.yml b/crates/kingfisher-rules/data/rules/render.yml new file mode 100644 index 0000000..4848411 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/render.yml @@ -0,0 +1,39 @@ +rules: + - name: Render API Key + id: kingfisher.render.1 + pattern: | + (?xi) + \b + render + (?:.|[\n\r]){0,32}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN|API) + (?:.|[\n\r]){0,32}? + \b + ( + (?:[A-Za-z0-9]{32}|rnd_[A-Za-z0-9]{33}) + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - RENDER_API_KEY=abcdef1234567890abcdef1234567890 + - render_api_key = "rnd_abc123def456ghi789jkl012mno345pqr" + references: + - https://docs.render.com/api + - https://api-docs.render.com/docs + validation: + type: Http + content: + request: + method: GET + url: https://api.render.com/v1/services?limit=1 + headers: + Authorization: "Bearer {{ TOKEN }}" + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/rollbar.yml b/crates/kingfisher-rules/data/rules/rollbar.yml new file mode 100644 index 0000000..436fa9f --- /dev/null +++ b/crates/kingfisher-rules/data/rules/rollbar.yml @@ -0,0 +1,42 @@ +rules: + - name: Rollbar Access Token + id: kingfisher.rollbar.1 + pattern: | + (?xi) + \b + rollbar + (?:.|[\n\r]){0,32}? + (?:access[_-]?token|token|key) + (?:.|[\n\r]){0,16}? + \b + ( + [A-Za-z0-9]{32} + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - rollbar_access_token = "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" + - ROLLBAR_ACCESS_TOKEN=abcdef1234567890abcdef1234567890 + references: + - https://docs.rollbar.com/docs/access-tokens + - https://docs.rollbar.com/reference/getting-started-1 + validation: + type: Http + content: + request: + method: GET + url: https://api.rollbar.com/api/1/projects + headers: + X-Rollbar-Access-Token: "{{ TOKEN }}" + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: StatusMatch + status: [403] + negative: true + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/salesloft.yml b/crates/kingfisher-rules/data/rules/salesloft.yml new file mode 100644 index 0000000..f64d75b --- /dev/null +++ b/crates/kingfisher-rules/data/rules/salesloft.yml @@ -0,0 +1,39 @@ +rules: + - name: Salesloft API Key + id: kingfisher.salesloft.1 + pattern: | + (?xi) + \b + salesloft + (?:.|[\n\r]){0,32}? + (?:SECRET|PRIVATE|API|KEY|TOKEN) + (?:.|[\n\r]){0,16}? + \b + ( + ak_[a-fA-F0-9]{64} + ) + \b + pattern_requirements: + min_digits: 2 + min_entropy: 3.2 + confidence: medium + examples: + - SALESLOFT_API_KEY=ak_de656ec86bcab24878c24ff4d86758f8963d8ea6bcd4e90f8fae846ba8f9ac62 + - salesloft_key = "ak_1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" + references: + - https://developer.salesloft.com/docs/platform/api-basics/api-key-authentication + - https://developers.salesloft.com/docs/api/me + validation: + type: Http + content: + request: + method: GET + url: https://api.salesloft.com/v2/me + headers: + Authorization: "Bearer {{ TOKEN }}" + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/sanity.yml b/crates/kingfisher-rules/data/rules/sanity.yml new file mode 100644 index 0000000..0fd13c2 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/sanity.yml @@ -0,0 +1,39 @@ +rules: + - name: Sanity API Token + id: kingfisher.sanity.1 + pattern: | + (?xi) + \b + sanity + (?:.|[\n\r]){0,32}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN|API) + (?:.|[\n\r]){0,32}? + \b + ( + (?:sk[A-Za-z0-9]{52}|sk[A-Za-z0-9]{78}) + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - SANITY_API_TOKEN=skE5UXUmBEy7U50jcG4In4v4xoHZTlduDxQYet8Y84tsTqAZxp2reIPJsA1JzqXJno2qcpauGwPfjHpU + - sanity_token = "sk1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdef" + references: + - https://www.sanity.io/docs/content-lake/http-auth + - https://www.sanity.io/docs/projects-api + validation: + type: Http + content: + request: + method: GET + url: https://api.sanity.io/v2021-06-07/projects + headers: + Authorization: "Bearer {{ TOKEN }}" + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/statuscake.yml b/crates/kingfisher-rules/data/rules/statuscake.yml new file mode 100644 index 0000000..da30768 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/statuscake.yml @@ -0,0 +1,41 @@ +rules: + - name: StatusCake API Token + id: kingfisher.statuscake.1 + pattern: | + (?xi) + \b + statuscake + (?:.|[\n\r]){0,16}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) + (?:.|[\n\r]){0,16}? + \b + ( + [A-Za-z0-9_-]{20} + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - statuscake_api_token = "a1b2c3d4e5f6g7h8i9j0" + - STATUSCAKE_TOKEN=abcdef1234567890abcd + references: + - https://developers.statuscake.com/guides/api/authentication/ + - https://developers.statuscake.com/api + validation: + type: Http + content: + request: + method: GET + url: https://api.statuscake.com/v1/uptime + headers: + Authorization: "Bearer {{ TOKEN }}" + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: StatusMatch + status: [401, 403] + negative: true diff --git a/crates/kingfisher-rules/data/rules/storyblok.yml b/crates/kingfisher-rules/data/rules/storyblok.yml new file mode 100644 index 0000000..833fe81 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/storyblok.yml @@ -0,0 +1,38 @@ +rules: + - name: Storyblok API Token + id: kingfisher.storyblok.1 + pattern: | + (?xi) + \b + storyblok + (?:.|[\n\r]){0,32}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN|API) + (?:.|[\n\r]){0,32}? + \b + ( + [A-Za-z0-9]{22}tt + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - STORYBLOK_ACCESS_TOKEN=wANpEQEsMYGOwLxwXQ76Ggtt + - storyblok_token = "13Kft3335iwbBOI333wawOtt" + references: + - https://www.storyblok.com/docs/api/content-delivery/v2/getting-started/authentication + - https://www.storyblok.com/docs/concepts/access-tokens + validation: + type: Http + content: + request: + method: GET + url: "https://api.storyblok.com/v2/cdn/stories?token={{ TOKEN }}&version=published&per_page=1" + headers: + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/uptimerobot.yml b/crates/kingfisher-rules/data/rules/uptimerobot.yml new file mode 100644 index 0000000..2e7a517 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/uptimerobot.yml @@ -0,0 +1,38 @@ +rules: + - name: UptimeRobot API Key + id: kingfisher.uptimerobot.1 + pattern: | + (?xi) + \b + uptimerobot + (?:.|[\n\r]){0,16}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) + (?:.|[\n\r]){0,16}? + \b + ( + (?:ur[A-Za-z0-9-]{29}|[A-Za-z0-9]{28}) + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - uptimerobot_api_key = "ur123456-7890abcdef1234567890ab" + - UPTIMEROBOT_KEY=abcdef1234567890abcdef123456 + references: + - https://uptimerobot.com/api/v3 + - https://help.uptimerobot.com/en/articles/11620152-how-to-use-uptimerobot-s-api + validation: + type: Http + content: + request: + method: GET + url: https://api.uptimerobot.com/v2/getMonitors?api_key={{ TOKEN }}&format=json + headers: + Content-Type: application/x-www-form-urlencoded + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/urlscan.yml b/crates/kingfisher-rules/data/rules/urlscan.yml new file mode 100644 index 0000000..0c66e77 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/urlscan.yml @@ -0,0 +1,39 @@ +rules: + - name: urlscan.io API Key + id: kingfisher.urlscan.1 + pattern: | + (?xi) + \b + urlscan + (?:.|[\n\r]){0,16}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) + (?:.|[\n\r]){0,16}? + \b + ( + (?:[A-Za-z0-9]{32}|[A-Za-z0-9]{36}) + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - urlscan_api_key = "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8" + - URLSCAN_KEY=abcdef1234567890abcdef1234567890 + references: + - https://urlscan.io/docs/api/ + - https://docs.urlscan.io/ + validation: + type: Http + content: + request: + method: GET + url: https://urlscan.io/user/quotas/ + headers: + API-Key: "{{ TOKEN }}" + Content-Type: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/virustotal.yml b/crates/kingfisher-rules/data/rules/virustotal.yml new file mode 100644 index 0000000..4884482 --- /dev/null +++ b/crates/kingfisher-rules/data/rules/virustotal.yml @@ -0,0 +1,42 @@ +rules: + - name: VirusTotal API Key + id: kingfisher.virustotal.1 + pattern: | + (?xi) + \b + virustotal + (?:.|[\n\r]){0,32}? + (?:api[_-]?key|x[_-]?apikey|key) + (?:.|[\n\r]){0,16}? + \b + ( + [A-Za-z0-9]{64} + ) + \b + min_entropy: 3.6 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - VIRUSTOTAL_API_KEY=abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890 + - virustotal_x_apikey = "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2" + references: + - https://docs.virustotal.com/reference/authentication + - https://docs.virustotal.com/docs/please-give-me-an-api-key + validation: + type: Http + content: + request: + method: GET + url: https://www.virustotal.com/api/v3/domains/google.com + headers: + x-apikey: "{{ TOKEN }}" + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: StatusMatch + status: [401, 403] + negative: true + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/weatherapi.yml b/crates/kingfisher-rules/data/rules/weatherapi.yml new file mode 100644 index 0000000..cd5271b --- /dev/null +++ b/crates/kingfisher-rules/data/rules/weatherapi.yml @@ -0,0 +1,40 @@ +rules: + - name: WeatherAPI.com API Key + id: kingfisher.weatherapi.1 + pattern: | + (?xi) + \b + weatherapi + (?:.|[\n\r]){0,16}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) + (?:.|[\n\r]){0,16}? + \b + ( + [A-Za-z0-9]{32} + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - WEATHERAPI_KEY=abc123def456ghi789jkl012mno345pq + - weatherapi_key = "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" + references: + - https://www.weatherapi.com/docs/ + validation: + type: Http + content: + request: + method: GET + url: https://api.weatherapi.com/v1/current.json?key={{ TOKEN }}&q=London + headers: + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: StatusMatch + status: [401] + negative: true + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/webflow.yml b/crates/kingfisher-rules/data/rules/webflow.yml new file mode 100644 index 0000000..62bf0ac --- /dev/null +++ b/crates/kingfisher-rules/data/rules/webflow.yml @@ -0,0 +1,39 @@ +rules: + - name: Webflow API Token + id: kingfisher.webflow.1 + pattern: | + (?xi) + \b + webflow + (?:.|[\n\r]){0,32}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN|API) + (?:.|[\n\r]){0,32}? + \b + ( + (?:[A-Za-z0-9]{32}|[A-Za-z0-9]{36}) + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - WEBFLOW_API_TOKEN=abcdef1234567890abcdef1234567890 + - webflow_token = "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8" + references: + - https://developers.webflow.com/data/reference/authentication + - https://developers.webflow.com/data/reference/rest-introduction/quick-start + validation: + type: Http + content: + request: + method: GET + url: https://api.webflow.com/v2/sites + headers: + Authorization: "Bearer {{ TOKEN }}" + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: JsonValid diff --git a/crates/kingfisher-rules/data/rules/zerobounce.yml b/crates/kingfisher-rules/data/rules/zerobounce.yml new file mode 100644 index 0000000..1c0ecdf --- /dev/null +++ b/crates/kingfisher-rules/data/rules/zerobounce.yml @@ -0,0 +1,38 @@ +rules: + - name: ZeroBounce API Key + id: kingfisher.zerobounce.1 + pattern: | + (?xi) + \b + zerobounce + (?:.|[\n\r]){0,16}? + (?:SECRET|PRIVATE|ACCESS|KEY|TOKEN) + (?:.|[\n\r]){0,16}? + \b + ( + [A-Za-z0-9]{32} + ) + \b + min_entropy: 3.5 + confidence: medium + pattern_requirements: + min_digits: 2 + examples: + - zerobounce_api_key = "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" + - ZEROBOUNCE_KEY=abcdef1234567890abcdef1234567890 + references: + - https://www.zerobounce.net/docs/email-validation-api-quickstart/ + - https://api.zerobounce.net/v2/validate + validation: + type: Http + content: + request: + method: GET + url: https://api.zerobounce.net/v2/validate?api_key={{ TOKEN }}&email=test@example.com&ip_address= + headers: + Accept: application/json + response_matcher: + - report_response: true + - type: StatusMatch + status: [200] + - type: JsonValid