Scan for hardcoded secrets before they reach your repository
Project description
nosecrets
Scan for hardcoded secrets before they reach your repository.
Zero runtime dependencies. Runs as a pre-commit hook or standalone CLI. Designed for developers who want a lightweight, auditable secrets scanner without pulling in a 20MB Go binary or a heavy Python dependency tree.
$ secrets scan
[CRITICAL] src/config.py:14
AWS Access Key ID: AKIA************MPLE
[HIGH] deploy/docker-compose.yml:8
Database Connection String: postg****alhost
Found 2 potential secret(s): 1 CRITICAL, 1 HIGH
To suppress a finding:
Inline: add # nosecrets at end of line
Global: add path to .secretsignore
Why nosecrets?
| Feature | gitleaks | truffleHog | detect-secrets | nosecrets |
|---|---|---|---|---|
| Git history scan | ✅ | ✅ | ❌ | ✅ |
| SARIF output | ✅ | ✅ | ❌ | ✅ |
| Baseline file | ❌ | ❌ | ✅ | ✅ |
| Zero runtime deps | ❌ Go binary | ❌ | ❌ | ✅ |
pip install |
❌ | ❌ | ✅ | ✅ |
| False positive handling | weak | weak | ok | best-in-class |
The only zero-dependency Python tool with git history scanning, SARIF output, and baseline suppression — all three.
Install
pip install nosecrets
Requires Python 3.12+.
Usage
# Scan current directory
secrets scan
# Scan a specific path
secrets scan src/
# Scan only staged files (pre-commit)
secrets scan --staged
# Output formats
secrets scan --format text # coloured output (default)
secrets scan --format json # JSON for CI pipelines
secrets scan --format sarif # SARIF for GitHub Advanced Security
# Only report HIGH and above
secrets scan --severity high
# Scan entire git history (finds secrets in deleted commits too)
secrets scan --history
secrets scan --history --max-commits 50
# Baseline — skip known findings, report only new ones
secrets baseline # write .nosecrets-baseline.json
secrets scan --baseline # compare against baseline
# Install pre-commit hook
secrets init
# Remove hook
secrets uninstall
Pre-commit hook
secrets init
Installs a git hook that runs secrets scan --staged before every commit. If a CRITICAL or HIGH secret is found, the commit is blocked.
To remove:
secrets uninstall
What it detects
| Severity | Pattern |
|---|---|
| CRITICAL | RSA / EC / OpenSSH private keys |
| CRITICAL | AWS Access Key ID (AKIA...) |
| CRITICAL | AWS Secret Access Key (with keyword context) |
| CRITICAL | Azure Storage connection string (DefaultEndpointsProtocol=...) |
| CRITICAL | Azure Storage Account Key (with keyword context) |
| CRITICAL | OpenAI API Key (sk-..., sk-proj-...) |
| CRITICAL | Anthropic API Key (sk-ant-...) |
| CRITICAL | Stripe Live Secret Key (sk_live_...) |
| HIGH | GitHub Tokens (ghp_, github_pat_, gho_, ghs_, ghr_) |
| HIGH | GitLab Personal Access Token (glpat-...) |
| HIGH | npm Access Token (npm_...) |
| HIGH | Google API Key (AIza...) |
| HIGH | Slack Bot / User / Webhook tokens |
| HIGH | SendGrid API Key (SG....) |
| HIGH | Twilio Account SID (AC...) |
| HIGH | Database connection strings with credentials |
| MEDIUM | JSON Web Tokens (hardcoded) |
| MEDIUM | Generic secrets (high-entropy api_key, password, token values) |
False positive prevention
Two-layer defence against false positives:
1. Placeholder detection — values like "changeme", "your_api_key_here", ${SECRET}, {{token}} are never flagged regardless of pattern match.
2. Shannon entropy filter — generic patterns (password, api_key, token) only trigger when the value has sufficient entropy. password = "test123" is ignored. password = "X7#mK9$pL2@nQ8!" is flagged.
High-confidence patterns (AWS AKIA..., GitHub ghp_..., etc.) skip entropy filtering because their fixed prefix already guarantees low false positive rate.
Suppression
Inline — suppress a single line:
api_key = "AKIAIOSFODNN7EXAMPLE" # nosecrets
File/directory — .secretsignore:
# gitignore-style syntax
tests/fixtures/
*.example
legacy_config.py
Copy .secretsignore.example from the repo as a starting point.
Exit codes
| Code | Meaning |
|---|---|
0 |
No findings at or above --fail-on threshold |
1 |
One or more findings at or above threshold |
Default --fail-on is high. Change with --fail-on critical to only block on critical findings.
CI integration
# GitHub Actions — basic
- name: Scan for secrets
run: |
pip install nosecrets
secrets scan --severity medium
# GitHub Actions — SARIF upload (shows findings inline in PR diffs)
- name: Scan for secrets
run: |
pip install nosecrets
secrets scan --format sarif > results.sarif
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
# GitHub Actions — baseline (report only new secrets)
- name: Scan for new secrets
run: |
pip install nosecrets
secrets scan --baseline # requires .nosecrets-baseline.json committed to repo
Philosophy
"A secrets scanner that leaks its own secrets is not a secrets scanner."
- Zero runtime dependencies — stdlib only, fully auditable
- Staged scanning reads from the git index (
git show :<path>), not the working tree — you scan exactly what will be committed - Secrets are never printed in full — output always redacts the middle portion
- Pattern quality over quantity — 20 well-tested patterns beat 500 noisy ones
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nosecrets-0.3.1.tar.gz.
File metadata
- Download URL: nosecrets-0.3.1.tar.gz
- Upload date:
- Size: 20.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4d801cf11abcc4941de36dbc0ed75e56389c78749814fb3f5c5103b825054f2a
|
|
| MD5 |
f4a514b3abec00f919bb33941acbe314
|
|
| BLAKE2b-256 |
55a40e71450ce15054f0cf63105f8448d705419f056b8fa0a50667a4e15394dc
|
File details
Details for the file nosecrets-0.3.1-py3-none-any.whl.
File metadata
- Download URL: nosecrets-0.3.1-py3-none-any.whl
- Upload date:
- Size: 18.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
51cdaa039d6589af684602601da4b462ccfeeab850456646f942a060228ec297
|
|
| MD5 |
7cb1fbc583bed290fff698131f577cfa
|
|
| BLAKE2b-256 |
8fc8a6a5fe1cd1074677567142274a3e82a26bb723b5e7b750832d7e7cdcf30e
|