Skip to main content

A simple secret/credential scanner for source code repositories.

Project description

secret-scan

PyPI version PyPI downloads CI Python License: MIT

A fast, lightweight CLI tool to detect secrets in source code. Zero dependencies — stdlib only.

secret-scan scans directories for sensitive data such as:

  • AWS Access Keys and Secret Keys
  • GitHub tokens (PAT, OAuth, App, fine-grained)
  • Slack tokens (bot, user)
  • Stripe keys (live and test)
  • Google API keys
  • OpenAI API keys
  • npm and PyPI tokens
  • Twilio and SendGrid API keys
  • Heroku and HashiCorp Vault tokens
  • Passwords, Bearer tokens, and JWTs
  • SSH/RSA/PGP private keys
  • Azure storage keys
  • Database connection strings

It skips binary files, ignores common junk directories (node_modules, .git, venv, etc.), avoids scanning large files, and supports extensible detection rules.

Installation

pip install secret-scan

To upgrade:

pip install --upgrade secret-scan

Check version:

secret-scan --version

Quick Start

# Scan current directory
secret-scan .

# Only show high-confidence findings
secret-scan . --severity error

# JSON output for scripting
secret-scan . --json

# SARIF output for GitHub/GitLab integration
secret-scan . --sarif > results.sarif

# Advisory mode (always exit 0)
secret-scan . --no-fail

GitHub Action (Marketplace)

The easiest way to add secret scanning to your CI — no pip install needed:

name: Secret Scan

on: [push, pull_request]

jobs:
  secret-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: harshahemanth/secret-scan@v1

SARIF + Code Scanning

Upload results to GitHub's Security tab:

name: Secret Scan

on: [push, pull_request]

permissions:
  security-events: write

jobs:
  secret-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: harshahemanth/secret-scan@v1
        id: scan
        with:
          sarif: "true"
          no-fail: "true"

      - name: Upload SARIF
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: ${{ steps.scan.outputs.sarif-file }}

Action Inputs

Input Description Default
path Directory to scan .
severity Minimum severity: error, warning, or note (all)
sarif Output SARIF format false
no-fail Always exit 0 (advisory mode) false
entropy Enable entropy-based detection false
extra-args Additional CLI arguments

Action Outputs

Output Description
sarif-file Path to SARIF file (when sarif=true)
exit-code Scanner exit code (0=clean, 1=secrets found)

CI/CD Integration

GitHub Actions (manual install)

Add this to .github/workflows/secret-scan.yml:

name: Secret Scan

on: [push, pull_request]

jobs:
  secret-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install secret-scan
        run: pip install secret-scan

      - name: Scan for secrets
        run: secret-scan . --output /dev/null

The scanner exits with code 1 if secrets are found, which will fail the workflow.

GitHub Actions with SARIF (Code Scanning)

Upload results to GitHub's Security tab:

name: Secret Scan

on: [push, pull_request]

permissions:
  security-events: write

jobs:
  secret-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install secret-scan
        run: pip install secret-scan

      - name: Scan for secrets
        run: secret-scan . --sarif --no-fail --output /dev/null > results.sarif

      - name: Upload SARIF
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: results.sarif

GitLab CI

secret-scan:
  image: python:3.12-slim
  script:
    - pip install secret-scan
    - secret-scan . --output /dev/null

Pre-commit Hook

Add to .pre-commit-config.yaml:

repos:
  - repo: local
    hooks:
      - id: secret-scan
        name: secret-scan
        entry: secret-scan
        args: ['.', '--output', '/dev/null']
        language: python
        additional_dependencies: ['secret-scan']
        pass_filenames: false

Exit Codes

Exit Code Meaning
0 No secrets found
1 Secrets were found

Use --no-fail to always exit with 0 (advisory mode):

secret-scan . --no-fail

Severity Filter

Each finding has a severity: error (high confidence), warning (medium), or note (low).

Filter to only show high-confidence findings:

secret-scan . --severity error

Show errors and warnings (exclude notes):

secret-scan . --severity warning

JSON Output

Generate JSON output (useful for CI pipelines):

secret-scan . --json

Example output:

[
  {
    "file": "config/settings.py",
    "line": 20,
    "match": "AWS_ACCESS_KEY_ID=AKIA1234567890ABCD12",
    "rule_id": "aws-access-key-assignment",
    "rule_name": "AWS Access Key Assignment",
    "severity": "error",
    "column": 0,
    "end_column": 42
  }
]

SARIF Output

Generate SARIF v2.1.0 output for integration with GitHub Code Scanning, GitLab SAST, and other security tools:

secret-scan . --sarif

Suppressing False Positives

.secretscanignore

Create a .secretscanignore file in your project root to suppress known false positives:

