geiger

module
v1.11.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 6, 2026 License: MIT

README

geiger

Is it still live, what does it reach, and how bad? Read-only blast-radius triage for leaked credentials.

release

Your secret scanner found a key but it won't tell you if it's still live or what it unlocks.

geiger does: pipe any credential-bearing text at it and it recognizes the credentials inside, runs read-only recon with each, and ranks what they actually reach by blast radius.

Triage: an incident responder's "how bad is this?" and a pentester's "what does this key reach?". Read-only by construction, dry-run by default.


Install

Binary — grab the archive for your OS/arch from Releases:

tar xzf geiger_*_linux_amd64.tar.gz && sudo mv geiger /usr/local/bin/

Source (Go 1.25+):

git clone https://github.com/puck-security/geiger && cd geiger
go build -o geiger ./cmd/geiger

Tutorial

geiger doesn't touch anything on the network until you say so. Dry-run first (default): it recognizes the credential and prints the read-only calls it would make. Try it on AWS's well-known example keys — no real secret needed:

printf 'AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE\nAWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\n' | geiger

That prints the read-only calls it would run (sts:GetCallerIdentity, …). Add --live with a real credential to actually run them and get the impact note:

echo 'GITHUB_TOKEN=ghp_...' | geiger --live

How-to

# a file, stdin, or a cloud CLI's output
geiger --live .env
cat sso-cache.json | geiger --live
aws configure export-credentials | geiger --live

# the current environment
geiger --env --live

# this box's own cloud identity — harvest the instance-metadata credential
# (AWS instance role, GCP/Azure managed identity, k8s in-cluster SA, …) and
# triage what it reaches. The post-exploitation question, answered read-only.
geiger --metadata --live
geiger --metadata --live --intrusive   # + in-cluster k8s RBAC, secrets-store drain

# a whole repo / dir (walked; results sorted by impact)
geiger --live ./leaked-repo

# a scanner's report — e.g. a TruffleHog sweep of a compromised laptop,
# exactly what supply-chain worms (Shai-Hulud) run; triage which creds reach prod
geiger --live --from-trufflehog trufflehog.json
geiger --live --from-gitleaks gitleaks-report.json

# external recon: pipe a nuclei exposure scan straight in. Its templates pull the
# leaked value out of each exposed endpoint (/.env, phpinfo, instance metadata);
# geiger types, validates, and ranks it, and records the URL it leaked from. It
# also parses the response body when present, reassembling multi-field creds (an
# AWS key+secret pair, a connection string) the flat extracted-results can't —
# run nuclei with -irr to include the body.
# Stream over a pipe so live secrets never land on disk (add -o only if you must).
nuclei -t exposures/ -l targets.txt -j -irr | geiger --live --from-nuclei -

# rank by YOUR crown jewels (boost anything touching these to HIGH+)
geiger --live --context '1234567890,acme-prod,billing-service' ./repo

# self-hosted services need a host
echo 'VAULT_TOKEN=hvs....' | geiger --live --endpoint https://vault.internal:8200

# only what matters; save a clean artifact
geiger --live --min-severity high -o case-1234.txt ./repo

# OPSEC: identity call only; route egress through a proxy
geiger --live --min-footprint --proxy socks5://127.0.0.1:9050 .env

# machine-readable
geiger --live --json ./repo | jq .

