Skip to main content

CLI toolchain to detect and prevent accidental publication of sensitive data via git

Project description

git-safe-publish

git-safe-publish logo

A CLI toolchain that analyzes git repositories, commit history, and staged content to detect and prevent the accidental publication of sensitive data. It acts as a safety layer between a developer's local work and any remote push.

Features

  • Secret detection — 35+ built-in patterns: AWS, GCP, Azure, GitHub, GitLab, Stripe, OpenAI, Anthropic, Slack, database URLs, PEM keys, JWTs, and more
  • High-entropy heuristics — catches unknown/custom secrets via Shannon entropy analysis
  • Sensitive file detection — flags .env, *.pem, *.key, terraform.tfvars, *.tfstate, kubeconfig, and 30+ other risky types
  • Metadata scanning — checks branch names, tag annotations, git stash, submodule URLs, .git/hooks integrity, and GitHub Actions misconfigurations
  • Author identity validation — confirms committer email/name matches expectations
  • Push safety — guards against wrong remotes, force-pushing protected branches, insecure protocols
  • .gitignore auditing — detects missing coverage for common sensitive patterns
  • Full history scan — surfaces secrets buried in old commits with exposure window reporting
  • Guided remediation — generates exact git filter-repo commands to remove secrets from history
  • SARIF / Markdown output — integrate with GitHub Code Scanning or post findings as PR comments
  • Inline suppression — suppress individual findings with # gsp-ignore comments
  • Allowlist — persist false-positive suppressions in .git-safe-allowlist.yml
  • Custom patterns — extend detection via .git-safe-publish.yml

Installation

pip install git-safe-publish

Or install from source:

git clone https://github.com/your-org/git-safe-publish
cd git-safe-publish
pip install -e .

Commands

Command Description
git-safe-check Scan staged/tracked content. Exits 0 = clean, 1 = issues, 2 = error.
git-safe-commit Drop-in for git commit — scans staged changes and commit message.
git-safe-push Drop-in for git push — runs checks before pushing.
git-safe-publish Interactive full check + identity confirm + push.
git-safe-search Deep-scan entire commit history.
git-safe-hooks Install, remove, and manage git hooks.
git-safe-fix Generate guided git filter-repo remediation commands.
git-safe-scan Scan arbitrary files or directories — no git repo required.

Usage

Commit safely

# Drop-in for git commit — scans staged changes and commit message
git-safe-commit -m "feat: add login page"

# Skip checks (e.g. amending with --no-edit)
git-safe-commit --amend --no-edit --skip-checks

Check staged content

# Scan staged changes and all tracked files
git-safe-check

# Staged changes only
git-safe-check --staged

# PR/CI mode — scan only lines changed vs. a base branch
git-safe-check --base main

# Re-run every 3 seconds (Ctrl+C to stop)
git-safe-check --watch

# Show all 35+ built-in patterns
git-safe-check --list-patterns

# Test a custom regex against a sample value
git-safe-check --test-pattern "MYCO-[A-Z0-9]{20}" --against "MYCO-ABC123DEF456GHI789JK"

# Also scan branch names, tags, submodules, hooks, and GitHub Actions
git-safe-check --metadata

Push safely

# Drop-in for git push
git-safe-push origin main

# Full interactive flow with identity confirmation
git-safe-publish --remote origin --branch main

Scan history

# Scan all commits on all branches
git-safe-search

# Filter by date or author
git-safe-search --since 2024-01-01 --author "@yourcompany.com"

# Show exposure windows (first / last seen per finding)
git-safe-search --exposure

# Scan only last 50 commits on current branch
git-safe-search --branch HEAD --limit 50

# Include branch names, tags, stash, and metadata
git-safe-search --metadata

Output formats

All commands support --format and --output:

# Write SARIF for GitHub Code Scanning
git-safe-search --format sarif --output results.sarif

# Write a Markdown report (e.g. for a PR comment)
git-safe-check --format markdown --output report.md

# JSON for custom tooling
git-safe-search --format json --output findings.json

Guided remediation

# Scan history and generate a git filter-repo remediation script
git-safe-fix --history --output fix.sh
cat fix.sh   # review before running!

Scan arbitrary files

# Scan a directory with no git repo needed
git-safe-scan ./config-backup/
git-safe-scan /tmp/archive/ --severity P1 --format sarif --output scan.sarif

