Metadata-Version: 2.5
Name: credguard
Version: 0.1.0
Summary: Block accidental commits of tokens, passwords and other credentials.
Project-URL: Homepage, https://github.com/akashrana/credguard
Project-URL: Repository, https://github.com/akashrana/credguard
Project-URL: Issues, https://github.com/akashrana/credguard/issues
Author-email: Akash Rana <akashrana.india@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: credentials,git-hooks,pre-commit,sast,secrets,security
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.9
Requires-Dist: tomli>=2.0; python_version < '3.11'
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == 'dev'
Description-Content-Type: text/markdown

# credguard

Stop credentials from ever reaching your git history. `credguard` scans staged
content before a commit lands, blocks the commit when it finds a token,
password, key or connection string, and tells you what to do about it.

- **38 provider rules** — AWS, GitHub, GitLab, Slack, Stripe, OpenAI, Anthropic,
  Google, Azure, npm, PyPI, SendGrid, Twilio, Shopify, Discord, Telegram,
  Databricks, Hugging Face, private keys, DB URIs, auth headers, payment cards.
- **Checksum verification** where the provider supports it (GitHub CRC32,
  card issuer prefix + Luhn). A verified match is escalated to `CRITICAL`.
- **Entropy heuristic** for keys no pattern covers, tuned to stay quiet on
  hashes, UUIDs, lockfiles and charset constants.
- **Scans the index, not the working tree** — what you're actually committing.
- **Zero runtime dependencies** on Python 3.11+ (`tomli` only below that).
- **Secrets are never echoed.** Output, JSON, SARIF and the baseline file all
  carry masked values and fingerprints only.

## Install

```bash
pip install credguard          # from PyPI once published
pip install -e .              # from this source tree
```

## Quick start

```bash
credguard install-hook                # blocks commits (.git/hooks/pre-commit)
credguard install-hook --type pre-push # blocks pushes as well
credguard scan                        # scan the working tree
credguard scan --staged               # scan what is staged (what the hook runs)
credguard scan --range main..HEAD     # scan lines added in a range (CI)
credguard rules                       # list every rule and its severity
```

Exit codes: `0` clean, `1` blocking findings, `2` usage/config error.

### With [pre-commit](https://pre-commit.com)

```yaml
# .pre-commit-config.yaml
repos:
  - repo: https://github.com/your-org/credguard
    rev: v0.1.0
    hooks:
      - id: credguard
```

### In GitHub Actions

```yaml
- run: pip install credguard
- run: credguard scan --range "${{ github.event.pull_request.base.sha }}..HEAD" --format github
```

Use `--format sarif --output credguard.sarif` to feed GitHub code scanning.

## Adopting it on a repo that already has findings

Record what exists today so only *new* secrets fail the build:

```bash
credguard baseline            # writes .credguard-baseline.json
git add .credguard-baseline.json
```

The baseline stores `sha256(path + rule + secret)` fingerprints and masked
values — no plaintext. Fingerprints survive line moves and reformatting.
`credguard prune-baseline` lists entries that no longer match anything.

**A baselined secret is still a leaked secret.** Rotate it; the baseline only
stops the check from failing repeatedly while you work through the list.

## Suppressing a false positive

Narrowest option first:

```python
API_URL = "https://api.example.com/v3/aBcDeF0123456789"  # credguard:ignore
KEY = "Kq7zP2mXv9Ld4RbT"  # credguard:ignore[high_entropy_string]
# credguard:ignore-next-line
SAMPLE = "sk_live_51H8bQwKZvKQ1aBcDeFgHiJkL"
```

`# credguard:ignore-file` in the first 15 lines skips the whole file.
`# pragma: allowlist secret` and `# noqa: credguard` are accepted as aliases.

## Configuration

`.credguard.toml` in the repo root, or a `[tool.credguard]` table in
`pyproject.toml`. CLI flags win over the file.

```toml
[tool.credguard]
fail_on = "HIGH"                  # LOW | MEDIUM | HIGH | CRITICAL
exclude_rules = ["credit_card"]   # or only_rules = ["private_key", ...]
exclude_globs = ["docs/samples/*", "*.fixture.json"]
exclude_dirs = ["third_party"]
allow_values = [                  # regexes matched against the captured value
  "^AKIAIOSFODNN7EXAMPLE$",
  "^sk_test_",
]
entropy_enabled = true
base64_entropy_threshold = 4.5    # raise to 4.8 for less noise
hex_entropy_threshold = 3.0
max_file_size_kb = 1024
baseline_path = ".credguard-baseline.json"
```

`exclude_dirs` and `exclude_globs` extend the built-in defaults (`.git`,
`node_modules`, `dist`, lockfiles, binaries, minified assets) rather than
replacing them.

### Tuning notes

| Symptom | Fix |
| --- | --- |
| Noisy `high_entropy_string` findings | Raise `base64_entropy_threshold`, or set `entropy_enabled = false` — the provider rules keep working |
| Test fixtures flagged | Add them to `exclude_globs`, or use `sk_test_`-style values plus an `allow_values` entry |
| Docs and samples flagged | Values containing `example`, `changeme`, `your-…`, `${VAR}`, `os.environ[…]` are already ignored |
| Payment-card rule too eager | `exclude_rules = ["credit_card"]` |

By default `fail_on = "HIGH"`, so `MEDIUM` entropy findings are reported but do
not block. Against the Python 3.12 standard library (586 files) that yields
19 informational findings and **zero** blocking ones.

## Python API

```python
from credguard import Config, Scanner

scanner = Scanner(Config(entropy_enabled=False))
for finding in scanner.scan_text(open("settings.py").read(), "settings.py"):
    print(finding.severity, finding.rule_id, finding.line_no, finding.masked_secret())
```

## What this does not do

- It does not scan history you already pushed. Use
  `credguard scan --range <first-commit>..HEAD` to audit, and
  `git filter-repo` / BFG to rewrite — after rotating the credential.
- It is a pattern-and-heuristic scanner, not a proof. Treat a clean run as one
  layer, alongside secret managers, short-lived credentials and provider-side
  push protection.
- It never calls a vendor API to check whether a key is live, so nothing leaves
  your machine.

## Development

```bash
pip install -e ".[dev]"
pytest -q
credguard scan src        # credguard scans itself cleanly
```

MIT licensed.
