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.
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.
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).
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.
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.
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.
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.
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.
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.
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.
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.
| factor | weight |
|---|---|
| pattern match | 0.30 |
| context | 0.25 |
| entropy | 0.20 |
| technology | 0.15 |
| environment + validation | 0.10 |
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.
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.
| provider | flag | read-only check |
|---|---|---|
| AWS | --validate-aws | sts:GetCallerIdentity |
| GitHub | --verify | GET /user |
| Slack | --verify | auth.test |
| Stripe | --verify | GET /v1/account |
| GCP | --verify | oauth2 tokeninfo |
| OpenAI | --verify | GET /v1/models |
| Anthropic | --verify | GET /v1/models |
| npm | --verify | GET /-/whoami |
This correlates password-like findings against the HaveIBeenPwned Pwned Passwords corpus using k-anonymity. The secret never leaves the machine.
| format | use case |
|---|---|
| console | default, colored terminal output for local runs |
| json | full detail incl. remediation; the audit log, full values here only |
| sarif | SARIF 2.1.0 for GitHub code scanning and VS Code; CWE tags |
| html | masked and escaped report for sharing |
| excel | spreadsheet of findings; masked values |
| csv | flat findings table; masked values |
| printable report; masked values | |
| compliance | CSV pivoted by control framework for auditors; masked values |
| flag | description |
|---|---|
| --path, -p PATH | Directory or file to scan (default: .) |
| --exclude, -e PATTERNS | Comma-separated path patterns to skip, e.g. "node_modules/,*.log" |
| --include, -i PATTERNS | Only scan paths matching these comma-separated patterns |
| --staged | Scan only git-staged changes (fast; for pre-commit) |
| --diff REF | Scan only files changed vs a git ref, e.g. origin/main |
| --url URL | Web URL to scan for credentials |
| --crawl | Crawl the target URL to discover additional pages |
| --crawl-depth N | Max crawl depth (default: 2) |
| flag | description |
|---|---|
| --output, -o FORMAT | Report format(s): console, json, sarif, html, excel, csv, pdf, compliance (default: console) |
| --output-dir, -d DIR | Directory for saved reports (default: .) |
| --group-by-severity | Group findings by severity (critical, high, medium, low) |
| --summary-mode | Print a one-line summary per file instead of full details |
| --show-confidence-details | Show per-factor confidence score breakdown |
| --show-test-credentials | Include auto-detected test/example credentials in output |
| --no-color | Disable ANSI colors (useful for CI logs) |
| --verbose, -v | Enable debug-level logging |
| flag | description |
|---|---|
| --min-confidence SCORE | Minimum confidence to report a finding, 0.0 to 1.0 (default: 0.3) |
| --entropy-threshold N | Shannon entropy threshold; raise to reduce false positives (default: 4.0) |
| --min-length N | Minimum credential value length (default: 6) |
| --no-entropy | Disable all entropy-based detection |
| --no-context-analysis | Disable context-aware false positive filtering |
| --no-deduplication | Show every raw finding instead of grouped/deduped results |
| flag | description |
|---|---|
| --scan-history | Scan git commit history for credentials |
| --max-commits N | Limit history scan to the N most recent commits |
| --since DATE | Only scan commits newer than DATE, e.g. "2 weeks ago" |
| --until DATE | Only scan commits older than DATE |
| --branch REF | Branch or ref to scan (default: HEAD) |
| --install-hook | Install CredScan as a git pre-commit hook |
| --hook-config MODE | Pre-commit hook mode: warning-only, or block |
| flag | description |
|---|---|
| --baseline-file FILE | Load exclusions from a baseline JSON file |
| --create-baseline FILE | Write current findings to a new baseline file |
| --show-excluded | Show baseline-excluded findings (marked as excluded) |
| --mark-fp ID | Mark a finding ID as false positive and add to baseline |
| --exclusion-reason TEXT | Reason stored with a baseline exclusion (default: "Marked as false positive") |
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.
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.
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.
| capability | state | why disabled |
|---|---|---|
| filesystem / path scanning | off | would let a visitor read the host filesystem |
| git-history scanning | off | same host-read surface, against repo history |
| live validation | off | would make the server a credential-checking oracle |
| web / URL scanning | on, guarded | allowed (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 |
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.
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.