Go deeper — --intrusive (doesn't modify resources, but leaves a trail): connects to databases (Postgres, MySQL, MongoDB, Redis, SQL Server, Oracle, ClickHouse, Cassandra — fixed catalog queries, read-only session), reads local SQLite/IDE stores in place, hits cluster APIs, redeems cached user refresh tokens (Azure / GCP sessions) to map their reach — an active sign-in that shows in the tenant's audit log — and follows secrets-store reads, draining Vault/Doppler/1Password/cloud secret managers (AWS SM, GCP SM, Azure Key Vault) and recursively triaging each extracted secret. The same fan-out a worm performs, so you see the real blast radius. Plain --live stays read-only: it uses a still-valid cached token but never redeems a refresh token.

geiger --live --intrusive .env

SSH keys — point it at a directory; it fingerprints each key (encrypted keys are locked, not dead). With --live it confirms the key's main use — git access — by attempting an SSH login to GitHub/GitLab/Bitbucket and reporting the account it authenticates as (or the repo, for a deploy key); a user key that logs in means pull/push to that account's private repos (supply-chain risk). --ssh-correlate adds candidate target hosts from ~/.ssh/config, known_hosts, and shell history.

geiger --live ~/.ssh            # fingerprint + test GitHub/GitLab/Bitbucket access
geiger --ssh-correlate ~/.ssh   # + guess other target hosts from local hints

Browser extensions--browser models the impact of a malicious Chromium-family (Chrome, Edge, Brave, Chromium, Vivaldi) extension (CursedChrome-style proxy, infostealer, sideloaded MV3). It scores each installed extension's permission union — cookies + broad host access + request interception / script injection / proxy = read every site's session cookies and pivot through the browser — and flags sideloaded/unpacked ones (unsigned, not content-verified). With --live --intrusive it also inventories the live sessions such an extension would reach from the Cookies store metadata (domains only — the values are keychain-encrypted), ranked by blast radius (IdP/SSO sessions first).

Because an unsigned all-sites extension is capability-identical to a real CursedChrome, geiger doesn't guess intent — for each flagged sideloaded extension it builds a responder triage bundle: install age, UI surface, dev-project markers, the extension id, and a low-false-positive grep of its on-disk code (and, under --intrusive, its LevelDB storage) for hardcoded remote hosts (websocket / public-IP endpoints) to verify against egress/DNS logs. Everything is emitted as clean IOCs in --json (detail arrays) for a SIEM.

By default only extensions with risky reach are shown; narrow/benign ones are collapsed into a count. --all lists every installed extension (a full inventory).

geiger --browser                    # score extensions + triage bundle
geiger --browser --live --intrusive # + session inventory + storage IOC grep
geiger --browser --all              # full inventory (incl. narrow/benign)
geiger --browser --json             # IOCs (extension id, hosts) for a SIEM

Where geiger fits

geiger layers on top of the scanners you already run: detection finds the secret, geiger characterizes it. Pipe in a report (--from-gitleaks / --from-trufflehog / --from-nuclei -), or point it at a directory — which is how IR usually uses it.

gitleaks TruffleHog GitGuardian Kingfisher geiger
Find secrets in code / git / files walks a tree; consumes their reports
Verify the secret is live
Characterize blast radius (identity, scope, reach) partial partial ✅ ~170+ types
Triage any credential you hand it, type auto-detected partial
Drain secret-managers + recursively triage downstream
DB / cluster / on-disk store recon (read-only) partial
Ranked for IR ("how bad, in what order") partial
Local, no SaaS / account — (SaaS)

Performance

Offline triage runs locally in seconds. A live run is dominated by provider round-trip, so it scales with --concurrency and rate limits, not corpus size.

measured
Dry-run, 20k files / 148MB ~2.9s warm, ~8s cold
Dry-run, a few files 20–30ms
Calls per credential identity + small inventory fan-out (AWS key: 4)
--min-footprint 1 call

--intrusive is slower due to DB handshakes, secret-manager fan-out, recursive triage.


Reference

Flags

Flag Effect
(stdin / files / dirs) input source; multiple files/dirs may be passed, and a directory is walked
--live make read-only recon calls (default: dry-run)
--intrusive connect to DBs / cluster APIs, read local stores, harvest downstream secrets (needs --live)
--min-footprint identity call only; skip inventory fan-out
--env read current environment variables
--metadata harvest this instance's metadata credential (AWS/GCP/Azure/k8s/Alibaba/DigitalOcean/OCI) and triage it; requires --live (it's a network read)
--browser model malicious-browser-extension impact: score installed Chromium-family extensions; with --live --intrusive, inventory the live sessions they'd reach
--all with --browser, list every extension (not just the risky ones)
--endpoint URL host/instance for self-hosted & set-shaped creds
--proxy URL route HTTP recon via http/https/socks5 proxy
--timeout DUR per-credential recon timeout (default 15s)
--concurrency N credentials reconned at once on --live (default 8)
--context TERMS comma-separated crown-jewel terms; a match raises tier
--min-severity TIER only print findings at or above a tier (critical/high/medium/low/info/unknown/dead); dead is the floor, so info excludes dead and unknown, and high keeps only critical+high
-o, --output FILE write results to FILE instead of stdout (0600, color off; status stays on stderr)
--json machine-readable output (NDJSON, one note per line)
--sarif SARIF 2.1.0 output for code-scanning and triage viewers; tier and score ride in properties (NDJSON stays canonical)
--stream print results as found (discovery order) instead of sorted by impact
--no-reverse keep highest-impact findings first; by default an interactive terminal reverses them to the bottom (above the summary) so the worst don't scroll off the top
--only TYPES / --skip TYPES scope by module name or category (databases,cloud,secrets,ai,vcs,kubernetes,identity,backup,endpoint)
--from-gitleaks F / --from-trufflehog F triage each finding in a scanner report
--from-nuclei F triage each value extracted by a nuclei JSONL (-j) scan; F = - reads stdin (stream over a pipe)
--from-kingfisher F triage each finding in a Kingfisher JSON/JSONL report (not --redacted — geiger needs the value); F = - reads stdin. Their finding fingerprint is carried through to --json/--sarif so their viewer dedupes against its own findings
--git-history also scan blobs in a repository's git history — catches credentials deleted from the working tree but still recoverable from the repo (needs git on PATH)
--ssh-correlate SSH: read local hints for candidate target hosts
--trace print the raw request + response of each call (secrets masked)
--user-agent UA User-Agent for recon calls (default geiger/<version>)
--color MODE auto (default, off when piped) / always / never
-v / -q show planned/executed calls (and full finding detail) / quiet stderr
--version print version

