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
pip install oneport-secrets
Set a free Gemini key (used only for triage — detection works without it):
export GEMINI_API_KEY=AIza... # https://aistudio.google.com/apikey
Quick start
# 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
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:
- regex: MYCORP_[A-Z0-9]{32} # detect our internal token format
- ignore: tests/fixtures/ # never scan these paths
Add entries from the CLI:
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/ 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
Metadata
Release files for oneport-secrets 1.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| oneport_secrets-1.0.1.tar.gz | 54.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| oneport_secrets-1.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 101.7 kB
Release files / oneport_secrets-1.0.1.tar.gz
| Download URL | oneport_secrets-1.0.1.tar.gz |
|---|---|
| Size | 54.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f2c7c3b1325e4b7d11b9361fdb5c50c4b104add2bfcbbe51c07306dc2e718c0c
|
|
BLAKE2b-256 checksum How to use checksums |
5283d536eeb52c2c571e58bc32e8d5d939c22acb83a3c916c035b67c34bdaa9d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.0
|
Release files / oneport_secrets-1.0.1-py3-none-any.whl
| Download URL | oneport_secrets-1.0.1-py3-none-any.whl |
|---|---|
| Size | 47.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6a8bba003204bc3217b8b83514ff90d1b9cc447ddf53a7b3c52377ad58676341
|
|
BLAKE2b-256 checksum How to use checksums |
e1742f96864179fa89f6e2812ba91398e0bfe4776af503258c8652d0502e3a27
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.0
|