CLI tools for secret hygiene: your terminal security stack
You run a secrets scanner once, find nothing, and consider the problem handled. Two weeks later a key shows up in a commit, your shell history, or the session file of the AI agent you started using. The scanner did its job on the day you ran it — but hygiene is not a one-time scan. It is a pipeline, and on a terminal it has five jobs: detect, store, inject, scrub, and verify. Each layer catches what the ones before it miss, and a stack with a missing layer fails in a predictable way.
The five layers
Detect. Scanners find secrets where they should not be. gitleaks as a pre-commit hook and in CI refuses commits that contain keys; for files outside git, a high-entropy scan of the home directory flags long random strings, and you triage the hits by hand. This layer is about stopping new leaks.
Store. Every value you care about lives in one place. pass keeps each secret in its own GPG-encrypted file — plain files, scriptable, syncable with git — and the Bitwarden CLI serves the same role behind a server. The test: can you answer “where does the API key live?” with a single path?
Inject. The layer most setups skip. A wrapper resolves the secret from the store and sets it in the environment of a subprocess, so the value exists in memory for the duration of one command instead of in a file, a config, or shell history. Output is sanitized before anyone — including an agent — sees it.
Scrub. Prevention fails, so something must clean up after it. Shell history, logs, and agent session databases keep copies of values, and deleting rows is not enough: SQLite free pages and index structures retain the bytes. A scrub pass replaces known values and pattern matches, rebuilds indexes, and compacts the file so no physical remnant survives.
Verify. A doctor check that the store is healthy — GPG key valid, store
readable, gpg-agent running, no stray .env files — and that the integration
pieces are wired. With --json output, the check becomes part of your dotfiles
setup instead of a one-off.
Why a single tool is not enough
Each tool family covers one job and fails the others. Scanners do not move a found key into the store. Stores do not stop a key from leaking at commit time. Injection does not repair the history where the key already appears. The stack is the fix: five small tools wired in sequence beat one ambitious product, because the failure mode of each layer is visible and fixable.
The injection layer is the one people skip
The default habit — export KEY=..., or pasting a value into .env — creates
copies everywhere, and the copies are what leak. Running secrets-receiving
commands through an injector breaks the pattern: the secret never appears in
argv, so it never reaches history; it never lives in a config file, so the
agent cannot read it.
One implementation of the whole stack is trustless, a single static binary that reads an existing pass or Bitwarden store, injects secrets into subprocess environments, and sanitizes stdout and stderr — including base64 and URL-encoded variants. Its 321 tests and cosign-signed releases make the binary itself verifiable before you trust it with your store; the command reference is in the documentation.
A concrete order
On a fresh machine: verify first, move every value you find into the store, wire detection into pre-commit and CI, run secrets-receiving commands through the injector, and schedule a periodic scrub of history and session files. None of the steps is expensive, and each makes the next more effective — detection feeds the store, the store feeds injection, and scrubbing covers what all three miss.
Which layer of your stack is missing right now — detection, storage, injection, scrubbing, or verification?