@josephyoung/pi-heimdall
Guardian extension for pi — security guards that block accidental secret exposure, enforce command policies, protect .env files, and sandbox bash commands
Package details
Install @josephyoung/pi-heimdall from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@josephyoung/pi-heimdall- Package
@josephyoung/pi-heimdall- Version
0.2.20- Published
- Aug 14, 2026
- Downloads
- 406/mo · 54/wk
- Author
- yangkyo821
- License
- MIT
- Types
- extension
- Size
- 60.4 KB
- Dependencies
- 1 dependency · 1 peer
Pi manifest JSON
{
"extensions": [
"./extensions"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@josephyoung/pi-heimdall
Security controls for @earendil-works/pi-coding-agent.
Heimdall puts policy checks around shell and file tools before their input or
output reaches the model.
Fork notice
This repository is a maintained fork of
casualjim/pi-heimdall. It retains
the original project's security goal and MIT attribution, while this fork is
published as @josephyoung/pi-heimdall and has evolved into a single-entry
package with sandbox, policy, and protected-configuration controls.
Install
# All projects
pi install @josephyoung/pi-heimdall
# Current project only
pi install -l @josephyoung/pi-heimdall
# One-off run
pi -e @josephyoung/pi-heimdall
GitHub fallback:
pi install git:github.com/josephyoung/pi-heimdall
Security controls
One extension entry point registers six independent guards:
| Guard | Scope |
|---|---|
sandbox-guard |
Applies filesystem, environment, and network policy to bash and file tools; protects Heimdall config |
secret-guard |
Blocks secret-variable references and redacts known secret values from bash output |
env-protect |
Blocks direct read calls for real dotenv files while allowing examples and templates |
kubectl-secret-guard |
Denies Kubernetes commands that expose secrets, pod environments, or protected finalizers |
sops-secret-guard |
Denies SOPS operations that decrypt or reveal content |
command-policy-guard |
Enforces repository-specific blocked command prefixes |
sandbox-guard is always registered. The other guards can be disabled without
sharing runtime state or weakening each other.
Configuration
Heimdall reads and deep-merges these files at session start:
~/.pi/agent/heimdall.json<cwd>/.pi/heimdall.json
Project values win for scalars and objects; arrays are concatenated.
{
"disabled": ["sops-secret-guard"],
"sandbox": {
"enabled": true,
"network": "host",
"bindRoot": ".",
"paths": {
".": { "mode": "write" },
"~/shared": {},
"~/.ssh": { "mode": "deny" }
},
"env": {
"allow": null,
"deny": ["*_TOKEN", "*_SECRET", "*_PASSWORD", "*_KEY"],
"set": { "NO_COLOR": "1" }
}
},
"commandPolicies": []
}
Valid disabled values are secret-guard, command-policy-guard,
env-protect, kubectl-secret-guard, and sops-secret-guard.
Sandbox rules
The bash sandbox requires Linux and bubblewrap. Paths default to read-only;
use mode: "write" for writable paths and mode: "deny" for exclusions. The
most specific matching path wins. ~, $VAR, and ${VAR} are expanded.
bindRoot promotes one allowed writable tree to the actual bubblewrap bind
mount. Use "." when one process hosts multiple isolated sessions: it resolves
to that session's current workspace without exposing sibling workspaces. An
explicit absolute path is also supported; / and relative escape paths are
rejected. This setting takes precedence over HEIMDALL_BWRAP_BIND_ROOT.
Common system paths and $HOME are read-only by default, while the project,
/tmp, and ~/.pi are writable. Heimdall config files remain protected as
described below. Credential stores, cloud configs, editor configs, and AI tool
configs under the home directory are denied by default. Add explicit rules for
any additional private paths in your environment.
Environment handling is ordered as follows:
allow: nullinherits the process environment;allow: []starts empty.denyremoves exact names or*glob matches.setoverrides values;nullremoves a variable.
network accepts "host" (default) or "none". The /sandbox TUI command
shows active policy. pi --no-sandbox disables isolation for the session, but
bash remains blocked as described below.
Container deployments may set:
HEIMDALL_BWRAP_BIND_KERNEL_FS=1to bind host/devand/proc.HEIMDALL_BWRAP_BIND_PROC=0to omit/procwhen an outer container would expose same-UID process roots through it.HEIMDALL_BWRAP_BIND_ROOT=/absolute/pathto promote an allowed workspace root to the actual writable bind mount.HEIMDALL_PROTECT_CONFIG_OVERLAY=0to disable the synthetic config overlay when rootless container mounts reject it.
Protected Configuration
Both Heimdall config files are operator-owned Protected Configuration:
- Direct file-tool reads and writes are blocked, including symlink aliases.
- Broad
grep,find, andlsresults omit the files and their contents. - Sandboxed bash receives synthetic empty files at those paths.
This boundary fails closed. If Linux/bubblewrap isolation is unavailable or the sandbox is disabled, Heimdall blocks bash instead of exposing its policy file. Edit the config outside Pi.
Command policies
Policies match tokenized command prefixes in every shell segment:
{
"commandPolicies": [
{
"name": "no-cargo-test",
"blocked": ["cargo", "test"],
"message": "Use `mise test` or `mise run test` instead of `cargo test`."
}
]
}
Matching handles environment prefixes, common wrappers, shell groups, shell
-c, path-qualified executables, quoting, escapes, and heredocs. It is a policy
guard, not a complete shell interpreter; indirect execution through containers,
SSH, or embedded languages is outside its scope.
Secret values
Create <cwd>/.env.json with the names to protect. JSON values are ignored;
actual values are captured from the Pi process environment.
{
"GITHUB_TOKEN": "",
"OPENAI_API_KEY": ""
}
Commands that name those variables are blocked. Matching output is redacted in
plain, base64, ROT13, reversed, hex, and hexdump-derived forms. Generic
SECRET, KEY, TOKEN, PASSWORD, PASS, APIKEY, CREDENTIAL, and
PRIVATE assignments are masked even without .env.json.
Package compatibility
Heimdall replaces Pi's built-in bash tool. Another package cannot register a
second replacement with the same name. For oh-pi, disable only
pi-package/extensions/bg-process.ts in pi config; its other extensions,
skills, prompts, and themes can remain enabled.
Development
There is no build step; Pi loads the TypeScript sources directly.
npm install
npm run typecheck
npm test
npm run check:pack
CI runs install, typecheck, and package-content checks. Guard changes should also include a blocked case and a nearby allowed case in the local test suite.
License
MIT. Original work © casualjim; fork maintenance by Joseph Young.