_
| |
________ _| |_ _ __ __ _
|______\ \/ / __| '__/ _` |
> <| |_| | | (_| |
/_/\_\\__|_| \__,_|
Maintained envchain fork for safer macOS Keychain secret release and local
AI-agent security stacks.
envchain-xtra installs the familiar envchain executable: secrets stay in the
OS vault, and are released only to the command you explicitly launch. This fork
keeps the original interface useful while tightening the defaults that matter
when coding agents, wrappers, and sandbox layers are part of the workflow.
brew tap nvk/tap
brew install nvk/tap/envchain-xtra
envchain --set aws AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY
envchain aws env | grep AWS_The original sorah/envchain made the
important design choice: do not put secrets in shell startup files. Store them in
the OS secret store and release them only when needed.
This fork is no longer just an experiment. As of 2026-05-01, the original
upstream master branch was last updated on 2024-04-24. This fork now carries
the active macOS maintenance, Homebrew distribution, security defaults, and
agent-stack integration used by this environment.
The premise is direct:
- you cannot let coding agents run loose with live keys
- you cannot assume a familiar command implies a trustworthy dependency tree
- you should not grant broad ambient environment access by default
This fork exists to keep the secret-release layer strong while leaving launch verification and sandbox policy to the layers above and below it.
envchaincommand compatibility with the maintainedenvchain-xtrapackage- macOS Keychain storage through the modernized
SecItempath - hidden input by default when running
envchain --set - redacted save confirmations instead of plaintext terminal leaks
- direct binary approval and fingerprint inspection commands
- Homebrew distribution through
nvk/tap/envchain-xtra - documented fit with
bondageandnonofor local agent hardening
This fork preserves upstream compatibility where that does not weaken the security model. It will intentionally diverge when safer defaults or modern macOS behavior require it.
Current fork responsibilities:
- maintain the Homebrew formula as
nvk/tap/envchain-xtra - keep the installed binary name as
envchainfor drop-in compatibility - ship macOS Keychain fixes as the primary supported path
- keep Linux Secret Service support on a best-effort basis
- default toward non-leaky terminal behavior
- document how this fits into a multi-agent local security stack
Notable fork changes:
- modernized the macOS backend away from deprecated Keychain APIs toward
SecItem - added binary approval and fingerprint inspection commands
- made
envchain --sethide input by default - redacts saved-value confirmation output instead of printing secrets in plaintext
- documents the preferred
bondage+nonolaunch stack
This fork still tracks the original project as upstream, but does not wait on
upstream for releases that affect local security posture.
Upstream patches are welcome when they fit the fork's goals. If upstream becomes
active again, this repository remains the maintained downstream distribution for
the envchain-xtra security stack rather than a temporary branch.
Secrets for common computing environments, such as AWS_SECRET_ACCESS_KEY, are
commonly provided through environment variables.
A common practice is to place them in shell initialization files such as .bashrc and .zshrc.
Putting these secrets on disk in this way is a grave risk.
envchain stores credential values in a secure vault and exports them to environment
variables only when you invoke it explicitly.
Currently, envchain supports macOS Keychain and D-Bus Secret Service
(gnome-keyring) as storage backends.
Don't give any credentials implicitly!
The intended security model in this fork is not just "store secrets in Keychain and
run envchain."
The preferred stack is:
shell name -> bondage -> [envchain] -> [nono] -> exact pinned tool
In that model:
envchainstores and releases secretsenvchainapproves the direct binary it executesbondageverifies the exact leaf target, interpreter, and package treenonoremains the sandbox layer
That split is cleaner because secret release, launch verification, and sandbox policy stay in separate layers instead of being mixed into shell glue.
It also deliberately leans on the OS where the OS is stronger than userland glue:
- Keychain remains the real secret store on macOS
- OS-level signing identity can be used as part of binary approval and drift detection
envchainis not trying to replace either of those with custom storage logic
contrib/shell-guards.zsh is still provided for
wrapper-based workflows that have not moved to bondage yet.
It remains useful as a transitional or lightweight compatibility layer because it can:
- fingerprint the direct binary
envchainexecutes - fingerprint the final leaf binary a trusted wrapper launches
- optionally require an external
touchid-checkhelper before launch
Example:
source /path/to/contrib/shell-guards.zsh
my_tool() {
_verify_binary my_tool || return 1
envchain my-namespace nono run -- command my_tool "$@"
}The helper file also provides:
envchain-approve <binary>to store a fingerprint for a resolved binary pathenvchain-reapproveto refresh fingerprints after upgradesenvchain-statusto inspect the allowlist and current fingerprints
If you also want a human-approval gate, _require_touchid can be used with an
external touchid-check helper when ENVCHAIN_TOUCHID=1.
For new setups, bondage should be the preferred launcher path. The shell guard
script is best treated as compatibility glue for setups that still need shell-based
wrappers.
The touch-id branch is kept separate from master while biometric prompting
and secret-storage behavior are evaluated:
The stable path is still envchain for secret release, bondage for launch
verification, and nono for sandboxing.
- macOS
- Current Homebrew releases are built and used on modern Apple Silicon macOS.
- Older macOS compatibility is inherited from upstream and best-effort only.
- readline
- libsecret
- D-Bus Secret Service
- GNOME keyring
- KeePassXC
Linux support is inherited from upstream. It should not be treated as the primary tested path for this fork unless a maintainer is actively exercising it.
brew tap nvk/tap
brew install nvk/tap/envchain-xtra
This installs the envchain executable from this fork.
Choose this fork when you want the maintained macOS path, safer terminal defaults, Homebrew packaging, and integration with the local AI-agent security stack. Choose upstream only if you specifically need the original behavior and are prepared to own any missing maintenance locally.
If you also want the launcher/policy layer described above:
brew install nvk/tap/agent-bondage
It intentionally conflicts with the upstream Homebrew envchain formula because
both install the same binary name.
If upstream envchain is already installed:
brew uninstall envchain
brew install nvk/tap/envchain-xtra
If envchain-xtra is already installed but not linked yet:
brew link --overwrite envchain-xtra
This path is mainly for development work on the fork itself:
$ make
$ sudo make install
(or)
$ cp ./envchain ~/bin/
Environment variables are set within a specified namespace. You can set variables in a single command:
envchain --set NAMESPACE ENV [ENV ..]
You will be prompted to enter the values for each variable.
Input is hidden by default. After saving, envchain prints a redacted preview:
the first four characters, or the prefix up to an early dash, followed by
... and the last three characters. Short values are shown only as ....
For example, we can set two variables, AWS_ACCESS_KEY_ID and
AWS_SECRET_ACCESS_KEY, within a namespace called aws:
$ envchain --set aws AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY
aws.AWS_ACCESS_KEY_ID (hidden):
aws.AWS_ACCESS_KEY_ID saved: my-a...key
aws.AWS_SECRET_ACCESS_KEY (hidden):
aws.AWS_SECRET_ACCESS_KEY saved: ...
Here we define a single new variable within a different namespace:
$ envchain --set hubot HUBOT_HIPCHAT_PASSWORD
hubot.HUBOT_HIPCHAT_PASSWORD (hidden):
hubot.HUBOT_HIPCHAT_PASSWORD saved: ...
These will all appear as application passwords with envchain-NAMESPACE in the data store (Keychain in macOS, gnome-keyring in common Linux distros).
$ env | grep AWS_ || echo "No AWS_ env vars"
No AWS_ env vars
$ envchain aws env | grep AWS_
AWS_ACCESS_KEY_ID=my-access-key
AWS_SECRET_ACCESS_KEY=secret
$ envchain aws s3cmd blah blah blah
⋮
$ envchain hubot env | grep AWS_ || echo "No AWS_ env vars for hubot"
No AWS_ env vars for hubot
$ envchain hubot env | grep HUBOT_
HUBOT_HIPCHAT_PASSWORD: xxxx
You may specify multiple namespaces at once by separating them with commas:
$ envchain aws,hubot env | grep 'AWS_\|HUBOT_'
AWS_ACCESS_KEY_ID=my-access-key
AWS_SECRET_ACCESS_KEY=secret
HUBOT_HIPCHAT_PASSWORD: xxxx
List namespaces that have been created
$ envchain --list
aws
hubot
Do not echo user input. This is the default.
$ envchain --set --noecho foo BAR
foo.BAR (hidden):
foo.BAR saved: ...
Echo user input while typing. Use this only when you explicitly want plaintext visible in terminal scrollback or logs.
$ envchain --set --echo foo BAR
foo.BAR: visible-while-typing
foo.BAR saved: visi...ing
Always ask for keychain passphrase
$ envchain --set --require-passphrase name
Do not ask for keychain passphrase
$ envchain --set --no-require-passphrase name
envchain-xtra is based on envchain by Shota Fukumori and contributors.
The original project made the important design choice: keep secrets out of shell
startup files and release them only for explicit commands.
Original authors:
- Sorah Fukumori her@sorah.jp
- eagletmt
Fork maintenance and additional changes:
- NVK, 2026-present
MIT License
See RELEASING.md.