Tainted CLI
The local developer loop. One surface, three ways to run analyze (static, fast, no
target or credentials needed):
- on demand —
tainted analyze <repo> - on save —
tainted watch <repo>(re-runs analyze on every file change) - on commit — the pre-commit hook (
tainted-gate), which blocks the commit on a high-severity possible hole
It also runs the interactive fix and can prove against a running target.
Install
pip install tainted-cli # the engine comes with it, pinned to this version
export GEMINI_API_KEY=... # optional: turns on the LLM "meaning" register
prove additionally needs the browser the engine's dynamic extra carries. A package cannot
request an extra of its own dependency, so that is a second command rather than a flag:
pip install "tainted[dynamic]" && playwright install chromium
From a checkout instead — the core is a sibling directory, not a release:
pip install -e . # the core engine (repo root)
pip install -e surfaces/cli # this surface
Use
tainted analyze ./my-app # ranked possible holes in the terminal
tainted analyze ./my-app --only bola,rls --json # narrow the checks + machine-readable output
tainted watch ./my-app # re-analyze on every save
tainted fix ./my-app --finding-id 1db5cbc5 --apply # write the fix to disk
tainted prove ./my-app \ # drive a running target
--url http://localhost:54321 --anon-key "$ANON" \
--login-a a@x.com:pw --login-b b@x.com:pw --seed invoices:<id>
tainted tutorial walks through all of this from inside the terminal: run it with no
argument to list the lessons, or tainted tutorial proving-it to read one.
tainted tutorial # first-scan, reading-a-report, on-save, on-commit, proving-it, fixing-it
tainted tutorial first-scan # one lesson, with the commands to run and what to expect back
prove is gated by an ownership check: a localhost target needs nothing; a remote
target needs --ownership-token (checked via a DNS TXT record or a
/.well-known/tainted-verify file).
Which hole is fix fixing?
analyze prints a # and an ID for every row, and fix takes either:
tainted fix ./my-app --finding-id 1db5cbc5350811b5 # the hole itself; survives a re-run
tainted fix ./my-app --index 0 # the row number from that one run
Prefer the id. # is a position in the report that run drew, and both the code and the model's
ranking move underneath it.
Pre-commit
The hook manifest is .pre-commit-hooks.yaml at the repository root — pre-commit reads it
from there and nowhere else — and it is a language: system hook, so it runs the tainted-gate
you installed above rather than building an environment of its own. (It cannot build one: a
language: python hook installs this repo's root package, which is the engine, and the engine
has no tainted-gate script and none of this surface's dependencies.)
So: install Tainted, then add this to the project's .pre-commit-config.yaml:
- repo: https://github.com/OWNER/tainted
rev: v0.1.0
hooks:
- id: tainted
Or skip the clone entirely and run the command already on your PATH:
- repo: local
hooks:
- id: tainted
name: Tainted security gate
entry: tainted-gate
language: system
pass_filenames: false
always_run: true
tainted analyze exits 0 or 1. prove exits 1 when a high-severity finding is
proven, and 2 when the ownership check fails — both usable directly in scripts.
Release files for tainted-cli 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| tainted_cli-0.1.0.tar.gz | 25.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tainted_cli-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 44.8 kB
Release files / tainted_cli-0.1.0.tar.gz
| Download URL | tainted_cli-0.1.0.tar.gz |
|---|---|
| Size | 25.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9ce755bb9773bb73960ee4b988955a0908b8934d4093a58675b1752d7e0fce54
|
|
BLAKE2b-256 checksum How to use checksums |
fa277e2453d192f09d8d692f8182f908bd761e801d29e5e1e8037f9027029e8a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.9
|
Release files / tainted_cli-0.1.0-py3-none-any.whl
| Download URL | tainted_cli-0.1.0-py3-none-any.whl |
|---|---|
| Size | 19.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ff837cd8d31b7b1b6fbe4aed398f21d3a3f296e195d1cfc3fdae1f31554acaf2
|
|
BLAKE2b-256 checksum How to use checksums |
10536ce624954d6e9b6408846b95c6b3ff1d6a8fba6b2a9d33342c0a3ccf0a4d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.9
|