Securing pi, Your AI Coding Agent, with Greywall: A Practical Guide
AI coding agents like pi have become essential daily companions. But by default, pi runs in YOLO mode: full filesystem access, unrestricted command execution, no permissions. It’s a deliberate design choice by its creator, but this freedom comes with real risks. Today, let’s explore Greywall, a tool that sandboxes pi using a deny-by-default approach at the kernel level.
Why Sandbox an AI Coding Agent?
pi in YOLO mode is convenient but risky. Without restrictions, the agent can:
- Read your secrets: SSH keys (
~/.ssh/id_rsa),.envfiles, AWS or GCP credentials, - Exfiltrate data: send files to a remote server via
curl, - Modify your system: alter
~/.bashrc,~/.gitconfig, git hooks, - Execute destructive commands:
rm -rf /,git push --force,npm publish, - Be manipulated via prompt injection: malicious content in a file can influence its behavior.
Greywall provides defense-in-depth: even in YOLO mode, the agent is contained within a kernel-level sandbox that limits what it can actually do.
Overview of Greywall
Greywall is a container-free sandbox operating at the kernel level, built on the deny-by-default principle: everything is denied by default, and you only open what the agent needs.
Features by Platform
| Layer | Linux | macOS |
|---|---|---|
| Sandbox engine | Bubblewrap (namespaces) | sandbox-exec (Seatbelt) |
| Filesystem deny-by-default | ✅ Landlock + bubblewrap | ✅ Seatbelt |
| Syscall filtering | ✅ Seccomp BPF (27+ syscalls blocked) | ✅ Seatbelt |
| Violation monitoring | ✅ eBPF | ✅ Seatbelt denial logs |
| Transparent network proxy | ✅ tun2socks + TUN | ❌ (env vars only) |
| Network isolation | ✅ Network namespace | N/A |
| Credential protection | ✅ (HTTP substitution + .env) | ✅ (HTTP substitution, .env blocked) |
Architecture at a Glance
The architecture relies on four pillars:
- Filesystem: read and write controlled via allowlists/denylists,
- Network: routed through a SOCKS5 proxy (greyproxy) with domain filtering,
- Commands: dangerous commands blocked, even in pipelines and subshells,
- Credentials: transparent API key substitution via greyproxy.
Installation and First Steps
Linux (Arch, Ubuntu, Fedora)
# Install Greywall
curl -fsSL https://raw.githubusercontent.com/GreyhavenHQ/greywall/main/install.sh | sh
# Linux dependencies
# Arch
sudo pacman -S bubblewrap socat xdg-dbus-proxy libsecret
# Ubuntu/Debian
sudo apt install bubblewrap socat xdg-dbus-proxy libsecret-tools
# Fedora
sudo dnf install bubblewrap socat xdg-dbus-proxy libsecret
macOS
brew tap greyhavenhq/tap
brew install greywall
Greyproxy is automatically installed as a dependency.
Verification and Setup
# Verify installation
greywall check
# Install and start greyproxy (SOCKS5 proxy + dashboard)
greywall setup
# Check kernel features (Linux)
greywall --linux-features
Without greyproxy, all network access is blocked by default — by design.
Running pi in the Sandbox
# Basic sandbox: only CWD accessible, network blocked
greywall -- pi
Note: at this time, pi does not yet have a built-in agent profile in Greywall. Native profiles exist for Claude Code, Codex, Gemini CLI, Cursor, OpenCode, etc. — but not yet for pi. Don’t worry, we can work around this!
Security Profile for pi
Since pi doesn’t have a dedicated profile yet, two approaches are available.
Approach 1: Learning Mode (Recommended to Get Started)
Learning mode traces pi’s filesystem access and automatically generates a least-privilege profile:
# Launch in learning mode
greywall --learning -- pi
# Work normally for a few minutes...
# Exit pi — the profile is generated automatically
# View the generated profile
greywall profiles show pi
# Launch pi with the learned profile (loaded automatically)
greywall -- pi
This is the fastest way to get a tailored profile without guessing the agent’s exact needs.
Approach 2: Custom Config Extending the Code Template
Greywall’s code template is designed for AI coding agents. You can extend it with pi-specific settings:
{
"extends": "code",
"filesystem": {
"denyRead": [
"~/.ssh/id_*",
"~/.gnupg/**",
".env",
".env.*"
],
"denyWrite": [
"~/.bashrc",
"~/.zshrc",
"~/.ssh/**",
".git/hooks/**"
]
},
"command": {
"deny": [
"git push --force",
"npm publish"
]
},
"credentials": {
"inject": [
"ANTHROPIC_API_KEY",
"OPENAI_API_KEY"
]
}
}
Place this file in ~/.config/greywall/greywall.json (Linux) or ~/Library/Application Support/greywall/greywall.json (macOS).
# Launch pi with this profile
greywall -- pi
The code template already provides baseline protections: dangerous system command blocking, sensitive file protection, network routing via proxy.
Combining with Toolchains
If your project uses multiple languages, you can combine built-in toolchain profiles:
# pi + Node.js + Go
greywall --profile node,go -- pi
# pi + Python
greywall --profile python -- pi
# pi + Rust
greywall --profile rust -- pi
These toolchain profiles allow necessary access to caches, runtimes, and dependencies for each ecosystem.
What You Must Protect
| Path | Risk |
|---|---|
~/.ssh/id_* | Private SSH keys |
~/.gnupg/** | GPG keys |
.env, .env.* | Application secrets |
~/.aws/credentials | AWS credentials |
~/.config/gcloud/ | GCP credentials |
*.pem, *.key | TLS certificates and keys |
~/.bashrc, ~/.zshrc | Persistence via shell config |
.git/hooks/** | Persistence via git hooks |
Greywall includes automatic dangerous file protection: .git/hooks/*, ~/.bashrc, ~/.zshrc, ~/.ssh/ are write-blocked even without explicit configuration.
Credential Protection
This is one of Greywall’s most powerful features. The principle is elegant (requires greyproxy v0.3.4+):
- Detection: Greywall scans environment variables for known names (
ANTHROPIC_API_KEY,AWS_SECRET_ACCESS_KEY, etc.) and common suffixes (_API_KEY,_TOKEN,_SECRET,_PASSWORD). - Replacement: Each credential is replaced with an opaque placeholder (
greyproxy:credential:v1:gw-<id>:<digest>). - HTTP Substitution: When pi makes an HTTP request containing a placeholder, greyproxy substitutes the real value before forwarding.
- Cleanup: When the sandbox exits, the session is deleted from greyproxy.
Result: pi never sees the real API keys. Only greyproxy handles them.
In Practice
# Automatic protection
greywall -- pi
# Injection from greyproxy (keys don't exist in the environment)
greywall --inject ANTHROPIC_API_KEY --inject OPENAI_API_KEY -- pi
# Add a custom variable as a secret
greywall --secret MY_CUSTOM_KEY -- pi
# Ignore a false positive
greywall --ignore-secret PI_OFFLINE -- pi
You can also store credentials directly in the greyproxy dashboard (http://localhost:43080/settings#credentials), without them ever existing in your environment.
On Linux, Greywall mounts rewritten versions of .env files with placeholders. On macOS, .env files are entirely blocked from reading — use --inject instead.
Network and Filesystem Control
Network: SOCKS5 Proxy and Allowlist
All network requests go through greyproxy, which filters by domain. The default policy is Deny:
# No network mode (greyproxy not running)
greywall -- pi
# With controlled network (configure domains in the dashboard)
greywall -- pi
Typical domains to allow for a coding agent:
| Domain | Provider |
|---|---|
api.anthropic.com | Anthropic (Claude) |
api.openai.com | OpenAI (GPT) |
generativelanguage.googleapis.com | Google (Gemini) |
openrouter.ai | OpenRouter |
api.github.com | GitHub |
registry.npmjs.org | npm |
Exposing Ports
# Allow pi to start a dev server
greywall -p 3000 -p 5173 -- pi
# Forward a host port (e.g., PostgreSQL, Redis) — Linux only
greywall -f 5432 -f 6379 -- pi
Monitoring, Auditing, and Learning Mode
Real-Time Violations
# Monitoring mode — display violations only
greywall -m -- pi
Example output:
[VIOLATION] read denied: /home/user/.ssh/id_rsa (Landlock)
[VIOLATION] write denied: /home/user/.bashrc (protected file)
[VIOLATION] command denied: git push --force origin main (command policy)
[VIOLATION] network denied: evil.com:443 (greyproxy)
Every violation is logged and visible in real time. If pi tries to read ~/.ssh/id_rsa, write to ~/.bashrc, or connect to an unknown domain → blocked and logged.
Greyproxy Dashboard
The dashboard at http://localhost:43080 lets you visualize:
- Activity: all network connections in real time,
- Pending: requests awaiting a decision,
- Rules: active allow/deny rules,
- Credentials: stored credentials and active sessions.
Debug Mode
# Full verbose output
greywall -d -- pi
# Monitoring + debug
greywall -m -d -- pi
Known Limitations and Security Model
Greywall is defense-in-depth, not an absolute guarantee. It’s important to understand its limitations:
- Determined hostile code: a motivated attacker could escape via kernel vulnerabilities,
- Exfiltration to allowed destinations: Greywall filters destinations, not content,
- HTTP request bodies: credential substitution does not apply to request bodies,
- Non-HTTP protocols: raw TCP, WebSockets after upgrade — no inspection,
- Resource limits: CPU, memory, fork bombs — out of scope.
Linux vs macOS Differences
| Feature | Linux | macOS |
|---|---|---|
| Transparent proxy (TUN) | ✅ tun2socks | ❌ (env vars) |
| .env rewriting | ✅ (bind-mount) | ❌ (blocked) |
| Network isolation | ✅ (namespace) | N/A (host network) |
In summary: ✅ Greywall protects against accidents and basic prompt injection, ⚠️ it does not protect against a determined adversary.
Deployment Checklist
Installation
- Install Greywall (
curl -fsSL ... | shorbrew install greywall) - Install Linux dependencies (
bubblewrap,socat) - Run
greywall setupto install greyproxy - Verify with
greywall check
Configuration
- Run
greywall --learning -- pito discover pi’s actual needs - Refine the profile or create a custom config extending the
codetemplate - Add allowed LLM domains in the greyproxy dashboard
- Configure credential protection (
--injector dashboard)
Validation
- Run
greywall -m -- piand check violations - Test that reading
~/.ssh/id_*is blocked - Test that writing to
~/.bashrcis blocked - Test that
git push --forceis blocked
Daily Use
- Use
greywall -- piinstead of barepi - Check the greyproxy dashboard regularly
- Audit violations with
-mfrom time to time
Conclusion
Greywall transforms an all-powerful coding agent into a controlled tool. By adopting a deny-by-default approach at the kernel level, it lets you harness pi’s power without exposing your secrets, your system, or your network. Transparent credential protection, network filtering, and learning mode make it an ideal companion for any security-conscious developer.
This guide covers only the essentials — to go further, check out the official documentation and the Greywall GitHub.
Questions about implementation, security profiles, or other use cases to explore? Don’t hesitate to ask in the comments!