CREDENTIAL SCANNER
devops@credscan $ man credscan
// how to leverage CredScan from the online GUI, Docker, locally, or the CLI
devops@credscan $ credscan --help # what is this
// hardcoded-secret scanner for cloud-native sources, with transparent scoring and verification

CredScan finds hardcoded secrets across source code, Infrastructure-as-Code, CI/CD pipelines, Docker, git history, and web endpoints, and can verify which keys are still live. It is built for developers and cloud-security engineers who need to know not just that a key leaked, but where it came from and whether it still works.

what it scans[8 parser sources + git history + web]
// purpose-built for IaC, pipelines, and containers
[✓] Terraform .tf / .tfvars + CloudFormation [✓] GitHub Actions / GitLab CI / CircleCI / Jenkinsfile [✓] Dockerfile + image tarballs [✓] .env files [✓] JSON + YAML [✓] source code (.py .js .ts .go .java .rb .c .cpp .cs .php .kt .swift) [✓] archives (zip / tar / jar / war / apk / ipa) [✓] git commit history [✓] web URLs
what it detects[15+ categories]
// provider-anchored where possible; private keys are critical severity
[✓] AWS access keys + secret keys [✓] GCP service-account + API keys [✓] Azure connection strings [✓] Stripe [✓] Slack [✓] GitHub / GitLab / Bitbucket tokens [✓] Twilio / SendGrid / Mailgun [✓] OpenAI / Anthropic / HuggingFace [✓] DB connection strings (postgres / mysql / mongodb / redis) [✓] generic passwords [✓] JWT [✓] OAuth client secrets [✓] private keys (RSA / DSA / EC / OPENSSH / PGP) [✓] PKCS#12 / PFX [✓] X.509 certificates
devops@credscan $ credscan --get-started
// four ways to run it; pick by what you can install and how much power you need
two-image safety model[read first]
// the public image is safe by construction; the local image is trusted-machine-only

The hosted/public path omits boto3 and defaults to public mode (upload-only, sandboxed, no path scanning, no git-history, no live validation), so no single misconfiguration turns the demo into a host-filesystem reader or a credential-checking oracle. The local path is a separate image with full power: path scanning, git-history, and AWS validation. Run it only on your own machine.

[✓] public = upload-only, sandboxed[✓] local = full power, trusted machine
1. online[hosted public GUI]
// nothing to install; upload files or paste text in the browser

Open the hosted GUI, upload files or paste text, and read the masked findings. Public mode is hardened: no filesystem or path scanning, no git-history, no live validation. Content is scanned in a per-request sandbox and deleted; hard limits apply (2 MB, 200 files, rate-limited).

[✓] upload or paste[✓] sandboxed + deleted[✓] findings masked
2. docker public[upload-only image]
// build the hardened public image and run it
$ docker build -f Dockerfile.gui -t credscan-gui .
$ docker run -p 8000:8000 credscan-gui
// then open http://localhost:8000

This image runs public mode by construction (no boto3, no path scanning, no git-history, no validation): the same upload-only experience as the hosted GUI above, in a container you control.

3. docker local[full power, your machine]
// path scan + git-history + AWS validation; loopback-published, never exposed
$ docker build -f Dockerfile.gui.local -t credscan-gui-local .
$ docker run --rm -p 127.0.0.1:8000:8000 -v "$PWD:/scan:ro" credscan-gui-local
// mount the code you want to scan at /scan; publish to 127.0.0.1 so it is unreachable off-machine

This is a separate image that includes boto3 and runs local mode, so the browser UI can do everything the CLI can. It is not safe to expose; publish the port to loopback only. For AWS validation, also mount your credentials read-only.

$ docker run --rm -p 127.0.0.1:8000:8000 -v "$PWD:/scan:ro" -v "$HOME/.aws:/home/scanner/.aws:ro" credscan-gui-local
4. local pip[install from source]
// the local GUI in full mode, or the CLI directly
$ pip install -e ".[gui,aws]"
// then run the GUI (local mode: path scan + git-history + validation)
$ credscan-gui
// or run the CLI against the current directory
$ credscan -p .

The gui extra installs fastapi, uvicorn, and python-multipart; the aws extra adds boto3 for live AWS key validation. The CLI accepts every flag documented in the rest of this guide.

devops@credscan $ credscan --explain detection
// four layers, applied in order: pattern, entropy, context, confidence

