MongoDB Kingfisher - secret detection and live validation
  • Rust 95.9%
  • Makefile 1.1%
  • Python 1%
  • Shell 0.7%
  • PowerShell 0.5%
  • Other 0.7%
Find a file
2025-07-29 20:55:44 -07:00
.github Added support for Slack 2025-07-29 19:00:49 -07:00
data WIP: Adding support for scanning Docker images 2025-07-27 12:20:20 -07:00
docker Fixing issue with dockerfile. Removed non-existent sh package from apk command 2025-07-22 11:49:07 -07:00
docs updated README 2025-07-17 15:11:41 -07:00
src Added support for Slack. Wrote a basic integration test 2025-07-29 20:55:44 -07:00
testdata Ensuring temp files are cleaned up. Applying visual style to the update check output 2025-06-26 09:45:14 -07:00
tests Added support for Slack. Wrote a basic integration test 2025-07-29 20:20:33 -07:00
vendor removed openssl dependency from jira-query 2025-07-25 21:50:28 -07:00
.gitattributes preparing for v1.12 2025-06-24 17:17:16 -07:00
.gitignore fixed failing test 2025-07-25 19:40:40 -07:00
buildwin.bat Fixed broken windows build script 2025-07-29 13:38:59 -07:00
Cargo.toml Added support for Slack 2025-07-29 19:00:49 -07:00
CHANGELOG.md Added support for Slack 2025-07-29 19:00:49 -07:00
install-precommit-hook.sh Fixed broken windows build script 2025-07-29 10:12:40 -07:00
LICENSE preparing for v1.12 2025-06-24 17:17:16 -07:00
Makefile fixing docker build permission error in github actions 2025-07-26 17:28:49 -07:00
nextest.toml preparing for v1.12 2025-06-24 17:17:16 -07:00
NOTICE Added support for scanning issues returned from a JQL search using --jira-url and --jql 2025-07-25 17:23:18 -07:00
README.md Added support for Slack. Wrote a basic integration test 2025-07-29 20:54:22 -07:00
rustfmt.toml preparing for v1.12 2025-06-24 17:17:16 -07:00
THIRD_PARTY_NOTICES preparing for v1.12 2025-06-24 17:17:16 -07:00

Kingfisher

Kingfisher Logo

License

Kingfisher is a blazingly fast secretscanning and validation tool built in Rust. It combines Intels hardwareaccelerated Hyperscan regex engine with languageaware parsing via TreeSitter, and ships with hundreds of builtin rules to detect, validate, and triage secrets before they ever reach production

Kingfisher originated as a fork of Praetorian's Nosey Parker, and is built atop their incredible work and the work contributed by the Nosey Parker community.

What Kingfisher Adds

  • Live validation via cloud-provider APIs
  • Language-aware detection (source-code parsing) for ~20 languages
  • Extra targets: GitLab repos, Docker images, Jira issues, and Slack messages
  • Baseline mode: ignore known secrets, flag only new ones
  • Native Windows binary

Key Features

  • Performance: multithreaded, Hyperscanpowered scanning built for huge codebases
  • Extensible rules: hundreds of built-in detectors plus YAML-defined custom rules (docs/RULES.md)
  • Multiple targets:
    • Git history: local repos or GitHub/GitLab orgs/users
    • Docker images: public or private via --docker-image
    • Jira issues: JQLdriven scans with --jira-url and --jql
    • Slack messages: querybased scans with --slack-query
  • Baseline management: generate and track baselines to suppress known secrets (docs/BASELINE.md)

Learn more: Introducing Kingfisher: RealTime Secret Detection and Validation

Benchmark Results

See (docs/COMPARISON.md)

Kingfisher Runtime Comparison

Getting Started

Installation

On macOS, you can simply

brew install kingfisher

Pre-built binaries are also available on the Releases section of this page.

You can also install using ubi, which downloads the correct binary for your platform:

# Linux, macOS
curl --silent --location \
    https://raw.githubusercontent.com/houseabsolute/ubi/master/bootstrap/bootstrap-ubi.sh | \
    sh && \
  ubi --project mongodb/kingfisher --in "$HOME/bin"
# Windows
powershell -exec bypass -c "Invoke-WebRequest -URI 'https://raw.githubusercontent.com/houseabsolute/ubi/master/bootstrap/bootstrap-ubi.ps1' -UseBasicParsing | Invoke-Expression" && ubi --project mongodb/kingfisher --in .

This installs ubi and then places the kingfisher executable in ~/bin on Unix-like systems (or the current directory on Windows).

Or you may compile for your platform via make:

# NOTE: Requires Docker
make linux

# macOS --- must build from a macOS host
make darwin

# Windows x64 --- requires building from a Windows host with Visual Studio installed
./buildwin.bat -force
# Build all targets
make linux-all # builds both x64 and arm64
make darwin-all # builds both x64 and arm64
make all # builds for every OS and architecture supported

