fixed github actions

This commit is contained in:
Mick Grove 2026-03-29 10:41:54 -07:00
commit 482a60bb9d
15 changed files with 716 additions and 53 deletions

View file

@ -1,49 +0,0 @@
name: SLSA Provenance
on:
release:
types: [published]
permissions: {}
jobs:
# Compute SHA256 hashes of all release assets
hash:
name: Compute artifact hashes
runs-on: ubuntu-24.04
permissions:
contents: read
outputs:
hashes: ${{ steps.hash.outputs.hashes }}
steps:
- name: Download release assets
env:
GH_TOKEN: ${{ github.token }}
TAG_NAME: ${{ github.event.release.tag_name }}
run: |
set -euo pipefail
mkdir -p assets
gh release download "${TAG_NAME}" \
--repo "${{ github.repository }}" \
--dir assets
- name: Compute SHA256 hashes
id: hash
run: |
set -euo pipefail
cd assets
# Base64-encode the SHA256 hashes for SLSA provenance
echo "hashes=$(sha256sum -- * | base64 -w0)" >> "$GITHUB_OUTPUT"
# Generate SLSA provenance for the release artifacts
provenance:
name: Generate SLSA provenance
needs: [hash]
permissions:
actions: read
id-token: write
contents: write
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@f7dd8c54c2067bafc12ca7a55595d5ee9b75204a # v2.1.0
with:
base64-subjects: "${{ needs.hash.outputs.hashes }}"
upload-assets: true

View file

@ -408,6 +408,46 @@ jobs:
with:
subject-path: 'target/release/*'
# ──────────────── SLSA Provenance ────────────────
hash:
name: Compute artifact hashes
needs: [release]
runs-on: ubuntu-24.04
permissions:
contents: read
outputs:
hashes: ${{ steps.hash.outputs.hashes }}
steps:
- name: Download release assets
env:
GH_TOKEN: ${{ github.token }}
TAG_NAME: ${{ needs.release.outputs.tag }}
run: |
set -euo pipefail
mkdir -p assets
gh release download "${TAG_NAME}" \
--repo "${{ github.repository }}" \
--dir assets
- name: Compute SHA256 hashes
id: hash
run: |
set -euo pipefail
cd assets
echo "hashes=$(sha256sum -- * | base64 -w0)" >> "$GITHUB_OUTPUT"
provenance:
name: Generate SLSA provenance
needs: [hash]
permissions:
actions: read
id-token: write
contents: write
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@f7dd8c54c2067bafc12ca7a55595d5ee9b75204a # v2.1.0
with:
base64-subjects: "${{ needs.hash.outputs.hashes }}"
upload-assets: true
# ──────────────── Publish Docker image ────────────────
publish-docker:
needs: [release]

View file

@ -3,8 +3,10 @@
All notable changes to this project will be documented in this file.
## [v1.92.0]
- Added new built-in rules for Etsy, Flutterwave, Freemius, JFrog, Kraken, KuCoin, and Trello, plus recent Betterleaks-derived additions including Octopus Deploy, OpenShift, Private AI, SettleMint, Sidekiq, and Polymarket.
- Added new built-in rules for Etsy, Flutterwave, Freemius, JFrog, Kraken, KuCoin, Trello, Octopus Deploy, OpenShift, Private AI, SettleMint, Sidekiq, and Polymarket.
- Added live HTTP validation for Etsy, JFrog, Octopus Deploy, OpenShift, and Private AI where provider documentation supported reliable token-only checks.
- Added detection + validation rules for Anthropic Admin, Azure Speech, Azure Translator, Databento, DataStax Astra, DevCycle, Fullstory, GC Notify, and Stytch; built-in runtime rule count is now 601 with `--confidence=low`.
- Added Heroku token revocation support for both legacy UUID-format tokens and `HRKU-` platform tokens via the OAuth authorizations API.
## [v1.91.0]
- Added SSRF protection for credential validation: outbound HTTP requests now block connections to loopback, private, link-local, and other non-public IP addresses. HTTP redirect targets are DNS-resolved and validated against the same SSRF rules. Use `--allow-internal-ips` to opt out when scanning internal infrastructure.

View file