A finding passes through four layers before it reaches output. Each layer contributes a signal; none of them is a verdict on its own. The last layer combines the signals into a single confidence score and drops anything below the threshold.

layer-1 pattern-match[high precision, structured secrets]
// provider-anchored regex

Provider-specific regex matches structured secrets: AWS access keys, GitHub and Slack tokens, Stripe keys, private-key PEM blocks, and so on. When a value carries a known provider shape, the match is high precision and anchors the rest of the pipeline.

[✓] aws[✓] github[✓] slack[✓] stripe[✓] private-key
layer-2 entropy[contributing factor, never a verdict]
// Shannon entropy with per-type thresholds

Shannon entropy flags random-looking strings that have no provider shape. The threshold is per encoding type, because a base64 blob, a hex digest, and a JWT do not carry the same bits per character. Entropy alone never decides a finding; it feeds the score in layer four.

base644.5
jwt4.0
hex3.8
// UUIDs and named integrity hashes (sha256-..., md5-...) are filtered as known false positives
layer-3 context[prod vs test/docs/example]
// examines the surrounding lines

Context reads the lines around the match and the file path to tell a production config apart from a test fixture, a doc snippet, or an example. A production signal raises confidence; a test or example signal lowers it, though not to zero, since test files still leak working keys.

layer-4 confidence[weighted combination]
// pattern + context + entropy + technology, then filter

The score is a weighted combination of the prior layers plus a technology signal. Pattern match carries the most weight, then context, then entropy, then technology. The result is bounded to 0.0 to 1.0 and explained per finding.

factorweight
pattern match0.30
context0.25
entropy0.20
technology0.15
environment + validation0.10
// default min-confidence 0.3; findings below it are filtered before output
$ credscan -p . --min-confidence 0.3
// honest tradeoff

gitleaks is faster; it is written in Go and runs regex at scale. CredScan trades some of that speed for the entropy, context, and scoring passes, which is what lets it report lower-precision classes such as generic and assignment-style secrets without burying you in noise.

devops@credscan $ credscan --verify --check-breaches
// turn a "looks like a secret" finding into "this key is live" or "this password is breached"
live-verification[opt-in, read-only, rate-limited]
// each token is sent only to its own provider, over a read-only call, never to a third party

Pattern, entropy, and context tell you a string looks like a credential. Verification tells you whether it still works. It is off by default and you enable it explicitly; the calls are read-only and rate-limited.

[✓] opt-in only [✓] read-only calls [✓] rate-limited [✓] token sent only to its own provider
$ credscan -p . --validate-aws
$ credscan -p . --verify
providerflagread-only check
AWS--validate-awssts:GetCallerIdentity
GitHub--verifyGET /user
Slack--verifyauth.test
Stripe--verifyGET /v1/account
GCP--verifyoauth2 tokeninfo
OpenAI--verifyGET /v1/models
Anthropic--verifyGET /v1/models
npm--verifyGET /-/whoami
// what the result means
verified liveescalated to critical
// a live key is the strongest signal the scanner gives: near-100% precision
network or parse errorreads as UNVERIFIED
// an unverifiable read is never treated as invalid; absence of proof is not proof of safety
// Azure and PyPI are detected but not verified: there is no honest read-only check for them, so credscan does not claim to verify them
breach-correlation[--check-breaches]
// cross-check password-like findings against the HaveIBeenPwned Pwned Passwords corpus

This correlates password-like findings against the HaveIBeenPwned Pwned Passwords corpus using k-anonymity. The secret never leaves the machine.