Run Kingfisher in Docker

Run the dockerized Kingfisher container:

# GitHub Container Registry 
docker run --rm ghcr.io/mongodb/kingfisher:latest --version

# Scan the current working directory
# (mounts your code at /src and scans it)
docker run --rm \
  -v "$PWD":/src \
  ghcr.io/mongodb/kingfisher:latest scan /src


# Scan while providing a GitHub token
# Mounts your working dir at /proj and passes in the token:
docker run --rm \
  -e KF_GITHUB_TOKEN=ghp_… \
  -v "$PWD":/proj \
  ghcr.io/mongodb/kingfisher:latest \
    scan --git-url https://github.com/org/private_repo.git

# Scan and write a JSON report locally
# Here we:
#    1. Mount $PWD → /proj
#    2. Tell Kingfisher to write findings.json inside /proj/reports
#   3. Ensure ./reports exists on your host so Docker can mount it
mkdir -p reports

# run and output into hosts ./reports directory
docker run --rm \
  -v "$PWD":/proj \
  ghcr.io/mongodb/kingfisher:latest \
    scan /proj \
    --format json \
    --output /proj/reports/findings.json


# Tip: you can combine multiple mounts if you prefer separating source vs. output:
# Here /src is readonly, and /out holds your generated reports
docker run --rm \
  -v "$PWD":/src:ro \
  -v "$PWD/reports":/out \
  ghcr.io/mongodb/kingfisher:latest \
    scan /src \
    --format json \
    --output /out/findings.json

🔐 Detection Rules at a Glance

Kingfisher ships with hundreds of rules that cover everything from classic cloud keys to the latest LLM-API secrets. Below is an overview:

Category What we catch
AI / LLM APIs OpenAI, Anthropic, Google Gemini, Cohere, Mistral, Stability AI, Replicate, xAI (Grok), and more
Cloud Providers AWS, Azure, GCP, Alibaba Cloud, DigitalOcean, IBM Cloud, Cloudflare, and more
Dev & CI/CD GitHub/GitLab tokens, CircleCI, TravisCI, TeamCity, Docker Hub, npm & PyPI publish token, and more
Messaging & Comms Slack, Discord, Microsoft Teams, Twilio, Mailgun/SendGrid/Mailchimp, and more
Databases & Data Ops MongoDB Atlas, PlanetScale, Postgres DSNs, Grafana Cloud, Datadog, Dynatrace, and more
Payments & Billing Stripe, PayPal, Square, GoCardless, and more
Security & DevSecOps Snyk, Dependency-Track, CodeClimate, Codacy, OpsGenie, PagerDuty, and more
Misc. SaaS & Tools 1Password, Adobe, Atlassian/Jira, Asana, Netlify, Baremetrics, and more

Write Custom Rules!

Kingfisher ships with hundreds of rules with HTTP and servicespecific validation checks (AWS, Azure, GCP, etc.) to confirm if a detected string is a live credential.

However, you may want to add your own custom rules, or modify a detection to better suit your needs / environment.

First, review docs/RULES.md to learn how to create custom Kingfisher rules.

Once you've done that, you can provide your custom rules (defined in a YAML file) and provide it to Kingfisher at runtime --- no recompiling required!

Usage

Basic Examples

Note

  kingfisher scan detects whether the input is a Git repository or a plain directory—no extra flags required.

Scan with secret validation

kingfisher scan /path/to/code
## NOTE: This path can refer to:
# 1. a local git repo
# 2. a directory with many git repos
# 3. or just a folder with files and subdirectories

## To explicitly prevent scanning git commit history add:
#   `--git-history=none`

Scan a directory containing multiple Git repositories

kingfisher scan /projects/monorepodir

Scan a Git repository without validation

kingfisher scan ~/src/myrepo --no-validate

Display only secrets confirmed active by thirdparty APIs

kingfisher scan /path/to/repo --only-valid

Output JSON and capture to a file

kingfisher scan . --format json | tee kingfisher.json

Output SARIF directly to disk

kingfisher scan /path/to/repo --format sarif --output findings.sarif

Pipe any text directly into Kingfisher by passing -

cat /path/to/file.py | kingfisher scan -

Scan using a rule family with one flag

_(prefix matching: --rule kingfisher.aws loads kingfisher.aws._)*

# Only apply AWS-related rules (kingfisher.aws.1 + kingfisher.aws.2)
kingfisher scan /path/to/repo --rule kingfisher.aws

Display rule performance statistics

kingfisher scan /path/to/repo --rule-stats

Scan while ignoring likely test files

--exclude skips any file or directory whose path matches this glob pattern (repeatable, uses gitignore-style syntax, case sensitive)