@ -4,7 +4,7 @@
<img src="docs/kingfisher_logo.png" alt="Kingfisher Logo" width="126" height="173" style="vertical-align: right;" />
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![Detection Rules](https://img.shields.io/badge/Detection%20Rules-548-2ea043.svg)](https://github.com/mongodb/kingfisher)<br>
[![Detection Rules](https://img.shields.io/badge/Detection%20Rules-601-2ea043.svg)](https://github.com/mongodb/kingfisher)<br>
[![ghcr downloads](https://ghcr-badge.elias.eu.org/shield/mongodb/kingfisher/kingfisher)](https://github.com/mongodb/kingfisher/pkgs/container/kingfisher)<br>
@ -302,6 +302,40 @@ Kingfisher supports multiple installation methods:
**For complete installation instructions and pre-commit hook setup, see [docs/INSTALLATION.md](docs/INSTALLATION.md).**
## Verifying Releases
Every Kingfisher release includes [SLSA v3](https://slsa.dev) provenance and GitHub build attestations so you can verify that artifacts were built by our CI pipeline and haven't been tampered with.
### SLSA provenance
Each GitHub release includes a `multiple.intoto.jsonl` provenance file. Verify any release artifact with [`slsa-verifier`](https://github.com/slsa-framework/slsa-verifier):
```bash
# Install slsa-verifier
go install github.com/slsa-framework/slsa-verifier/v2/cli/slsa-verifier@latest
# Download the artifact and provenance from the release
gh release download v1.91.0 --repo mongodb/kingfisher \
--pattern 'kingfisher-linux-x64.tgz' \
--pattern 'multiple.intoto.jsonl'
# Verify
slsa-verifier verify-artifact kingfisher-linux-x64.tgz \
--provenance-path multiple.intoto.jsonl \
--source-uri github.com/mongodb/kingfisher
```
### GitHub attestations
Release artifacts also have GitHub build attestations, verifiable with the GitHub CLI:
```bash
gh release download v1.91.0 --repo mongodb/kingfisher \
--pattern 'kingfisher-linux-x64.tgz'
gh attestation verify kingfisher-linux-x64.tgz --repo mongodb/kingfisher
```
# Detection Rules
Kingfisher ships with [hundreds of rules](crates/kingfisher-rules/data/rules/) that cover everything from classic cloud keys to the latest AI SaaS tokens. Below is an overview:

View file

@ -30,8 +30,27 @@ Strongly recommended fields:
## Pattern Quality Rules
- Prefer specific anchors/prefixes and provider context over broad generic regex.
- When the token format is generic or common-looking (for example bare 32-hex keys), prefer contextual patterns of the form: provider keyword -> short flexible gap -> key/secret label -> short flexible gap -> token. A good default is:
- `\b`
- provider identifier (for example `amplitude`, `azure`, `speech`, `translator`)
- `(?:.|[\n\r]){0,N}?`
- common credential labels such as `(?:SECRET|PRIVATE|ACCESS|KEY|TOKEN|AUTHORIZATION|API)`
- `(?:.|[\n\r]){0,M}?`
- the token capture wrapped in a single unnamed capture group
- Do not add surrounding context when the token is already strongly self-identifying by prefix or structure (for example `sk-ant-api...`, `AstraCS:...`, `dvc_client_...`, `secret-test-...`). In those cases, prefer the tighter self-identifying 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 checksum validation in `pattern_requirements.checksum` when token formats support it. This is preferred when the provider token format includes a documented or reverse-engineered check segment, because it can sharply reduce false positives without adding brittle surrounding context.
- For checksum-based rules, prefer named captures for the main token body and checksum suffix/prefix, then compute the expected checksum in Liquid. A typical pattern is:
- `(
prefix_(?P<body>...)(?P<checksum>...)
)`
- with:
- `actual.template: "{{ checksum }}"`
- `actual.requires_capture: checksum`
- `expected: "{{ body | <checksum-filter> | <encoding/filter chain> }}"`
- `skip_if_missing: true`
- Example: GitHub PATs use a CRC32-derived base62 checksum. The rule in `github.yml` captures `body` and `checksum`, then compares `{{ checksum }}` against `{{ body | crc32 | base62: 6 }}`.
- Prefer checksum validation over extra loose context whenever the token structure itself supports it. If the checksum is only present on some token generations, keep `skip_if_missing: true` so older examples continue to load safely.
- 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).

View file

@ -47,4 +47,38 @@ rules:
words:
- '"type":"message"'
- 'credit balance is too low'
url: https://api.anthropic.com/v1/messages
url: https://api.anthropic.com/v1/messages
- name: Anthropic Admin API Key
id: kingfisher.anthropic.2
pattern: |
(?xi)
(
sk-ant-admin(?:\d{2,4})?-[A-Za-z0-9_-]{40,}
)
pattern_requirements:
min_digits: 2
min_uppercase: 1
min_lowercase: 1
min_entropy: 3.5
confidence: medium
examples:
- sk-ant-admin03-4mB9zY2Qx8LmN7pR5sT1uV6wX0aBcDeFgHiJkLmNoPqRsTuVwXyZ1234
references:
- https://docs.anthropic.com/en/api/administration-api
- https://docs.anthropic.com/en/api/admin-api/organization/get-me
validation:
type: Http
content:
request:
method: GET
url: https://api.anthropic.com/v1/organizations/me
headers:
x-api-key: '{{ TOKEN }}'
anthropic-version: "2023-06-01"
content-type: application/json
response_matcher:
- report_response: true
- type: StatusMatch
status: [200]
- type: JsonValid

View file

@ -0,0 +1,84 @@
rules:
- name: Azure Speech Region
id: kingfisher.azurespeech.1
visible: false
pattern: |
(?xi)
\b
(?:
SPEECH_REGION
|
AZURE_SPEECH_REGION
|
speech[_-]?region
|
azure[_-]?speech[_-]?region
)
\b
(?:.|[\n\r]){0,16}?
[=:]
\s*["']?
(
[a-z0-9-]{4,32}
)
["']?
min_entropy: 1.5
confidence: medium
examples:
- SPEECH_REGION=eastus
- azure_speech_region="westus2"
references:
- https://learn.microsoft.com/en-us/azure/ai-services/speech-service/rest-text-to-speech
- name: Azure Speech API Key
id: kingfisher.azurespeech.2
pattern: |
(?xi)
\b
(?:
speech
|
azure[_-]?speech
)
(?:.|[\n\r]){0,24}?
(?:
key
|
api[_-]?key
|
subscription[_-]?key
|
secret
)
(?:.|[\n\r]){0,16}?
(
[a-f0-9]{32}
)
\b
pattern_requirements:
min_digits: 2
min_lowercase: 2
min_entropy: 3.5
confidence: medium
examples:
- AZURE_SPEECH_KEY=1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d
- speech_subscription_key="abcdef0123456789abcdef0123456789"
references:
- https://learn.microsoft.com/en-us/azure/ai-services/speech-service/rest-text-to-speech
depends_on_rule:
- rule_id: kingfisher.azurespeech.1
variable: AZURE_SPEECH_REGION
validation:
type: Http
content:
request:
method: POST
url: https://{{ AZURE_SPEECH_REGION }}.api.cognitive.microsoft.com/sts/v1.0/issueToken
headers:
Ocp-Apim-Subscription-Key: "{{ TOKEN }}"
Content-Type: application/x-www-form-urlencoded
Content-Length: "0"
response_matcher:
- report_response: true
- type: StatusMatch
status: [200]

View file

@ -0,0 +1,97 @@
rules:
- name: Azure Translator Region
id: kingfisher.azuretranslator.1
visible: false
pattern: |
(?xi)
\b
(?:
TRANSLATOR_REGION
|
AZURE_TRANSLATOR_REGION
|
translator[_-]?region
|
translation[_-]?region
|
Ocp-Apim-Subscription-Region
)
\b
(?:.|[\n\r]){0,16}?
[=:]
\s*["']?
(
[a-z0-9-]{4,32}
)
["']?
min_entropy: 1.5
confidence: medium
examples:
- TRANSLATOR_REGION=eastus
- azure_translator_region="westeurope"
references:
- https://learn.microsoft.com/en-us/azure/ai-services/translator/text-translation/reference/authentication
- https://learn.microsoft.com/en-us/azure/ai-services/translator/reference/v3-0-reference
- name: Azure Translator API Key
id: kingfisher.azuretranslator.2
pattern: |
(?xi)
\b
(?:
translator
|
translation
|
azure[_-]?(?:translator|translation)
)
(?:.|[\n\r]){0,24}?
(?:
key
|
api[_-]?key
|
subscription[_-]?key
|
secret
)
(?:.|[\n\r]){0,16}?
(
[a-f0-9]{32}
)
\b
pattern_requirements:
min_digits: 2
min_lowercase: 2
min_entropy: 3.5
confidence: medium
examples:
- AZURE_TRANSLATOR_KEY=1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d
- translator_subscription_key="abcdef0123456789abcdef0123456789"
references:
- https://learn.microsoft.com/en-us/azure/ai-services/translator/text-translation/reference/authentication
- https://learn.microsoft.com/en-us/azure/ai-services/translator/reference/v3-0-reference
depends_on_rule:
- rule_id: kingfisher.azuretranslator.1
variable: AZURE_TRANSLATOR_REGION
validation:
type: Http
content:
request:
method: POST
url: https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&to=es
headers:
Ocp-Apim-Subscription-Key: "{{ TOKEN }}"
Ocp-Apim-Subscription-Region: "{{ AZURE_TRANSLATOR_REGION }}"
Content-Type: application/json
body: |
[
{
"Text": "hello"
}
]
response_matcher:
- report_response: true
- type: StatusMatch
status: [200]
- type: JsonValid

View file

@ -0,0 +1,34 @@
rules:
- name: Databento API Key
id: kingfisher.databento.1
pattern: |
(?x)
\b
(
db-[A-Za-z0-9]{29}
)
\b
pattern_requirements:
min_digits: 2
min_lowercase: 2
min_entropy: 3.3
confidence: medium
examples:
- DATABENTO_API_KEY=db-abc123def456ghi789jkl012mno34
references:
- https://databento.com/docs/api-reference-historical
- https://databento.com/docs/portal/api-keys
validation:
type: Http
content:
request:
method: GET
url: https://hist.databento.com/v0/metadata.list_datasets
headers:
Authorization: "Basic {{ TOKEN | append: ':' | b64enc }}"
Accept: application/json
response_matcher:
- report_response: true
- type: StatusMatch
status: [200]
- type: JsonValid

View file

@ -0,0 +1,33 @@
rules:
- name: DataStax Astra Application Token
id: kingfisher.datastax.1
pattern: |
(?x)
\b
(
AstraCS:[A-Za-z0-9]{20,}
)
\b
pattern_requirements:
min_digits: 2
min_entropy: 4.0
confidence: medium
examples:
- ASTRA_DB_APPLICATION_TOKEN=AstraCS:Q29kZXhWYWxpZGF0aW9uVG9rZW5FeGFtcGxlMTIzNDU2Nzg5
references:
- https://docs.datastax.com/en/astra-db-serverless/administration/manage-application-tokens.html
- https://docs.datastax.com/en/astra-db-classic/api-reference/devops-api.html
validation:
type: Http
content:
request:
method: GET
url: https://api.astra.datastax.com/v2/databases
headers:
Authorization: Bearer {{ TOKEN }}
Accept: application/json
response_matcher:
- report_response: true
- type: StatusMatch
status: [200]
- type: JsonValid

View file

@ -0,0 +1,117 @@
rules:
- name: DevCycle Client SDK Key
id: kingfisher.devcycle.1
pattern: |
(?x)
\b
(
dvc_client_[A-Za-z0-9]{8,32}
)
\b
pattern_requirements:
min_digits: 2
min_lowercase: 2
min_entropy: 3.0
confidence: medium
examples:
- dvc_client_abc12345
- 'sdkKey: "dvc_client_abcdefg1234"'
references:
- https://docs.devcycle.com/cli-guides/environments/
- https://docs.devcycle.com/bucketing-api/
validation:
type: Http
content:
request:
method: POST
url: https://bucketing-api.devcycle.com/v1/variables
headers:
Authorization: Bearer {{ TOKEN }}
Content-Type: application/json
body: |
{
"user_id": "kingfisher-validation-user"
}
response_matcher:
- report_response: true
- type: StatusMatch
status: [200]
- type: JsonValid
- name: DevCycle Mobile SDK Key
id: kingfisher.devcycle.2
pattern: |
(?x)
\b
(
dvc_mobile_[A-Za-z0-9]{8,32}
)
\b
pattern_requirements:
min_digits: 2
min_lowercase: 2
min_entropy: 3.0
confidence: medium
examples:
- dvc_mobile_abc12345
- 'mobileKey: "dvc_mobile_abcdefg1234"'
references:
- https://docs.devcycle.com/cli-guides/environments/
- https://docs.devcycle.com/bucketing-api/
validation:
type: Http
content:
request:
method: POST
url: https://bucketing-api.devcycle.com/v1/variables
headers:
Authorization: Bearer {{ TOKEN }}
Content-Type: application/json
body: |
{
"user_id": "kingfisher-validation-user"
}
response_matcher:
- report_response: true
- type: StatusMatch
status: [200]
- type: JsonValid
- name: DevCycle Server SDK Key
id: kingfisher.devcycle.3
pattern: |
(?x)
\b
(
dvc_server_[A-Za-z0-9]{8,32}
)
\b
pattern_requirements:
min_digits: 2
min_lowercase: 2
min_entropy: 3.0
confidence: medium
examples:
- dvc_server_abc12345
- 'serverKey: "dvc_server_abcdefg1234"'
references:
- https://docs.devcycle.com/cli-guides/environments/
- https://docs.devcycle.com/bucketing-api/
validation:
type: Http
content:
request:
method: POST
url: https://bucketing-api.devcycle.com/v1/variables
headers:
Authorization: Bearer {{ TOKEN }}
Content-Type: application/json
body: |
{
"user_id": "kingfisher-validation-user"
}
response_matcher:
- report_response: true
- type: StatusMatch
status: [200]
- type: JsonValid

View file

@ -0,0 +1,41 @@
rules:
- name: Fullstory API Key
id: kingfisher.fullstory.1
pattern: |
(?xi)
\b
(?:fullstory|fs_api_key|fullstory_api_key)
(?:.|[\n\r]){0,32}?
(?:SECRET|PRIVATE|ACCESS|KEY|TOKEN|AUTHORIZATION|API)
(?:.|[\n\r]){0,16}?
\b
(
(?:na1|eu1)\.[A-Za-z0-9]{20,}
)
\b
pattern_requirements:
min_digits: 2
min_lowercase: 2
min_entropy: 3.3
confidence: medium
examples:
- FULLSTORY_API_KEY=na1.Abcd1234Efgh5678Ijkl9012Mnop3456
- 'fs_api_key: "eu1.Abcd1234Efgh5678Ijkl9012Mnop3456"'
references:
- https://developer.fullstory.com/server/v1/getting-started/
- https://developer.fullstory.com/server/authentication/
- https://developer.fullstory.com/server/v1/authentication/me/
validation:
type: Http
content:
request:
method: GET
url: https://api.fullstory.com/me
headers:
Authorization: Basic {{ TOKEN }}
Accept: application/json
response_matcher:
- report_response: true
- type: StatusMatch
status: [200]
- type: JsonValid

View file

@ -0,0 +1,41 @@
rules:
- name: GC Notify API Key
id: kingfisher.gcnotify.1
pattern: |
(?xi)
\b
(
ApiKey-v1
\s+
gcntfy-[a-z0-9_]+
-
[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}
-
[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: 4
min_lowercase: 2
min_entropy: 3.5
confidence: medium
examples:
- 'Authorization: "ApiKey-v1 gcntfy-my_test_key-26785a09-ab16-4eb0-8407-a37497a57506-3d844edf-8d35-48ac-975b-e847b4f122b0"'
references:
- https://documentation.notification.canada.ca/en/start.html
- https://documentation.notification.canada.ca/en/status.html
- https://documentation.notification.canada.ca/en/keys.html
validation:
type: Http
content:
request:
method: GET
url: https://api.notification.canada.ca/v2/notifications
headers:
Authorization: "{{ TOKEN }}"
Accept: application/json
response_matcher:
- report_response: true
- type: StatusMatch
status: [200]
- type: JsonValid

View file

@ -20,6 +20,7 @@ rules:
- 'HEROKU_API_KEY: c55dbac4-e0e8-4a06-b892-75cac2387ce5'
references:
- https://devcenter.heroku.com/articles/authentication
- https://devcenter.heroku.com/articles/oauth
validation:
type: Http
content:
@ -33,6 +34,35 @@ rules:
- report_response: true
- type: StatusMatch
status: [200]
revocation:
type: HttpMultiStep
content:
steps:
- name: lookup_authorization_id
request:
method: GET
url: https://api.heroku.com/oauth/authorizations
headers:
Accept: application/vnd.heroku+json; version=3
Authorization: Bearer {{ TOKEN }}
response_matcher:
- type: StatusMatch
status: [200]
extract:
AUTHORIZATION_ID:
type: Regex
pattern: '"id":"([^"]+)"(?:.|[\n\r]){0,2048}?"token":"{{ TOKEN }}"'
- name: revoke_authorization
request:
method: DELETE
url: https://api.heroku.com/oauth/authorizations/{{ AUTHORIZATION_ID }}
headers:
Accept: application/vnd.heroku+json; version=3
Authorization: Bearer {{ TOKEN }}
response_matcher:
- report_response: true
- type: StatusMatch
status: [200]
- name: Heroku API Key (Platform Key)
id: kingfisher.heroku.2
pattern: |
@ -61,8 +91,38 @@ rules:
- '"id":'
- '"name":'
match_all_words: true
revocation:
type: HttpMultiStep
content:
steps:
- name: lookup_authorization_id
request:
method: GET
url: https://api.heroku.com/oauth/authorizations
headers:
Accept: application/vnd.heroku+json; version=3
Authorization: Bearer {{TOKEN}}
response_matcher:
- type: StatusMatch
status: [200]
extract:
AUTHORIZATION_ID:
type: Regex
pattern: '"id":"([^"]+)"(?:.|[\n\r]){0,2048}?"token":"{{ TOKEN }}"'
- name: revoke_authorization
request:
method: DELETE
url: https://api.heroku.com/oauth/authorizations/{{ AUTHORIZATION_ID }}
headers:
Accept: application/vnd.heroku+json; version=3
Authorization: "Bearer {{TOKEN}}"
response_matcher:
- report_response: true
- type: StatusMatch
status: [200]
references:
- https://devcenter.heroku.com/articles/platform-api-quickstart
- https://devcenter.heroku.com/articles/oauth
examples:
- "HRKU-AADVTUYvfjT4nhuJ07bEfAUq9GS3PkTdyWuNBiXYmYMg_____wgAf6OTnGyh"
- "HRKU-AABW9W1iH9NHEIlAABq9nZUq9GS3PkTdyWuNBiXYmYMg_____wV2XYIXxm5p"

View file

@ -0,0 +1,76 @@
rules:
- name: Stytch Project ID
id: kingfisher.stytch.1
visible: false
pattern: |
(?xi)
\b
(
project-(?:test|live)-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}
)
\b
min_entropy: 2.0
confidence: medium
examples:
- project-test-8aed2e54-0266-4793-9b5e-0cc9c56064da
references:
- https://stytch.com/docs/api-reference/consumer/api/overview
- https://stytch.com/docs/api-reference/b2b/api/sessions/authenticate-jwt
- name: Stytch Project Secret
id: kingfisher.stytch.2
pattern: |
(?xi)
\b
(
secret-(?:test|live)-[A-Za-z0-9_-]{35}=?
)
\b
pattern_requirements:
min_digits: 2
min_uppercase: 1
min_lowercase: 1
min_entropy: 3.5
confidence: medium
examples:
- secret-test-IJ7zLTgXp8xoS7yXO2xavNxZTbYfvm-2nZM=
references:
- https://stytch.com/docs/api-reference/consumer/api/overview
- https://stytch.com/docs/api-reference/b2b/api/m2m/overview
- https://stytch.com/docs/api-reference/b2b/api/sessions/authenticate-jwt
depends_on_rule:
- rule_id: kingfisher.stytch.1
variable: STYTCH_PROJECT_ID
validation:
type: Http
content:
request:
method: POST
url: >
{%- if TOKEN contains "-live-" -%}
https://api.stytch.com/v1/m2m/clients/search
{%- else -%}
https://test.stytch.com/v1/m2m/clients/search
{%- endif -%}
headers:
Authorization: "Basic {{ STYTCH_PROJECT_ID | append: ':' | append: TOKEN | b64enc }}"
Content-Type: application/json
body: |
{
"query": {
"operator": "AND",
"operands": [
{
"filter_name": "status",
"filter_value": ["active"]
}
]
}
}
response_matcher:
- report_response: true
- type: StatusMatch
status: [200]
- type: WordMatch
words:
- '"m2m_clients"'