# Ignore entire files or directories
tests/fixtures/*.json
docs/**

# Ignore a specific rule for a specific file
config/settings.py:generic-secret

# Ignore matches containing specific text
!match:EXAMPLE_KEY_DO_NOT_USE

Inline suppression

Add # nosecret to any line to suppress detection on that line:

DEFAULT_KEY = "sk-placeholder-not-real"  # nosecret

Use --no-ignore to bypass all suppression rules:

secret-scan . --no-ignore

Command-Line Options

Flag Description
-v, --version Show version and exit
-o, --output <file> Save text results (default: docsCred.txt)
--skip-ext .log Skip specific file extensions
--skip-dir <dir> Skip specific directories
--max-size-mb N Scan only files smaller than N MB
--severity <level> Minimum severity: error, warning, or note
--json Print JSON results to stdout
--sarif Print SARIF v2.1.0 results to stdout
--no-fail Always exit 0 even if secrets are found
--no-ignore Do not read .secretscanignore file
--entropy Enable entropy-based detection (opt-in)

What It Detects

Each detection rule has a unique rule_id and a severity level (error, warning, or note).

Cloud Providers

Provider What Severity
AWS Access Key IDs (AKIA...), Secret Access Keys error
Azure Storage account keys, Account keys error
Google API keys (AIza...) error
Heroku API key assignments error
HashiCorp Vault Service tokens (hvs.) error

SaaS / API Platforms

Provider What Severity
GitHub PAT, OAuth, App, Refresh, Fine-grained tokens error
Slack Bot tokens (xoxb-), User tokens (xoxp-) error
Stripe Live secret/publishable/restricted keys error/warning
Stripe Test keys note
OpenAI API keys (sk-) error
Twilio API keys (SK...) error
SendGrid API keys (SG.) error
npm Access tokens error
PyPI API tokens error

Generic Patterns

What Severity
Password assignments (password=, passwd=, pwd=) warning
Bearer tokens error
JWT tokens warning
API key/token assignments warning
Private key blocks (PEM headers) error
SSH RSA public keys note
Database connection strings warning
Generic secret assignments warning

Entropy-Based Detection

Use --entropy to detect high-entropy hex and base64 strings that don't match any known pattern. This catches secrets that slip through regex-based rules.

secret-scan . --entropy
secret-scan . --entropy --json

This is opt-in to avoid false positive noise. When enabled, the scanner tokenizes each line and computes Shannon entropy for candidate strings.

Thresholds:

Type Min Length Entropy Threshold
Hex strings 20 chars 3.0 bits/char
Base64 strings 20 chars 4.5 bits/char

Automatically excluded (false positive filters):

  • UUIDs (550e8400-e29b-41d4-a716-446655440000)
  • CSS hex colors (#1a2b3c)
  • Version strings (v1.2.3...)
  • Lockfile hashes (sha256-..., sha512-...)
  • Repeated characters (AAAAAA...)
  • Entire lockfiles (package-lock.json, yarn.lock, etc.)

Entropy findings use rule IDs high-entropy-hex and high-entropy-base64, both at severity warning. They respect # nosecret inline suppression and .secretscanignore rules.

Automatic Skips

The scanner automatically ignores:

  • .git, .hg, .svn
  • node_modules
  • Python virtual environments (venv, .venv, env)
  • IDE directories (.idea, .vscode)
  • Binary files (null-byte detection)
  • Large files (over 5 MB by default)
  • Common non-text extensions (images, archives, executables)

Extending Detection Patterns

Detection patterns are defined as SecretPattern dataclass instances in:

src/secret_scanner/patterns.py

Each pattern has a rule_id, name, severity, pattern (regex), and description. You can add new patterns by appending to the PATTERNS list.

Programmatic Usage

from pathlib import Path
from secret_scanner import scan_directory

matches = scan_directory(Path("."), output_path=None)
for m in matches:
    print(f"[{m['severity']}] {m['rule_name']}: {m['file']}:{m['line']}")

Running Tests

PYTHONPATH=src pytest tests/ -q

Contributing

Contributions are welcome.

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Open a pull request

License

This project is licensed under the MIT License. See the LICENSE file for full details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

secret_scan-0.3.0.tar.gz (24.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

secret_scan-0.3.0-py3-none-any.whl (19.1 kB view details)

Uploaded Python 3

File details

Details for the file secret_scan-0.3.0.tar.gz.

File metadata

  • Download URL: secret_scan-0.3.0.tar.gz
  • Upload date:
  • Size: 24.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for secret_scan-0.3.0.tar.gz
Algorithm Hash digest
SHA256 73255901150cbdc615e1f747a713ba6c1dbeac9f35773bb43800fb155a426fc0
MD5 02648fe55cb6b45ce2f900c7fdec503d
BLAKE2b-256 aaa51fdc88837ae19badb09a5774e80d6013eefb1b5a2d0dc63ad0eb5d2dbc61

See more details on using hashes here.

Provenance

The following attestation bundles were made for secret_scan-0.3.0.tar.gz:

Publisher: publish.yml on harshahemanth/secret-scan

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file secret_scan-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: secret_scan-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 19.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for secret_scan-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8403c6b962bff5718cb0524a8e167a37a6672a6b1306bc7b880a424afcb4efb4
MD5 d05d130ff945a37f4be1028281095cbf
BLAKE2b-256 fdb0d79825d6ad315a523396f1be364fc580f4af0b9b42f4b0a4bc2c024c9e31

See more details on using hashes here.

Provenance

The following attestation bundles were made for secret_scan-0.3.0-py3-none-any.whl:

Publisher: publish.yml on harshahemanth/secret-scan

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page