# Scan source but skip likely unit / integration tests
kingfisher scan ./my-project \
  --exclude='[Tt]est' \
  --exclude='spec' \
  --exclude='[Ff]ixture' \
  --exclude='example' \
  --exclude='sample'

Exclude specific paths

# Skip all Python files and any directory named tests
kingfisher scan ./my-project \
  --exclude '*.py' \
  --exclude '[Tt]ests'

If you want to know which files are being skipped, enable verbose debugging (-v) when scanning, which will report any files being skipped by the baseline file (or via --exclude):

# Skip all Python files and any directory named tests, and report to stderr any skipped files
kingfisher scan ./my-project \
  --exclude '*.py' \
  --exclude tests \
  -v

Scanning Docker Images

Kingfisher will first try to use any locally available image, then fall back to pulling via OCI.

Authentication happens in this order:

  1. KF_DOCKER_TOKEN env var
    • If it contains user:pass, its used as Basic auth
    • Otherwise its sent as a Bearer token
  2. Docker CLI credentials
    • Checks credHelpers (per-registry) and credsStore in ~/.docker/config.json.
    • Falls back to the legacy authsauth (base64) entries.
  3. Anonymous (no credentials)
# 1) Scan public or already-pulled image
kingfisher scan --docker-image ghcr.io/owasp/wrongsecrets/wrongsecrets-master:latest-master

# 2) For private registries, explicitly set KF_DOCKER_TOKEN:
#    - Basic auth:     "user:pass"
#    - Bearer only:    "TOKEN"
export KF_DOCKER_TOKEN="AWS:$(aws ecr get-login-password --region us-east-1)"
kingfisher scan --docker-image some-private-registry.dkr.ecr.us-east-1.amazonaws.com/base/amazonlinux2023:latest

# 3) Or rely on your Docker CLI login/keychain:
#    (e.g. aws ecr get-login-password … | docker login …)
kingfisher scan --docker-image private.registry.example.com/my-image:tag

Scanning GitHub

Scan GitHub organisation (requires KF_GITHUB_TOKEN)

kingfisher scan --github-organization my-org

Scan remote GitHub repository

kingfisher scan --git-url https://github.com/org/repo.git

# Optionally provide a GitHub Token
KF_GITHUB_TOKEN="ghp_…" kingfisher scan --git-url https://github.com/org/private_repo.git


Scanning GitLab

Scan GitLab group (requires KF_GITLAB_TOKEN)

kingfisher scan --gitlab-group my-group

Scan GitLab user

kingfisher scan --gitlab-user johndoe

Scan remote GitLab repository by URL

kingfisher scan --git-url https://gitlab.com/group/project.git

List GitLab repositories

kingfisher gitlab repos list --group my-group

Scanning Jira

Scan Jira issues matching a JQL query

KF_JIRA_TOKEN="token" kingfisher scan \
    --jira-url https://jira.company.com \
    --jql "project = TEST AND status = Open" \
    --max-results 500

Scan the last 1,000 Jira issues:

KF_JIRA_TOKEN="token" kingfisher scan \
  --jira-url https://jira.mongodb.org \
  --jql 'ORDER BY created DESC' \
  --max-results 1000

Scanning Slack

Scan Slack messages matching a search query

KF_SLACK_TOKEN="xoxp-1234..." kingfisher scan \
    --slack-query "from:username has:link" \
    --max-results 1000

KF_SLACK_TOKEN="xoxp-1234..." kingfisher scan \
    --slack-query "akia" \
    --max-results 1000

The Slack token must be a user token with the search:read scope. Bot tokens (those beginning with xoxb-) cannot call the Slack search API.

Environment Variables for Tokens

Variable Purpose
KF_GITHUB_TOKEN GitHub Personal Access Token
KF_GITLAB_TOKEN GitLab Personal Access Token
KF_JIRA_TOKEN Jira API token
KF_SLACK_TOKEN Slack API token
KF_DOCKER_TOKEN Docker registry token (user:pass or bearer token). If unset, credentials from the Docker keychain are used
Set them temporarily per command:
KF_GITLAB_TOKEN="glpat-…" kingfisher scan --gitlab-group my-group

Or export for the session:

export KF_GITLAB_TOKEN="glpat-…"

To authenticate Jira requests:

export KF_JIRA_TOKEN="token"

If no token is provided Kingfisher still works for public repositories.


Exit Codes

Code Meaning
0 No findings
200 Findings discovered
205 Validated findings discovered

Install a Pre-Commit Hook

Run the provided helper script to add a hook that scans staged files before each commit:

# local (current repo only ─ default)
./install-precommit-hook.sh

This creates .git/hooks/pre-commit that scans the files staged for commit with kingfisher scan --no-update-check and blocks the commit if any secrets are found.

# global (every repo on this machine)
./install-precommit-hook.sh --global
### Install a Pre-Receive Hook

