Maintained envchain fork for safer macOS Keychain secret release and local AI-agent security stacks.
_
| |
________ _| |_ _ __ __ _
|______\ \/ / __| '__/ _` |
> <| |_| | | (_| |
/_/\_\\__|_| \__,_|
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:
This fork exists to keep the secret-release layer strong while leaving launch verification and sandbox policy to the layers above and below it.
envchain command compatibility with the maintained envchain-xtra packageSecItem pathenvchain --setnvk/tap/envchain-xtrabondage and nono for local agent hardeningThis 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:
nvk/tap/envchain-xtraenvchain for drop-in compatibilityNotable fork changes:
SecItemenvchain --set hide input by defaultbondage + nono launch stackThis 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:
envchain stores and releases secretsenvchain approves the direct binary it executesbondage verifies the exact leaf target, interpreter, and package treenono remains the sandbox layerThat 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:
envchain is not trying to replace either of those with custom storage logiccontrib/shell-guards.zshcontrib/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:
envchain executestouchid-check helper before launchExample:
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-reapprove to refresh fingerprints after upgradesenvchain-status to inspect the allowlist and current fingerprintsIf 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.
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
--listList namespaces that have been created
$ envchain --list
aws
hubot
--noechoDo not echo user input. This is the default.
$ envchain --set --noecho foo BAR
foo.BAR (hidden):
foo.BAR saved: ...
--echoEcho 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
--require-passphraseAlways ask for keychain passphrase
$ envchain --set --require-passphrase name
--no-require-passphraseDo 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:
Fork maintenance and additional changes:
MIT License
See RELEASING.md.