Tiers

CRITICAL · HIGH · MEDIUM · LOW · INFO · DEAD — a composite blast-radius score (capability × reach × sensitivity), relative not absolute. --context matches and force-multiplier capabilities force at least HIGH.

What geiger reads — and what it can't

geiger triages a credential you were handed, or one sitting on disk.

  • In scope — on-disk / offline-readable. API tokens, connection strings, cloud CLI caches (~/.aws, gcloud, MSAL), SSH keys, kubeconfigs, secrets-manager creds, MCP configs, AI-IDE plaintext token stores, password-manager recovery material (KeePass, encrypted Bitwarden — offline-crackable with the master password), plaintext exports, and Firefox saved logins (logins.json + key4.db), which decrypt offline when no primary password is set.
  • Out of scope — in-process / OS-bound. Chromium passwords & cookies (wrapped by DPAPI / macOS Keychain / Secret Service), raw DPAPI blobs, the macOS Keychain, LSASS. Reading those means decrypting against a live OS session — credential extraction from a host, not triage of one. Not always a black and white line. (--browser models the extension-capability and session-metadata angle — which domains have a live session, which extension could reach them — without decrypting the cookie values; see Browser extensions above.)

Coverage

Recognition rides on gitleaks (shape/checksum) plus geiger's own shape/env-name recognizers; an unrecognized type is reported unknown, not characterized. Triage keys on capability — a key that runs code, wipes devices, restores backups, or reads other secrets is a force multiplier; a billed-usage API key is a warning.

Full coverage — 175 credential types (regenerate with go run ./tools/coverage)

Cloud & hosting