# Scan specific files
git-safe-scan settings.py .env

Manage git hooks

# Install all three hooks (pre-commit, commit-msg, pre-push)
git-safe-hooks install

# Install a specific hook
git-safe-hooks install --hook pre-commit

# Show hook status
git-safe-hooks status

# Remove all managed hooks
git-safe-hooks uninstall

Generate CI integration

# Print a ready-to-use GitHub Actions workflow with SARIF upload
git-safe-hooks ci github

# Write it directly to .github/workflows/
git-safe-hooks ci github --output .github/workflows/git-safe-publish.yml

# GitLab CI snippet
git-safe-hooks ci gitlab

# pre-commit framework config
git-safe-hooks ci pre-commit

Inline suppression

Add # gsp-ignore to a line to suppress all findings on it. Specify a check name to be more precise:

# Suppress everything on this line
EXAMPLE_KEY = "AKIAIOSFODNN7EXAMPLE"  # gsp-ignore

# Suppress a specific check only
STRIPE_WEBHOOK = os.getenv("STRIPE_WEBHOOK")  # gsp-ignore: stripe-secret-key

# Suppress multiple checks
DB_URL = "postgres://..."  # gsp-ignore: postgres-url, basic-auth-in-url

Allowlist

For persistent false-positive suppression, create .git-safe-allowlist.yml in your repo:

# .git-safe-allowlist.yml
- check_name: aws-access-key-id
  filename: tests/fixtures/config.py
  line_hash: <sha256-of-line-content>
  reason: "Test fixture  not a real key"

- check_name: generic-password-assignment
  filename: ""    # matches any file
  reason: "Default config example values"

Configuration

Generate a starter config:

git-safe-check --init-config

Key options in .git-safe-publish.yml:

# Minimum severity to fail: P0 | P1 | P2 | P3
severity_threshold: "P0"

# Block commit/push when blockers found
block_on_secrets: true

# Branches that block force-push
protected_branches: [main, master, production]

# Require committer email to match a regex
required_email_pattern: ".*@yourcompany\\.com$"

# Require GPG/SSH commit signing
require_signed_commits: false

# Paths/globs to skip
ignore_paths:
  - "tests/**"
  - "*.example"

# Custom patterns
custom_patterns:
  - name: my-internal-token
    regex: "MYCO-[A-Za-z0-9]{32}"
    severity: P0
    category: Internal
    description: "Acme Corp internal service token"

A global config at ~/.git-safe-publish.yml applies to all repositories.

Exit codes

Code Meaning
0 Clean — no issues at or above the configured severity threshold
1 Issues found
2 Tool error (not a git repo, git command failed, etc.)

Severity levels

Level Label Examples
P0 CRITICAL AWS key, private key, Stripe live key
P1 HIGH OpenAI key, database URL with credentials, GitHub PAT, pull_request_target misconfiguration
P2 MEDIUM Generic hardcoded password, JWT, absolute path disclosure, unpinned GitHub Action
P3 LOW Commented-out credentials, TODO referencing secrets, unmanaged hook

Support

If you find this tool useful, consider buying me a coffee ☕

Buy Me A Coffee

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

git_safe_publish-1.0.0.tar.gz (342.7 kB view details)

Uploaded Source

Built Distribution

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

git_safe_publish-1.0.0-py3-none-any.whl (44.7 kB view details)

Uploaded Python 3

File details

Details for the file git_safe_publish-1.0.0.tar.gz.

File metadata

  • Download URL: git_safe_publish-1.0.0.tar.gz
  • Upload date:
  • Size: 342.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for git_safe_publish-1.0.0.tar.gz
Algorithm Hash digest
SHA256 0423013077cab5a1b4344e7613e3cc45b453dcb717a069443bcb5797b21396c1
MD5 60b80cf324d08a6a0d9437ed56244c9a
BLAKE2b-256 ad4cdd12169dd7c7d027182e3b7ecc04b51a3d74c741f3919d779304c8e8617d

See more details on using hashes here.

File details

Details for the file git_safe_publish-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for git_safe_publish-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 835da93c73ca79b2c4dbc8601b8fd71179fd83e25e72533dc945f3e669b6f2f9
MD5 eb49f02b359ace767b5818839635d551
BLAKE2b-256 61c855b9ee6d85689c5e25acfd3781cfe6aa2d77ea628747791d11c9628cccd2

See more details on using hashes here.

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