$ credscan -p . --check-breaches
[✓] SHA-1 computed locally [✓] only the first 5 hex chars of the hash are sent [✓] match checked locally [✓] secret never leaves the machine
// what a hit means
seen in N known breachesseverity escalated
// provider keys (AWS, PEM private keys) are excluded: the password corpus is the wrong reference for them
devops@credscan $ credscan -p . -o sarif,compliance -d ./reports
// pick a format, wire it into CI, track false positives
output formats[--output / -o, comma-separated; --output-dir / -d]
// all human-readable output masks values (AKIA...MPLE). full values live only in the json audit log on the CLI.
formatuse case
consoledefault, colored terminal output for local runs
jsonfull detail incl. remediation; the audit log, full values here only
sarifSARIF 2.1.0 for GitHub code scanning and VS Code; CWE tags
htmlmasked and escaped report for sharing
excelspreadsheet of findings; masked values
csvflat findings table; masked values
pdfprintable report; masked values
complianceCSV pivoted by control framework for auditors; masked values
$ credscan -p ./src -o json,sarif -d ./reports
sarif + github code scanning[SARIF 2.1.0]
// the sarif report loads in the github security tab and in vs code.
[✓] SARIF 2.1.0 schema [✓] CWE tags per rule [✓] stable partialFingerprints for cross-run dedup
// CWE mapping: CWE-798 hard-coded credentials, CWE-259 hard-coded password, CWE-321 hard-coded cryptographic key.
compliance export[-o compliance]
// one CSV, framework-segmented: a provenance header, then one row per finding x control.
// pivot on the Framework column across CWE, NIST 800-53, PCI-DSS v4.0, OWASP ASVS, SOC 2, ISO 27001.
[✓] Finding ID, stable across scans [✓] verification status [✓] confidence [✓] remediation
// values are masked; this report is for auditors, not for secrets.
github action[official]
// scans on push/PR, uploads SARIF to the Security tab, fails the job on findings.
default outputsarif
fail-on-findingsjob fails when secrets found
sarif-fileoutput path for upload
pre-commit hook[--install-hook]
// scan staged changes before the commit lands.
$ credscan --install-hook --hook-config block
[✓] warning-only: warn but allow the commit [✓] block: stop the commit when credentials are found
baseline[false-positive management]
// record known false positives once; later scans exclude them.
$ credscan -p . --create-baseline .credscan-baseline.json
$ credscan -p . --baseline-file .credscan-baseline.json
$ credscan --mark-fp FINDING_ID --baseline-file .credscan-baseline.json
incremental scans[--staged / --diff]
// scan only what changed instead of the whole tree.
$ credscan --staged
// only git-staged changes; fast, for pre-commit.
$ credscan --diff origin/main
// only files changed vs a git ref; for CI on a PR.
exit codes[for CI gating]
0clean
1credentials found
2argument error
devops@credscan $ credscan --help
// flags grouped as the help prints them; defaults shown inline
scan target[where to look]
// pick a path, a git diff, or a web URL
flagdescription
--path, -p PATHDirectory or file to scan (default: .)
--exclude, -e PATTERNSComma-separated path patterns to skip, e.g. "node_modules/,*.log"
--include, -i PATTERNSOnly scan paths matching these comma-separated patterns
--stagedScan only git-staged changes (fast; for pre-commit)
--diff REFScan only files changed vs a git ref, e.g. origin/main
--url URLWeb URL to scan for credentials
--crawlCrawl the target URL to discover additional pages
--crawl-depth NMax crawl depth (default: 2)
output[format and verbosity]
// --output takes a comma-separated list; values are masked except in json
flagdescription
--output, -o FORMATReport format(s): console, json, sarif, html, excel, csv, pdf, compliance (default: console)
--output-dir, -d DIRDirectory for saved reports (default: .)
--group-by-severityGroup findings by severity (critical, high, medium, low)
--summary-modePrint a one-line summary per file instead of full details
--show-confidence-detailsShow per-factor confidence score breakdown
--show-test-credentialsInclude auto-detected test/example credentials in output
--no-colorDisable ANSI colors (useful for CI logs)
--verbose, -vEnable debug-level logging
detection[tune the pipeline]
// min-confidence defaults to 0.3; entropy and context can be switched off
flagdescription
--min-confidence SCOREMinimum confidence to report a finding, 0.0 to 1.0 (default: 0.3)
--entropy-threshold NShannon entropy threshold; raise to reduce false positives (default: 4.0)
--min-length NMinimum credential value length (default: 6)
--no-entropyDisable all entropy-based detection
--no-context-analysisDisable context-aware false positive filtering
--no-deduplicationShow every raw finding instead of grouped/deduped results
cloud security[opt-in verification]
// read-only checks; tokens go only to their own provider, breach checks use k-anonymity
--validate-awsVerify discovered AWS keys via sts:GetCallerIdentity (read-only, opt-in)
--verifyVerify discovered tokens against provider identity endpoints (GitHub/GCP/Slack/Stripe/OpenAI/Anthropic/npm; read-only, opt-in)
--check-breachesCorrelate passwords/secrets against known breaches via HIBP (k-anonymity: the secret never leaves the machine; opt-in)
git integration[history and hooks]
// a deleted secret still lives in history; --scan-history walks the commits
flagdescription
--scan-historyScan git commit history for credentials
--max-commits NLimit history scan to the N most recent commits
--since DATEOnly scan commits newer than DATE, e.g. "2 weeks ago"
--until DATEOnly scan commits older than DATE
--branch REFBranch or ref to scan (default: HEAD)
--install-hookInstall CredScan as a git pre-commit hook
--hook-config MODEPre-commit hook mode: warning-only, or block
baseline[false positive management]
// record known false positives once, then suppress them on future runs
flagdescription
--baseline-file FILELoad exclusions from a baseline JSON file
--create-baseline FILEWrite current findings to a new baseline file
--show-excludedShow baseline-excluded findings (marked as excluded)
--mark-fp IDMark a finding ID as false positive and add to baseline
--exclusion-reason TEXTReason stored with a baseline exclusion (default: "Marked as false positive")
examples[copy-paste]
$ credscan
// scan current directory
$ credscan -p ./src -o json,sarif -d ./reports
// scan src/, write JSON + SARIF reports
$ credscan -p ./infra --group-by-severity
// scan Terraform/CloudFormation, grouped output
$ credscan --scan-history --max-commits 100
// scan last 100 git commits
$ credscan --url https://example.com/config.js
// scan a web endpoint
$ credscan --validate-aws -p .
// scan + verify any AWS keys found are active
exit codes[for CI]
0clean
1credentials found
2argument error
devops@credscan $ cat THREAT_MODEL.md
// how the tool protects the secrets it handles
masking[default everywhere]
// human-readable output masks values; full values live only in the JSON audit log