Credential / app Reach
aws AWS account — IAM-scoped access across all AWS services
aws_sso active SSO session
aws_sso_registration SSO client registration (no session)
gcp_service_account GCP service account — exchanged a read-only token
gcp_adc gcloud user credentials — delegated user access
gcp_metadata GCP instance service account — token-scoped reach
azure_msal Azure CLI session — Entra identity, refreshable headlessly
alibaba Alibaba Cloud RAM credential
oci_instance_principal OCI instance principal
digitalocean DigitalOcean — droplets, databases, Spaces, Kubernetes
digitalocean_oauth DigitalOcean OAuth — account API access
linode Linode — compute, storage, DNS account control
cloudflare Cloudflare — DNS/zones/Workers per token scope
cloudflare_global Cloudflare Global API Key — full account control
fastly Fastly — CDN config, edge purge/secrets
heroku Heroku — app deploy + config-vars (downstream secrets)
render Render — deploy (code exec) + env-secret access
railway Railway — deploy (code exec) + project-variable access
flyio Fly.io — machine deploy (code exec) + app-secret access
netlify Netlify — site deploy + build env vars
vercel Vercel — project deploy + env vars
tailscale Tailscale — tailnet device/ACL admin + auth-key minting
terraform_cloud Terraform Cloud — workspace state & variables (often secrets)
oci_config Oracle Cloud — API signing config (key_file referenced, not inline)

Source control & packages

Credential / app Reach
github_pat GitHub — repo read/write/admin, org membership, Actions
gitlab GitLab — repo/project access per token scope
gitlab_ci_token GitLab CI job token — pipeline-scoped repo/registry access
jfrog JFrog Artifactory — artifact read/write + package admin
docker_registry container registry — pull/push images (supply-chain)
npm npm — publish/yank packages (supply-chain)
pypi PyPI — publish packages (supply-chain)
rubygems RubyGems — publish gems (supply-chain)

CI/CD & build

Credential / app Reach
buildkite Buildkite — pipelines + build-agent access
circleci CircleCI — pipelines + project env vars

Databases & data platforms

Credential / app Reach
db_connection_string direct DB data-plane (pg/mysql/mongo/redis/mssql/oracle/clickhouse/cassandra/sqlite)
snowflake Snowflake — data-warehouse access (account-wide at ACCOUNTADMIN)
databricks Databricks — workspace, jobs, notebooks, data
mongodb_atlas MongoDB Atlas service account — Admin API access to orgs/projects/clusters
supabase Supabase service_role — RLS-bypass full DB + auth admin
planetscale PlanetScale service token — database & branch admin
neon Neon API key — Postgres project & role admin
aiven Aiven token — managed-service & credential admin
upstash Upstash management API — database & token admin
redis_cloud Redis Cloud API — subscription & database admin
clickhouse_cloud ClickHouse Cloud API key — service & member control
clickhouse_selfhosted ClickHouse (self-hosted) — SQL data & user access
plaid Plaid keys — bank-account data access (financial PII)

AI / LLM & agentic

Credential / app Reach
openai OpenAI — model access, files/fine-tunes; org-owner = key/billing admin
anthropic Anthropic — Claude model access (billed)
claude_code_oauth Claude Code / Claude subscription OAuth token — acts as the signed-in user
gemini Google Gemini — generative API (billed usage)
azure_openai Azure OpenAI — resource model access (billed usage)
cohere Cohere — LLM API access (billed)
mistral Mistral — LLM API access (billed)
replicate Replicate — model runs (billed) + model access
huggingface Hugging Face — model/dataset access; write token can push
groq groq — LLM API access (billed usage)
together together — LLM API access (billed usage)
deepseek deepseek — LLM API access (billed usage)
openrouter openrouter — LLM API access (billed usage)
xai xai — LLM API access (billed usage)
fireworks fireworks — LLM API access (billed usage)
perplexity Perplexity — LLM API (billed usage)
elevenlabs ElevenLabs — voice API (billed usage + voice library)
stability Stability AI — image API (billed usage)
pinecone Pinecone — vector index read/write (embedded data)
mcp_config MCP config — agent credential aggregator
ai_ide_store AI-IDE token store (plaintext SQLite)

