- Improved Report Viewer layout

- Improved Salesforce rule
This commit is contained in:
Mick Grove 2025-12-17 11:57:35 -08:00
commit db2c0c7b4e
5 changed files with 918 additions and 289 deletions

View file

@ -2,6 +2,10 @@
All notable changes to this project will be documented in this file.
## [v1.71.0]
- Improved Report Viewer layout
- Improved Salesforce rule
## [v1.70.0]
- Added `--staged` argument to support new `pre-commit` behavior and added integration coverage to ensure validated secrets block commits when used as pre-commit hook
- Added new rules for AWS Bedrock, Voyage.ai, Posthog, Atlassian

View file

@ -10,7 +10,7 @@ publish = false
[package]
name = "kingfisher"
version = "1.70.0"
version = "1.71.0"
description = "MongoDB's blazingly fast and accurate secret scanning and validation tool"
edition.workspace = true
rust-version.workspace = true

View file

@ -33,10 +33,12 @@ For a look at how Kingfisher has grown from its early foundations into today's f
### Performance, Accuracy, and Hundreds of Rules
- **Performance**: multithreaded, Hyperscanpowered scanning built for huge codebases
- **Extensible rules**: hundreds of built-in detectors plus YAML-defined custom rules ([docs/RULES.md](/docs/RULES.md))
- **Broad AI SaaS coverage**: finds and validates tokens for OpenAI, Anthropic, Google Gemini, Cohere, Mistral, Stability AI, Replicate, xAI (Grok), Ollama, Langchain, Perplexity, Weights & Biases, Cerebras, Friendli, Fireworks.ai, NVIDIA NIM, Together.ai, Zhipu, and many more
- **Blast Radius Mapping**: instantly map leaked keys to their effective cloud identities and exposed resources with `--access-map`
- **Broad AI SaaS coverage**: finds and validates tokens for OpenAI, Anthropic, Google Gemini, Cohere, AWS Bedrock, Voyage AI, Mistral, Stability AI, Replicate, xAI (Grok), Ollama, Langchain, Perplexity, Weights & Biases, Cerebras, Friendli, Fireworks.ai, NVIDIA NIM, Together.ai, Zhipu, and many more
- **Compressed Files**: Supports extracting and scanning compressed files for secrets
- **Baseline management**: generate and track baselines to suppress known secrets ([docs/BASELINE.md](/docs/BASELINE.md))
- **Checksum-aware detection**: verifies tokens with built-in checksums (e.g., GitHub, Confluent, Zuplo) — no API calls required
- **Built-in Report Viewer**: Visualize and triage findings locally with `kingisher view ./report-file.json`
**Learn more:** [Introducing Kingfisher: RealTime Secret Detection and Validation](https://www.mongodb.com/blog/post/product-release-announcements/introducing-kingfisher-real-time-secret-detection-validation)
@ -559,7 +561,17 @@ kingfisher scan /path/to/repo --format sarif --output findings.sarif
### Access map outputs and viewer
- Add `--access-map` to enrich JSON, JSONL, BSON, pretty, and SARIF reports with an `access_map` array containing providers, accounts/projects, resources, and the permissions available for each resource (grouped when identical).
**Stop Guessing, Start Mapping: Understand Your True Blast Radius**
Finding a leaked credential is only the first step. The critical question isnt just “Is this a secret?”—its “What can an attacker do with it?”
Kingfisher's `--access-map` feature transforms secret detection from a simple alert into a comprehensive threat assessment. Instead of leaving you with a cryptic API key, Kingfisher actively authenticates against your cloud provider (AWS or GCP) to map the full extent of the credential's power.
* Instant Identity Resolution: Immediately identify who the key belongs to—whether it's a specific IAM user, an assumed role, or a service account.
* Visualize the Blast Radius: See exactly which resources (S3 buckets, EC2 instances, projects) are exposed and at risk.
Add `--access-map` to enrich JSON, JSONL, BSON, pretty, and SARIF reports with an `access_map` containing the resources and the permissions that the key can access - for each resource (grouped when identical).
- If you validated cloud credentials without `--access-map`, Kingfisher will remind you on stderr to rerun with the flag so the access map appears in the output.
- Run `kingfisher view ./kingfisher.json` to explore a report locally in a local web UI

View file

@ -63,36 +63,22 @@ rules:
examples:
- https://example123.my.salesforce.com
- mydomainname.my.salesforce.com
- name: Salesforce Consumer Key and Secret with Token URL
- name: Salesforce Consumer Key
id: kingfisher.salesforce.3
pattern: |
(?xi)(?s)
(?x)(?s)
(?:salesforce|sforce)
(?:.|[\n\r]){0,256}?
\bconsumer\s{0,8}key\b
\bconsumerKey\b
(?:.|[\n\r]){0,32}?
\b
(?P<CONSUMER_KEY>
[A-Z0-9+/=._-]{16,256}
)
\b.*?
(?:.|[\n\r]){0,256}?
\bconsumer\s{0,8}secret\b
(?:.|[\n\r]){0,32}?
\b
(?P<CONSUMER_SECRET>
(
[A-Za-z0-9+/=._-]{16,256}
)
.*?
\btoken\s{0,8}url\b
(?:.|[\n\r]){0,16}?
(?P<TOKEN_URL>
https?://
[A-Za-z0-9.-]{3,253}
/
(?:services/oauth2/token|oauth/login/[\w-]+/token|oauth2/(?:v1/)?token|oauth/token|[\w]{1,10}/oauth/token)
)
\b
min_entropy: 3.3
pattern_requirements:
min_digits: 3
confidence: medium
examples:
- |
@ -100,7 +86,7 @@ rules:
<AuthProvider xmlns="http://soap.sforce.com/2006/04/metadata">
<authorizeUrl>https://login.example.com/oauth/login/v2/authorize?authHint=SALESFORCE_OAUTH2&amp;authType=oauth2&amp;prompt=login</authorizeUrl>
<consumerKey>012cbddfa6b05ec1941143c0d37a036291492be9f2df0b42c5c0c220198185de</consumerKey>
<consumerSecret>REDACTED_CONSUMER_SECRET_1</consumerSecret>
<consumerSecret>7TVG9nQ8gW5RaRxV8i1SaI7vwa0xtQQoejTa48AR5QR6HBYV9YBKPnAzPU7bs6QxOgdjJy9TPabQYVTZtgT83</consumerSecret>
<friendlyName>ExampleProviderOne</friendlyName>
<includeOrgIdInIdentifier>false</includeOrgIdInIdentifier>
<providerType>OpenIdConnect</providerType>
@ -113,8 +99,8 @@ rules:
<?xml version="1.0" encoding="UTF-8"?>
<AuthProvider xmlns="http://soap.sforce.com/2006/04/metadata">
<authorizeUrl>https://api.example.net/oauth/authorize</authorizeUrl>
<consumerKey>REDACTED_CONSUMER_KEY_2</consumerKey>
<consumerSecret>REDACTED_CONSUMER_SECRET_2</consumerSecret>
<consumerKey>012cbddfa6b05ec1941143c0d37a036291492be9f2df0b42c5c0c220198185de</consumerKey>
<consumerSecret>7TVG9nQ8gW5RaRxV8i1SaI7vwa0xtQQoejTa48AR5QR6HBYV9YBKPnAzPU7bs6QxOgdjJy9TPabQYVTZtgT83</consumerSecret>
<friendlyName>ExampleBatchConnect</friendlyName>
<includeOrgIdInIdentifier>false</includeOrgIdInIdentifier>
<providerType>OpenIdConnect</providerType>
@ -127,8 +113,65 @@ rules:
<?xml version="1.0" encoding="UTF-8"?>
<AuthProvider xmlns="http://soap.sforce.com/2006/04/metadata">
<authorizeUrl>https://api.example.net/oauth/authorize</authorizeUrl>
<consumerKey>REDACTED_CONSUMER_KEY_3</consumerKey>
<consumerSecret>REDACTED_CONSUMER_SECRET_3</consumerSecret>
<consumerKey>012cbddfa6b05ec1941143c0d37a036291492be9f2df0b42c5c0c220198185de</consumerKey>
<consumerSecret>7TVG9nQ8gW5RaRxV8i1SaI7vwa0xtQQoejTa48AR5QR6HBYV9YBKPnAzPU7bs6QxOgdjJy9TPabQYVTZtgT83</consumerSecret>
<friendlyName>ExampleConnect</friendlyName>
<includeOrgIdInIdentifier>false</includeOrgIdInIdentifier>
<providerType>OpenIdConnect</providerType>
<sendAccessTokenInHeader>true</sendAccessTokenInHeader>
<sendClientCredentialsInHeader>false</sendClientCredentialsInHeader>
<sendSecretInApis>true</sendSecretInApis>
<tokenUrl>https://api.example.net/oauth/token</tokenUrl>
</AuthProvider>
- name: Salesforce Consumer Secret
id: kingfisher.salesforce.4
pattern: |
(?x)(?s)
\bconsumerSecret\b
(?:.|[\n\r]){0,32}?
\b
(
[A-Za-z0-9+/=._-]{16,256}
)
min_entropy: 3.3
pattern_requirements:
min_digits: 6
confidence: medium
examples:
- |
<?xml version="1.0" encoding="UTF-8"?>
<AuthProvider xmlns="http://soap.sforce.com/2006/04/metadata">
<authorizeUrl>https://login.example.com/oauth/login/v2/authorize?authHint=SALESFORCE_OAUTH2&amp;authType=oauth2&amp;prompt=login</authorizeUrl>
<consumerKey>012cbddfa6b05ec1941143c0d37a036291492be9f2df0b42c5c0c220198185de</consumerKey>
<consumerSecret>7TVG9nQ8gW5RaRxV8i1SaI7vwa0xtQQoejTa48AR5QR6HBYV9YBKPnAzPU7bs6QxOgdjJy9TPabQYVTZtgT83</consumerSecret>
<friendlyName>ExampleProviderOne</friendlyName>
<includeOrgIdInIdentifier>false</includeOrgIdInIdentifier>
<providerType>OpenIdConnect</providerType>
<sendAccessTokenInHeader>true</sendAccessTokenInHeader>
<sendClientCredentialsInHeader>false</sendClientCredentialsInHeader>
<sendSecretInApis>true</sendSecretInApis>
<tokenUrl>https://login.example.com/oauth/login/v2/token</tokenUrl>
</AuthProvider>
- |
<?xml version="1.0" encoding="UTF-8"?>
<AuthProvider xmlns="http://soap.sforce.com/2006/04/metadata">
<authorizeUrl>https://api.example.net/oauth/authorize</authorizeUrl>
<consumerKey>012cbddfa6b05ec1941143c0d37a036291492be9f2df0b42c5c0c220198185de</consumerKey>
<consumerSecret>7TVG9nQ8gW5RaRxV8i1SaI7vwa0xtQQoejTa48AR5QR6HBYV9YBKPnAzPU7bs6QxOgdjJy9TPabQYVTZtgT83</consumerSecret>
<friendlyName>ExampleBatchConnect</friendlyName>
<includeOrgIdInIdentifier>false</includeOrgIdInIdentifier>
<providerType>OpenIdConnect</providerType>
<sendAccessTokenInHeader>true</sendAccessTokenInHeader>
<sendClientCredentialsInHeader>false</sendClientCredentialsInHeader>
<sendSecretInApis>true</sendSecretInApis>
<tokenUrl>https://api.example.net/oauth/token</tokenUrl>
</AuthProvider>
- |
<?xml version="1.0" encoding="UTF-8"?>
<AuthProvider xmlns="http://soap.sforce.com/2006/04/metadata">
<authorizeUrl>https://api.example.net/oauth/authorize</authorizeUrl>
<consumerKey>012cbddfa6b05ec1941143c0d37a036291492be9f2df0b42c5c0c220198185de</consumerKey>
<consumerSecret>7TVG9nQ8gW5RaRxV8i1SaI7vwa0xtQQoejTa48AR5QR6HBYV9YBKPnAzPU7bs6QxOgdjJy9TPabQYVTZtgT83</consumerSecret>
<friendlyName>ExampleConnect</friendlyName>
<includeOrgIdInIdentifier>false</includeOrgIdInIdentifier>
<providerType>OpenIdConnect</providerType>
@ -137,33 +180,13 @@ rules:
<sendSecretInApis>true</sendSecretInApis>
<tokenUrl>https://api.example.net/oauth/token</tokenUrl>
</AuthProvider>
validation:
type: Http
content:
request:
method: POST
url: "{{ TOKEN_URL | default: 'https://login.salesforce.com/services/oauth2/token' }}"
headers:
Content-Type: application/x-www-form-urlencoded
body: grant_type=client_credentials&client_id={{ CONSUMER_KEY | url_encode }}&client_secret={{ CONSUMER_SECRET | url_encode }}
response_matcher:
- report_response: true
- type: StatusMatch
status: [200]
- type: StatusMatch
status: [400, 401, 403]
negative: true
- type: WordMatch
words: ["invalid_", "authentication failed"]
match_all_words: false
negative: true
- name: Salesforce Consumer Key and Secret
id: kingfisher.salesforce.4
pattern: |
(?xi)(?s)
(?:salesforce|sforce)
(?:.|[\n\r]){0,256}?
\bconsumer\s{0,8}key\b
\bconsumerKey\b
(?:.|[\n\r]){0,32}?
\b
(?P<CONSUMER_KEY>
@ -177,7 +200,9 @@ rules:
(?P<CONSUMER_SECRET>
[A-Za-z0-9+/=._-]{16,256}
)
min_entropy: 3.3
min_entropy: 3.5
pattern_requirements:
min_digits: 3
confidence: medium
examples:
- |
@ -185,7 +210,7 @@ rules:
<AuthProvider xmlns="http://soap.sforce.com/2006/04/metadata">
<authorizeUrl>https://login.example.com/oauth/login/v2/authorize?authHint=SALESFORCE_OAUTH2&amp;authType=oauth2&amp;prompt=login</authorizeUrl>
<consumerKey>012cbddfa6b05ec1941143c0d37a036291492be9f2df0b42c5c0c220198185de</consumerKey>
<consumerSecret>REDACTED_CONSUMER_SECRET_1</consumerSecret>
<consumerSecret>7TVG9nQ8gW5RaRxV8i1SaI7vwa0xtQQoejTa48AR5QR6HBYV9YBKPnAzPU7bs6QxOgdjJy9TPabQYVTZtgT83</consumerSecret>
<friendlyName>ExampleProviderOne</friendlyName>
<includeOrgIdInIdentifier>false</includeOrgIdInIdentifier>
<providerType>OpenIdConnect</providerType>
@ -198,8 +223,8 @@ rules:
<?xml version="1.0" encoding="UTF-8"?>
<AuthProvider xmlns="http://soap.sforce.com/2006/04/metadata">
<authorizeUrl>https://api.example.net/oauth/authorize</authorizeUrl>
<consumerKey>REDACTED_CONSUMER_KEY_2</consumerKey>
<consumerSecret>REDACTED_CONSUMER_SECRET_2</consumerSecret>
<consumerKey>012cbddfa6b05ec1941143c0d37a036291492be9f2df0b42c5c0c220198185de</consumerKey>
<consumerSecret>7TVG9nQ8gW5RaRxV8i1SaI7vwa0xtQQoejTa48AR5QR6HBYV9YBKPnAzPU7bs6QxOgdjJy9TPabQYVTZtgT83</consumerSecret>
<friendlyName>ExampleBatchConnect</friendlyName>
<includeOrgIdInIdentifier>false</includeOrgIdInIdentifier>
<providerType>OpenIdConnect</providerType>
@ -212,8 +237,8 @@ rules:
<?xml version="1.0" encoding="UTF-8"?>
<AuthProvider xmlns="http://soap.sforce.com/2006/04/metadata">
<authorizeUrl>https://api.example.net/oauth/authorize</authorizeUrl>
<consumerKey>REDACTED_CONSUMER_KEY_3</consumerKey>
<consumerSecret>REDACTED_CONSUMER_SECRET_3</consumerSecret>
<consumerKey>012cbddfa6b05ec1941143c0d37a036291492be9f2df0b42c5c0c220198185de</consumerKey>
<consumerSecret>7TVG9nQ8gW5RaRxV8i1SaI7vwa0xtQQoejTa48AR5QR6HBYV9YBKPnAzPU7bs6QxOgdjJy9TPabQYVTZtgT83</consumerSecret>
<friendlyName>ExampleConnect</friendlyName>
<includeOrgIdInIdentifier>false</includeOrgIdInIdentifier>
<providerType>OpenIdConnect</providerType>
@ -221,24 +246,4 @@ rules:
<sendClientCredentialsInHeader>false</sendClientCredentialsInHeader>
<sendSecretInApis>true</sendSecretInApis>
<tokenUrl>https://api.example.net/oauth/token</tokenUrl>
</AuthProvider>
validation:
type: Http
content:
request:
method: POST
url: "https://login.salesforce.com/services/oauth2/token"
headers:
Content-Type: application/x-www-form-urlencoded
body: grant_type=client_credentials&client_id={{ CONSUMER_KEY | url_encode }}&client_secret={{ CONSUMER_SECRET | url_encode }}
response_matcher:
- report_response: true
- type: StatusMatch
status: [200]
- type: StatusMatch
status: [400, 401, 403]
negative: true
- type: WordMatch
words: ["invalid_", "authentication failed"]
match_all_words: false
negative: true
</AuthProvider>

File diff suppressed because it is too large Load diff