Metadata-Version: 2.4
Name: oneport-secrets
Version: 1.0.1
Summary: AI pre-ship secret & .env gate — deterministic detection, LLM triage, git-history aware
Author-email: Oneport <eng@oneport.dev>
License: MIT License
        
        Copyright (c) 2026 Oneport
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://oneport.dev
Project-URL: Repository, https://github.com/oneport/oneport-secrets
Project-URL: Issues, https://github.com/oneport/oneport-secrets/issues
Project-URL: Changelog, https://github.com/oneport/oneport-secrets/blob/main/CHANGELOG.md
Keywords: secrets,secret-scanning,gitguardian,trufflehog,entropy,pre-commit,security,dotenv,ai,gemini
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: click>=8.1.0
Requires-Dist: oneport-account>=0.1.0
Requires-Dist: httpx>=0.27.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: pyyaml>=6.0.0
Requires-Dist: rich>=13.0.0
Requires-Dist: gitpython>=3.1.0
Requires-Dist: platformdirs>=4.0.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
Requires-Dist: respx>=0.21.0; extra == "dev"
Requires-Dist: ruff>=0.4.0; extra == "dev"
Requires-Dist: mypy>=1.10.0; extra == "dev"
Requires-Dist: types-pyyaml; extra == "dev"
Dynamic: license-file

# Oneport Secrets

**An AI pre-ship secret & `.env` gate that beats trufflehog's noise.**

Deterministic detection finds every candidate secret across your working tree
**and your full git history** (leaked keys live forever in old commits). Then a
free LLM does one thing — **triage**: it separates the real leaks from the test
fixtures, docs examples, and placeholders that make other scanners cry wolf.

```
detection = deterministic (regex catalog + Shannon entropy)
judgment  = LLM (Gemini)  — REAL vs FALSE-POSITIVE, with a reason
```

The model is **never** the detector. It cannot invent or miss a secret; it can
only annotate what the deterministic core already found. Anything it doesn't
explicitly clear stays blocking (fail-safe).

- 🔎 **Git-history aware** — scans every commit via GitPython, not just HEAD.
- 🧠 **Triage that cuts noise** — the wedge over trufflehog/GitGuardian.
- 🛠 **Provider-specific remediation** — the exact revoke → rotate → purge steps.
- 🌱 **Env-drift** — code env reads vs `.env.example`, secret-vs-toggle labelled.
- 🔒 **Serverless & private** — your key, your machine. No SaaS, no upload. Secrets
  are always redacted in output; the raw value never leaves your box.

---

## Install

```bash
pip install oneport-secrets
```

Set a **free** Gemini key (used only for triage — detection works without it):

```bash
export GEMINI_API_KEY=AIza...   # https://aistudio.google.com/apikey
```

## Quick start

```bash
# Scan the working tree
oneport-secrets scan .

# Scan the FULL git history (catches keys deleted from HEAD but alive in commits)
oneport-secrets scan . --history

# Pre-commit gate: only staged changes
oneport-secrets scan --staged

# Find env drift: vars used in code but missing from .env.example
oneport-secrets env-check .

# JSON for CI
oneport-secrets scan . --history --format json
```

`scan` exits **1** if any REAL (or untriaged) secret is found — drop it straight
into CI. `env-check` exits 1 on used-but-undeclared variables.

## What a finding looks like

```
* CRITICAL REAL  AWS Access Key ID
    location : deploy.py:1@997d52db
    value    : AKIA...LEAK
    commit   : 997d52db by alice (2026-06-14)
    triage   : Live-looking AWS key in deployment config, not a placeholder.
    remediation:
      - Deactivate then delete the key in IAM -> Users -> Security credentials ...
      - Create a replacement key and update your secret store (never commit it).
      - Check CloudTrail for use of the leaked key by an unexpected principal.
      - Purge it from git history (git filter-repo --invert-paths, or the BFG), ...

Suppressed 1 triaged false-positive(s):
  - AWS Access Key ID tests/test_auth.py:1 : AWS docs example key in a test fixture.
```

## Detectors

Provider regexes for AWS (AKIA/ASIA…), Google `AIza`, GCP service accounts,
Stripe `sk_live`, GitHub `ghp_`/fine-grained, GitLab, Slack tokens & webhooks,
Twilio, SendGrid, Mailgun, OpenAI, Anthropic, npm, PyPI, JWTs, PEM private keys,
and database connection URIs with embedded passwords — plus **Shannon-entropy**
scoring to catch high-entropy strings no signature knows about.

## Env-drift

```bash
oneport-secrets env-check .
```

Parses `os.getenv` / `os.environ`, `process.env`, `import.meta.env`,
`Deno.env.get` and diffs the result against `.env.example` (or
`.env.sample`/`.template`/`.dist`):

- **used-but-undeclared** → the "stale `.env.example`, new hire can't boot" bug
- **declared-but-unused** → dead config / a renamed variable

The LLM labels each drifting var **secret** vs **toggle**, so a forgotten
*secret* shouts louder than a forgotten feature flag.

## Custom rules — `.oneport/guidelines.md`

Version-controlled, shared by the whole team, no dashboard:

```markdown
- regex: MYCORP_[A-Z0-9]{32}    # detect our internal token format
- ignore: tests/fixtures/        # never scan these paths
```

Add entries from the CLI:

```bash
oneport-secrets learn "regex: MYCORP_[A-Z0-9]{32}"
oneport-secrets learn "ignore: vendor/"
```

## CI / PR comments

`--post` upserts a single sticky report comment on the PR (found by a hidden
marker, edited in place) and adds inline review comments on the offending lines.
See [`examples/workflows/`](examples/workflows/) for a ready-to-use GitHub
Actions workflow and a pre-commit hook.

## Privacy

100% serverless. Detection runs entirely locally. The only network call is the
triage request to Gemini **with your own key**, and it sends redacted values and
file paths — never the raw secret in full. Nothing is stored or uploaded by us.

## License

MIT