Secrets managers & vaults

Credential / app Reach
vault HashiCorp Vault — read secrets per policy
conjur CyberArk Conjur — secrets-manager access (reads downstream secret values)
cyberark_pvwa CyberArk PVWA — privileged-account vault access
infisical Infisical — secret-store read across authorized projects
akeyless Akeyless — secret-store read (list-items / get-secret-value)
delinea_secret_server Delinea/Thycotic Secret Server — vaulted-secret read access
doppler Doppler — project config/secret access
onepassword_connect 1Password Connect — vault item access via the Connect server
onepassword_sa 1Password service account — vault secret access (CLI/SDK only)
onepassword_secret_key 1Password Secret Key — vault-unlock half; dangerous with the master password
bitwarden Bitwarden API key — valid; enumerates the vault (items stay encrypted without the master password)
bitwarden_vault Bitwarden encrypted vault — offline-crackable with the master password
keepass_db KeePass vault — offline-crackable to every secret with the master password
vault_export_plaintext plaintext credential dump — full account takeover across every listed site

Identity, SSO & directory

Credential / app Reach
okta Okta — directory, SSO apps, admin per scope
pingone PingOne — identity & SSO admin
pingfederate PingFederate admin API — OAuth client & federation-trust control
entra_sp Microsoft Entra service principal — Graph/Azure per app roles
jumpcloud JumpCloud — directory, device & SSO admin
sailpoint SailPoint — identity governance (certs, provisioning)
auth0 Auth0 — tenant management API (users, apps, rules)
duo Duo — MFA admin API (bypass codes, user mgmt)
workday Workday — HR/finance records (PII)

Endpoint, MDM, RMM & config-mgmt

Credential / app Reach
ninjaone NinjaOne RMM — script execution + remote control across endpoints
atera Atera RMM/PSA — full agent & customer inventory
kandji Kandji MDM — device inventory + remote lock/erase
jamf Jamf Pro — script execution + MDM lock/wipe
mosyle Mosyle MDM — device control incl. remote wipe/lock
automox Automox — patch policies + worklet script execution across endpoints
tanium Tanium — package deploy + action execution across endpoints
ansible_awx Ansible AWX/Tower — playbook execution across managed hosts
puppet_enterprise Puppet Enterprise — orchestrator task/plan execution on nodes
saltstack SaltStack salt-api — arbitrary module execution across minions
fleet Fleet (osquery) — live queries + script execution + MDM wipe

Monitoring & observability

Credential / app Reach
datadog Datadog — metrics/logs/APM + monitor & key admin
newrelic New Relic — telemetry + account admin
grafana Grafana — dashboards/datasources; server-admin = full
splunk Splunk — search over all data + scripted-input command execution
sumologic Sumo Logic — log search (secrets/PII) + collector admin
dynatrace Dynatrace — observability data + config API
honeycomb Honeycomb — event data + query API
sentry Sentry — error events (may hold secrets/PII) + org admin
zabbix Zabbix — global script execution on monitored hosts
auvik Auvik — network topology & device inventory
manageengine_opmanager ManageEngine OpManager — device management + workflow script execution
lacework Lacework — cloud security posture across connected accounts
wiz Wiz — cloud security graph (findings, identities, secrets)
snyk Snyk — code/dependency vuln data + org project access

Backup & DR

Credential / app Reach
veeam Veeam Backup & Replication — job control + restores
acronis Acronis Cyber Protect — backup/restore + agent control
cohesity Cohesity — protection-job & restore control
netbackup Veritas NetBackup — policy & restore control
commvault Commvault — backup/restore + client management

ITSM, productivity & support