Console, HTML, Excel, CSV, PDF, SARIF, and compliance output mask matched values (AKIA...MPLE). The full plaintext value appears only in the CLI JSON output, which is the audit log; treat that file like the secret itself.

[✓] console masked [✓] html / excel / csv / pdf masked [✓] sarif / compliance masked [✓] full value: CLI json only
html-escaping[xss boundary]
// the report renders matched text; that text is attacker-influenced

Scanned content can contain markup. The HTML report escapes matched and surrounding text before rendering, so a finding cannot inject script into the report you open. Values are masked and escaped.

two-image-model[safe by construction]
// the public image cannot be misconfigured into a path reader or a validation oracle

The public image omits boto3 and defaults to public mode. There is no single setting that turns the hosted demo into a host-filesystem reader or a credential-checking oracle; the unsafe code paths are not present. The local image is separate and documented as trusted-machine-only.

public imageno boto3
public imagepublic mode default
local imagetrusted machine only
public-mode[hardened]
// disabled capabilities, and why each would be dangerous on a public server
capabilitystatewhy disabled
filesystem / path scanningoffwould let a visitor read the host filesystem
git-history scanningoffsame host-read surface, against repo history
live validationoffwould make the server a credential-checking oracle
web / URL scanningon, guardedallowed (scanning a public URL is a valid use); an SSRF guard refuses internal, loopback, link-local, and cloud-metadata targets and re-checks every redirect hop
// content is scanned in a per-request sandbox and deleted; limits 2 MB, 200 files, rate-limited; findings masked
breach-correlation[k-anonymity]
// --check-breaches: the secret never leaves the machine

Password-like findings are checked against the HaveIBeenPwned Pwned Passwords corpus. The value is SHA-1'd locally and only the first 5 hex characters of that hash are sent; the match is resolved locally. Provider keys (AWS, PEM) are excluded because that corpus does not apply.

[✓] hashed locally (SHA-1) [✓] only 5 hex prefix sent [✓] match checked locally [✓] opt-in
verification[opt-in, read-only]
// --verify / --validate-aws: a token is sent only to its own provider

Verification is off by default. When enabled, each check is read-only and rate-limited, and a given token is sent only to the provider that issued it: GitHub to GitHub, Stripe to Stripe, AWS via sts:GetCallerIdentity. Tokens are never sent to a third party. A network or parse error reads as UNVERIFIED, never as invalid.

$ credscan -p . --verify
$ credscan -p . --validate-aws
// Azure and PyPI are detected but not verified; there is no honest read-only check for them