Installs a global pre-commit hook at $HOME/.git/hooks/pre-commit; for every Git repository you use, it runs kingfisher scan --no-update-check on the staged files and cancels the commit if any secrets are detected.

Update Checks

Kingfisher automatically queries GitHub for a newer release when it starts and tells you whether an update is available.

  • Hands-free updates Add --self-update to any Kingfisher command

    • If a newer version exists, Kingfisher will download it, replace the running binary, and re-launch itself with the exact same arguments.
    • If the update fails or no newer release is found, the current run proceeds as normal
  • Disable version checks Pass --no-update-check to skip both the startup and shutdown checks entirely

Advanced Options

Build a Baseline / Detect New Secrets

There are situations where a repository already contains checkedin secrets, but you want to ensure no new secrets are introduced. A baseline file lets you document the known findings so future scans only report anything that is not already in that list.

The easiest way to create a baseline is to run a normal scan with the --manage-baseline flag (typically at a low confidence level to capture all potential matches):

kingfisher scan /path/to/code \
  --confidence low \
  --manage-baseline \
  --baseline-file ./baseline-file.yml

Use the same YAML file with the --baseline-file option on future scans to hide all recorded findings:

kingfisher scan /path/to/code \
  --baseline-file /path/to/baseline-file.yaml

See (docs/BASELINE.md) for full detail.

List Builtin Rules

kingfisher rules list

To scan using only your own my_rules.yaml you could run:

kingfisher scan \
  --load-builtins=false \
  --rules-path path/to/my_rules.yaml \
  ./src/

To add your rules alongside the builtins:

kingfisher scan \
  --rules-path ./custom-rules/ \
  --rules-path my_rules.yml \
  ~/path/to/project-dir/

Other Examples

# Check custom rules - this ensures all regular expressions compile, and can match the rule's `examples` in the YML file
kingfisher rules check --rules-path ./my_rules.yml

# List GitHub repos
kingfisher github repos list --user my-user
kingfisher github repos list --organization my-org

Notable Scan Options

  • --no-dedup: Report every occurrence of a finding (disable the default de-duplicate behavior)
  • --confidence <LEVEL>: (low|medium|high)
  • --min-entropy <VAL>: Override default threshold
  • --no-binary: Skip binary files
  • --no-extract-archives: Do not scan inside archives
  • --extraction-depth <N>: Specifies how deep nested archives should be extracted and scanned (default: 2)
  • --redact: Replaces discovered secrets with a one-way hash for secure output
  • --exclude <PATTERN>: Skip any file or directory whose path matches this glob pattern (repeatable, uses gitignore-style syntax, case sensitive)
  • --baseline-file <FILE>: Ignore matches listed in a baseline YAML file
  • --manage-baseline: Create or update the baseline file with current findings

Finding Fingerprint

The document below details the four-field formula (rule SHA-1, origin label, start & end offsets) hashed with XXH3-64 to create Kingfishers 64-bit finding fingerprint, and explains how this ID powers safe deduplication; plus how --no-dedup can be used shows every raw match. See (docs/FINGERPRINT.md)

Rule Performance Profiling

Use --rule-stats to collect timing information for every rule. After scanning, the summary prints a Rule Performance Stats section showing how many matches each rule produced along with its slowest and average match times. Useful when creating rules or debugging rules.

CLI Options

kingfisher scan --help

Business Value

By integrating Kingfisher into your development lifecycle, you can:

  • Prevent Costly Breaches
    Early detection of embedded credentials avoids expensive incident response, legal fees, and reputation damage
  • Automate Compliance
    Enforce secretscanning policies across GitOps, CI/CD, and pull requests to help satisfy SOC 2, PCIDSS, GDPR, and other standards
  • Reduce Noise, Focus on Real Threats
    Validation logic filters out false positives and highlights only active, valid secrets (--only-valid)
  • Accelerate Dev Workflows
    Run in parallel across dozens of languages, integrate with GitHub Actions or any pipeline, and shift security left to minimize delays

The Risk of Leaked Secrets

Real breaches show how one exposed key can snowball into a full-scale incident:

  • Uber (2016): GitHub-hosted AWS key let attackers access data on 57 M riders and 600 k drivers. [BBC] [Ars]
  • AWS engineer (2020): Pushed log files with root credentials to GitHub. [Register] [UpGuard]
  • Infosys (2023): Full-admin AWS key left in a public PyPI package for a year. [Stack] [Blog]
  • Microsoft (2023): Azure SAS token in an AI repo exposed 38 TB of internal data. [Wiz] [TechCrunch]
  • GitHub (2023): RSA SSH host key briefly went public; company rotated it. [GitHub]

Leaked secrets fuel unauthorized access, lateral movement, regulatory fines, and brand-damaging incident-response costs.

Roadmap

  • More rules
  • More targets
  • Please file a feature request if you have specific features you'd like added

License

Apache2 License