Credential / app Reach
servicenow ServiceNow — ITSM/CMDB records + workflows
jira Jira (Atlassian Cloud) — full issue/project read + user-directory PII
ivanti Ivanti ITSM — incident/CMDB access + employee PII
snipeit Snipe-IT — asset/license inventory + user PII
pagerduty PagerDuty — on-call schedules + incident API
linear Linear — issues/projects + member data
asana Asana — tasks/projects + workspace members
notion Notion — workspace pages/databases (often secrets/PII)
zendesk Zendesk — support tickets (customer PII)
intercom Intercom — conversations & customer profiles (PII)
freshservice Freshservice ITSM key — tickets, requester PII and CMDB
freshdesk Freshdesk help desk key — tickets and contact PII
freshchat Freshchat — all conversations and contact PII
freshsales Freshsales CRM — contact PII and pipeline data

Comms, email & SMS

Credential / app Reach
slack Slack — messages, files, users per token scope
discord_bot Discord bot — guild/message access per intents
telegram_bot Telegram bot — send/read in its chats
zoom Zoom — meetings, recordings, user admin (S2S OAuth)
twilio Twilio — SMS/voice send (billed) + message logs (PII)
vonage Vonage — SMS/voice send (billed)
sendgrid SendGrid — email send + template/contact access
mailgun Mailgun — email send + logs (recipient PII)
mailchimp Mailchimp — audience export (subscriber PII) + send
postmark Postmark — transactional email send + history
brevo Brevo — email/SMS + contact PII

Payments, CRM & SaaS data

Credential / app Reach
stripe Stripe — charges/customers/payouts (a live key moves money)
square Square — payments + customer data (financial)
coinbase Coinbase — account access (financial; can move funds)
salesforce Salesforce — CRM object access (customer PII)
hubspot HubSpot — CRM contacts/deals (PII)
shopify Shopify — store orders/customers (PII) + admin
klaviyo Klaviyo — customer-profile export (PII) + campaign send
braze Braze — message-send to all users + profile export (PII)
segment Segment — customer event-pipeline access (behavioral PII)
mixpanel Mixpanel — product-analytics data (behavioral PII)
amplitude Amplitude — product-analytics data (behavioral PII)
customerio Customer.io — messaging + customer data (PII)
docusign DocuSign — envelopes/agreements (legal docs)
dropbox Dropbox — file access per scope
box Box — file/folder access; admin = all content
airtable Airtable — base data (often PII/secrets)
algolia Algolia — search index read/write; admin key = full
confluent Confluent Cloud — Kafka cluster & topic admin

Local credential stores & keys

Credential / app Reach
ssh_private_key SSH private key — confirmed git host access
kubeconfig kubeconfig — cluster credential
firefox_logins Firefox saved logins — offline-decryptable on-disk store
jwt decoded offline — no network call made; map issuer to its provider for live recon
generic_secret unrecognized credential (matched by name)
needs_endpoint recognized — provide --endpoint to characterize

Uncategorized (add to a group in tools/coverage)

Credential / app Reach
atlassian Atlassian API token — set email + site to validate reach
bedrock Amazon Bedrock API key — foundation-model access (billable)
confluence Confluence (Atlassian Cloud) — full space/page read; pages often hold secrets
filestack Filestack API key — file upload/transform on this account
workos WorkOS API key — SSO/Directory Sync/User Management control

175 credential types

Output

A block per credential: a tier, a redacted title with the source location, never the raw secret, labeled findings ( notable, ⚠⚠ force multiplier, ? can't-determine-read-only), and a one-line takeaway.

For IR, each finding leads with where and when: an exposure line classifies the source — a crash dump (in-memory, persisted to disk, often auto-uploaded — may have left the host), a VS Code local-history snapshot, an IDE secret store, shell history, a log — and source modified / validated live carry the file mtime and live-check timestamp. When a secret turns up in several files, also exposed in groups them by class (8 local-history snapshots; 7 crash dumps) instead of listing paths (the full list expands under -v and in --json).

With -v each planned call prints as a copy-pasteable curl. Triaging more than one credential prints a closing summary — tier breakdown, rotate-first queue, and follow-ups (secrets-store reach, what couldn't be characterized, anything hidden by --min-severity). GitHub write/admin and org-admin are read from each repo's permissions and /user/memberships/orgs, so they're reported even for fine-grained PATs that expose no scopes.

Drift resilience. Beyond declared field paths, every response is scanned heuristically (admin/owner indicators → force multiplier; a fallback identity + count when the API shape changed), so a module stays useful as providers rename fields. --trace shows the raw request/response (secrets masked).


How it works

Pipeline: recognize → (authenticate) → recon → note. Recon runs the identity/whoami call first, then a couple of count calls to size reach.

Safety model

  • Read-only by construction. One client allows only GET/HEAD plus a short allowlist of read-only POSTs (STS GetCallerIdentity, k8s SelfSubjectRulesReview, the single OAuth token exchange). DB recon uses a read-only session and a fixed query allowlist. Local stores (SQLite, IDE state.vscdb, Firefox key4.db) open read-only. A guard test enforces this across every module.
  • Dry-run by default. --live is required and always prints the destinations it hits (real provider APIs, and their audit logs).
  • Attribution. Recon identifies itself as geiger/<version> — dual use beware, no detection evasion; defenders can attribute the calls.
  • Secrets are not printed or stored. Redacted everywhere; scrubbed from URLs, headers, and errors.
  • Untrusted-input hardening. Refuses cloud-metadata targets (SSRF), sanitizes hostile API responses, strips file-referencing DSN options
  • Endpoint provenance. A host read out of scanned data is untrusted: a planted URL would otherwise aim a real credential at whoever planted it. Every module declares where its credential may go, enforced centrally at recognition time — a SaaS module is pinned to its vendor's domains, --endpoint outranks anything in the file, and a violation degrades to "needs endpoint" instead of dialing. Self-hosted services can legitimately live at any domain, so those are not pinned; their destination is flagged in the note instead.

Principle: likely impact, not perfect impact. geiger is triage, not deep cloud-privesc graphing (use PMapper/CloudFox/ScoutSuite/etc for that).

Authorized use only. geiger exercises live credentials — run it only on creds you are entitled to triage.


Contributing a module

Most providers are a few lines of declarative recipe:

add("digitalocean-pat", recipe.HTTP{
    ModuleName: "digitalocean", Base: "https://api.digitalocean.com",
    Auth:   recipe.AuthSpec{Kind: recipe.Bearer},
    Whoami: recipe.GET("/v2/account").Field("email", "account.email"),
    Calls:  []recipe.Call{recipe.GET("/v2/droplets").CountFrom("meta.total", "droplets")},
}.Module())

If your Base is templated on a host — {endpoint}, {host}, {api}, {server} — you must also declare an Endpoint policy. That host comes from the file being scanned, which an attacker may have written, so geiger needs to know which hosts are legitimate for your service:

    // SaaS-only: pin the vendor's domains (list every region and gov host).
    ModuleName: "zendesk", Endpoint: saasOnly("zendesk.com"), Base: "{endpoint}",

    // Deployable at any domain — including vendors shipping both SaaS and
    // on-prem, where pinning would break real deployments.
    ModuleName: "vault", Endpoint: selfHosted, Base: "{endpoint}",

Resolve the host with resolveEndpoint rather than reading a variable yourself: it puts the operator's --endpoint ahead of anything in the file. Don't pair a service's credential with another service's URL variable — bind each host variable to the module it names. TestEveryEndpointSteeredModuleDeclaresAPolicy fails if a module skips this.

Add an httptest-backed test, then go run ./tools/coverage to refresh the coverage table above. Exotic signing (SigV4, RS256-JWT, Digest) implements the module.Module interface directly with the internal/sign + internal/auth helpers — see internal/modules/ for examples.

Directories

Path Synopsis
cmd
geiger command
Command geiger triages leaked credentials: it recognizes the credentials in piped text, a file, the environment, a directory, or a scanner report, runs read-only recon with each, and prints a short note on what the credential is and what it can reach.
Command geiger triages leaked credentials: it recognizes the credentials in piped text, a file, the environment, a directory, or a scanner report, runs read-only recon with each, and prints a short note on what the credential is and what it can reach.
internal
auth
Package auth implements the four headless OAuth grants Geiger supports.
Package auth implements the four headless OAuth grants Geiger supports.
browser
Package browser models the impact of a malicious Chromium browser extension (CursedChrome-style browser proxy, infostealer, sideloaded MV3 extension).
Package browser models the impact of a malicious Chromium browser extension (CursedChrome-style browser proxy, infostealer, sideloaded MV3 extension).
color
Package color provides terminal coloring that is a no-op unless enabled, so output stays clean when piped or redirected (codes would otherwise pollute files and tools like jq).
Package color provides terminal coloring that is a no-op unless enabled, so output stays clean when piped or redirected (codes would otherwise pollute files and tools like jq).
dbrecon
Package dbrecon runs read-only data-plane recon against a database connection string.
Package dbrecon runs read-only data-plane recon against a database connection string.
imds
Package imds harvests credentials from cloud instance-metadata services (AWS IMDS, GCP/Azure metadata, Kubernetes in-cluster SA, Alibaba, DigitalOcean, OCI) and normalizes each into a synthetic dotenv blob that geiger's normal recognizers pick up.
Package imds harvests credentials from cloud instance-metadata services (AWS IMDS, GCP/Azure metadata, Kubernetes in-cluster SA, Alibaba, DigitalOcean, OCI) and normalizes each into a synthetic dotenv blob that geiger's normal recognizers pick up.
module
Package module defines Geiger's core domain types and the Module contract.
Package module defines Geiger's core domain types and the Module contract.
module/recipe
Package recipe builds declarative HTTP modules.
Package recipe builds declarative HTTP modules.
modules
Package modules is the credential catalog.
Package modules is the credential catalog.
note
Package note renders a module's Note for the terminal or as JSON.
Package note renders a module's Note for the terminal or as JSON.
parse
Package parse turns raw input (a file, stdin, or the environment) into a Blob: the original text plus a flattened key/value view and any structured form (JSON object, INI sections).
Package parse turns raw input (a file, stdin, or the environment) into a Blob: the original text plus a flattened key/value view and any structured form (JSON object, INI sections).
pipeline
Package pipeline wires the stages together: parsed blob → recognize → for each match (authenticate → recon → summarize) → notes.
Package pipeline wires the stages together: parsed blob → recognize → for each match (authenticate → recon → summarize) → notes.
recognize
Package recognize routes parsed input to modules.
Package recognize routes parsed input to modules.
recon
Package recon provides the single HTTP client every module uses for recon.
Package recon provides the single HTTP client every module uses for recon.
redact
Package redact masks secret material so it never appears in Geiger output.
Package redact masks secret material so it never appears in Geiger output.
score
Package score derives a relative blast-radius score and tier for a Note.
Package score derives a relative blast-radius score and tier for a Note.
sign
Package sign holds the request/assertion signing schemes Geiger modules need: RS256 JWT assertions (GCP, Salesforce, Snowflake), Azure SharedKey, HTTP Digest (MongoDB Atlas), and generic HMAC.
Package sign holds the request/assertion signing schemes Geiger modules need: RS256 JWT assertions (GCP, Salesforce, Snowflake), Azure SharedKey, HTTP Digest (MongoDB Atlas), and generic HMAC.
tools
coverage command
Command coverage regenerates the credential-coverage table for the README from the live module registry.
Command coverage regenerates the credential-coverage table for the README from the live module registry.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL