rename Fence to Greywall as GreyHaven sandboxing component
Rebrand the project from Fence to Greywall, the sandboxing layer of the GreyHaven platform. This updates: - Go module path to gitea.app.monadical.io/monadical/greywall - Binary name, CLI help text, and all usage examples - Config paths (~/.config/greywall/greywall.json), env vars (GREYWALL_*) - Log prefixes ([greywall:*]), temp file prefixes (greywall-*) - All documentation, scripts, CI workflows, and example files - README rewritten with GreyHaven branding and Fence attribution Directory/file renames: cmd/fence → cmd/greywall, pkg/fence → pkg/greywall, docs/why-fence.md → docs/why-greywall.md, example JSON files, and banner.
This commit is contained in:
@@ -1,26 +1,26 @@
|
||||
# Fence Documentation
|
||||
# Greywall Documentation
|
||||
|
||||
Fence is a sandboxing tool that restricts network and filesystem access for arbitrary commands. It's most useful for running semi-trusted code (package installs, build scripts, CI jobs, unfamiliar repos) with controlled side effects.
|
||||
Greywall is a sandboxing tool that restricts network and filesystem access for arbitrary commands. It's most useful for running semi-trusted code (package installs, build scripts, CI jobs, unfamiliar repos) with controlled side effects.
|
||||
|
||||
## Getting Started
|
||||
|
||||
- [Quickstart](quickstart.md) - Install fence and run your first sandboxed command in 5 minutes
|
||||
- [Why Fence](why-fence.md) - What problem it solves (and what it doesn't)
|
||||
- [Quickstart](quickstart.md) - Install greywall and run your first sandboxed command in 5 minutes
|
||||
- [Why Greywall](why-greywall.md) - What problem it solves (and what it doesn't)
|
||||
|
||||
## Guides
|
||||
|
||||
- [Concepts](concepts.md) - Mental model: OS sandbox + local proxies + config
|
||||
- [Troubleshooting](troubleshooting.md) - Common failure modes and fixes
|
||||
- [Using Fence with AI agents](agents.md) - Defense-in-depth and policy standardization
|
||||
- [Using Greywall with AI agents](agents.md) - Defense-in-depth and policy standardization
|
||||
- [Recipes](recipes/README.md) - Common workflows (npm/pip/git/CI)
|
||||
- [Templates](./templates.md) - Copy/paste templates you can start from
|
||||
|
||||
## Reference
|
||||
|
||||
- [README](../README.md) - CLI usage
|
||||
- [Library Usage (Go)](library.md) - Using Fence as a Go package
|
||||
- [Configuration](./configuration.md) - How to configure Fence
|
||||
- [Architecture](../ARCHITECTURE.md) - How fence works under the hood
|
||||
- [Library Usage (Go)](library.md) - Using Greywall as a Go package
|
||||
- [Configuration](./configuration.md) - How to configure Greywall
|
||||
- [Architecture](../ARCHITECTURE.md) - How greywall works under the hood
|
||||
- [Security model](security-model.md) - Threat model, guarantees, and limitations
|
||||
- [Linux security features](linux-security-features.md) - Landlock, seccomp, eBPF details and fallback behavior
|
||||
- [Testing](testing.md) - How to run tests and write new ones
|
||||
@@ -36,20 +36,20 @@ See [`examples/`](../examples/README.md) for runnable demos.
|
||||
|
||||
```bash
|
||||
# Block all network (default)
|
||||
fence <command>
|
||||
greywall <command>
|
||||
|
||||
# Use custom config
|
||||
fence --settings ./fence.json <command>
|
||||
greywall --settings ./greywall.json <command>
|
||||
|
||||
# Debug mode (verbose output)
|
||||
fence -d <command>
|
||||
greywall -d <command>
|
||||
|
||||
# Monitor mode (show blocked requests)
|
||||
fence -m <command>
|
||||
greywall -m <command>
|
||||
|
||||
# Expose port for servers
|
||||
fence -p 3000 <command>
|
||||
greywall -p 3000 <command>
|
||||
|
||||
# Run shell command
|
||||
fence -c "echo hello && ls"
|
||||
greywall -c "echo hello && ls"
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Using Fence with AI Agents
|
||||
# Using Greywall with AI Agents
|
||||
|
||||
Many popular coding agents already include sandboxing. Fence can still be useful when you want a tool-agnostic policy layer that works the same way across:
|
||||
Many popular coding agents already include sandboxing. Greywall can still be useful when you want a tool-agnostic policy layer that works the same way across:
|
||||
|
||||
- local developer machines
|
||||
- CI jobs
|
||||
@@ -15,7 +15,7 @@ Treat an agent as "semi-trusted automation":
|
||||
- Allowlist only the network destinations you actually need
|
||||
- Use `-m` (monitor mode) to audit blocked attempts and tighten policy
|
||||
|
||||
Fence can also reduce the risk of running agents with fewer interactive permission prompts (e.g. "skip permissions"), as long as your Fence config tightly scopes writes and outbound destinations. It's defense-in-depth, not a substitute for the agent's own safeguards.
|
||||
Greywall can also reduce the risk of running agents with fewer interactive permission prompts (e.g. "skip permissions"), as long as your Greywall config tightly scopes writes and outbound destinations. It's defense-in-depth, not a substitute for the agent's own safeguards.
|
||||
|
||||
## Example: API-only agent
|
||||
|
||||
@@ -33,7 +33,7 @@ Fence can also reduce the risk of running agents with fewer interactive permissi
|
||||
Run:
|
||||
|
||||
```bash
|
||||
fence --settings ./fence.json <agent-command>
|
||||
greywall --settings ./greywall.json <agent-command>
|
||||
```
|
||||
|
||||
## Popular CLI coding agents
|
||||
@@ -43,7 +43,7 @@ We provide these template for guardrailing CLI coding agents:
|
||||
- [`code`](/internal/templates/code.json) - Strict deny-by-default network filtering via proxy. Works with agents that respect `HTTP_PROXY`. Blocks cloud metadata APIs, protects secrets, restricts dangerous commands.
|
||||
- [`code-relaxed`](/internal/templates/code-relaxed.json) - Allows direct network connections for agents that ignore `HTTP_PROXY`. Same filesystem/command protections as `code`, but `deniedDomains` only enforced for proxy-respecting apps.
|
||||
|
||||
You can use it like `fence -t code -- claude`.
|
||||
You can use it like `greywall -t code -- claude`.
|
||||
|
||||
| Agent | Works with template | Notes |
|
||||
|-------|--------| ----- |
|
||||
@@ -60,7 +60,7 @@ Note: On Linux, if OpenCode or Gemini CLI is installed via Linuxbrew, Landlock c
|
||||
|
||||
## Protecting your environment
|
||||
|
||||
Fence includes additional "dangerous file protection" (writes blocked regardless of config) to reduce persistence and environment-tampering vectors like:
|
||||
Greywall includes additional "dangerous file protection" (writes blocked regardless of config) to reduce persistence and environment-tampering vectors like:
|
||||
|
||||
- `.git/hooks/*`
|
||||
- shell startup files (`.zshrc`, `.bashrc`, etc.)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Benchmarking
|
||||
|
||||
This document describes how to run, interpret, and compare sandbox performance benchmarks for Fence.
|
||||
This document describes how to run, interpret, and compare sandbox performance benchmarks for Greywall.
|
||||
|
||||
## Quick Start
|
||||
|
||||
@@ -29,9 +29,9 @@ go test -run=^$ -bench=. -benchmem ./internal/sandbox/...
|
||||
|
||||
### Layer 1: CLI Benchmarks (`scripts/benchmark.sh`)
|
||||
|
||||
**What it measures**: Real-world agent cost - full `fence` invocation including proxy startup, socat bridges (Linux), and sandbox-exec/bwrap setup.
|
||||
**What it measures**: Real-world agent cost - full `greywall` invocation including proxy startup, socat bridges (Linux), and sandbox-exec/bwrap setup.
|
||||
|
||||
This is the most realistic benchmark for understanding the cost of running agent commands through Fence.
|
||||
This is the most realistic benchmark for understanding the cost of running agent commands through Greywall.
|
||||
|
||||
```bash
|
||||
# Full benchmark suite
|
||||
@@ -51,7 +51,7 @@ This is the most realistic benchmark for understanding the cost of running agent
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `-b, --binary PATH` | Path to fence binary (default: ./fence) |
|
||||
| `-b, --binary PATH` | Path to greywall binary (default: ./greywall) |
|
||||
| `-o, --output DIR` | Output directory (default: ./benchmarks) |
|
||||
| `-n, --runs N` | Minimum runs per benchmark (default: 30) |
|
||||
| `-q, --quick` | Quick mode: fewer runs, skip slow benchmarks |
|
||||
@@ -92,13 +92,13 @@ benchstat bench.txt
|
||||
|
||||
```bash
|
||||
# Quick syscall cost breakdown
|
||||
strace -f -c ./fence -- true
|
||||
strace -f -c ./greywall -- true
|
||||
|
||||
# Context switches, page faults
|
||||
perf stat -- ./fence -- true
|
||||
perf stat -- ./greywall -- true
|
||||
|
||||
# Full profiling (flamegraph-ready)
|
||||
perf record -F 99 -g -- ./fence -- git status
|
||||
perf record -F 99 -g -- ./greywall -- git status
|
||||
perf report
|
||||
```
|
||||
|
||||
@@ -106,10 +106,10 @@ perf report
|
||||
|
||||
```bash
|
||||
# Time Profiler via Instruments
|
||||
xcrun xctrace record --template 'Time Profiler' --launch -- ./fence -- true
|
||||
xcrun xctrace record --template 'Time Profiler' --launch -- ./greywall -- true
|
||||
|
||||
# Quick call-stack snapshot
|
||||
./fence -- sleep 5 &
|
||||
./greywall -- sleep 5 &
|
||||
sample $! 5 -file sample.txt
|
||||
```
|
||||
|
||||
@@ -150,7 +150,7 @@ The overhead factor decreases as the actual workload increases (because sandbox
|
||||
|
||||
1. Run benchmarks on each platform independently
|
||||
2. Compare overhead factors, not absolute times
|
||||
3. Use the same fence version and workloads
|
||||
3. Use the same greywall version and workloads
|
||||
|
||||
```bash
|
||||
# On macOS
|
||||
@@ -256,7 +256,7 @@ Linux initialization is ~3,700x slower because it must:
|
||||
|
||||
macOS only generates a Seatbelt profile string (very cheap).
|
||||
|
||||
### Cold Start Overhead (one `fence` invocation per command)
|
||||
### Cold Start Overhead (one `greywall` invocation per command)
|
||||
|
||||
| Workload | Linux | macOS |
|
||||
|----------|-------|-------|
|
||||
@@ -264,7 +264,7 @@ macOS only generates a Seatbelt profile string (very cheap).
|
||||
| Python | 124 ms | 33 ms |
|
||||
| Git status | 114 ms | 25 ms |
|
||||
|
||||
This is the realistic cost for scripts running `fence -c "command"` repeatedly.
|
||||
This is the realistic cost for scripts running `greywall -c "command"` repeatedly.
|
||||
|
||||
### Warm Path Overhead (pre-initialized manager)
|
||||
|
||||
@@ -289,9 +289,9 @@ Overhead decreases as the actual workload increases (sandbox setup is fixed cost
|
||||
|
||||
## Impact on Agent Usage
|
||||
|
||||
### Long-Running Agents (`fence claude`, `fence codex`)
|
||||
### Long-Running Agents (`greywall claude`, `greywall codex`)
|
||||
|
||||
For agents that run as a child process under fence:
|
||||
For agents that run as a child process under greywall:
|
||||
|
||||
| Phase | Cost |
|
||||
|-------|------|
|
||||
@@ -306,11 +306,11 @@ Child processes inherit the sandbox - no re-initialization, no WrapCommand overh
|
||||
| `git status` | 2.1 ms | 5.9 ms |
|
||||
| Python script | 11 ms | 15 ms |
|
||||
|
||||
**Bottom line**: For `fence <agent>` usage, sandbox overhead is a one-time startup cost. Tool calls inside the agent run at native speed.
|
||||
**Bottom line**: For `greywall <agent>` usage, sandbox overhead is a one-time startup cost. Tool calls inside the agent run at native speed.
|
||||
|
||||
### Per-Command Invocation (`fence -c "command"`)
|
||||
### Per-Command Invocation (`greywall -c "command"`)
|
||||
|
||||
For scripts or CI running fence per command:
|
||||
For scripts or CI running greywall per command:
|
||||
|
||||
| Session | Linux Cost | macOS Cost |
|
||||
|---------|------------|------------|
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
# Concepts
|
||||
|
||||
Fence combines two ideas:
|
||||
Greywall combines two ideas:
|
||||
|
||||
1. **An OS sandbox** to enforce "no direct network" and restrict filesystem operations.
|
||||
2. **Local filtering proxies** (HTTP + SOCKS5) to selectively allow outbound traffic by domain.
|
||||
|
||||
## Network model
|
||||
|
||||
By default, fence blocks all outbound network access.
|
||||
By default, greywall blocks all outbound network access.
|
||||
|
||||
When you allow domains, fence:
|
||||
When you allow domains, greywall:
|
||||
|
||||
- Starts local HTTP and SOCKS5 proxies
|
||||
- Sets proxy environment variables (`HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`)
|
||||
@@ -29,13 +29,13 @@ These are separate on purpose. A typical safe default for dev servers is:
|
||||
|
||||
## Filesystem model
|
||||
|
||||
Fence is designed around "read mostly, write narrowly":
|
||||
Greywall is designed around "read mostly, write narrowly":
|
||||
|
||||
- **Reads**: allowed by default (you can block specific paths via `denyRead`).
|
||||
- **Writes**: denied by default (you must opt-in with `allowWrite`).
|
||||
- **denyWrite**: overrides `allowWrite` (useful for protecting secrets and dangerous files).
|
||||
|
||||
Fence also protects some dangerous targets regardless of config (e.g. shell startup files and git hooks). See `ARCHITECTURE.md` for the full list.
|
||||
Greywall also protects some dangerous targets regardless of config (e.g. shell startup files and git hooks). See `ARCHITECTURE.md` for the full list.
|
||||
|
||||
## Debug vs Monitor mode
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Configuration
|
||||
|
||||
Fence reads settings from `~/.config/fence/fence.json` by default (or `~/Library/Application Support/fence/fence.json` on macOS). Legacy `~/.fence.json` is also supported. Pass `--settings ./fence.json` to use a custom path. Config files support JSONC.
|
||||
Greywall reads settings from `~/.config/greywall/greywall.json` by default (or `~/Library/Application Support/greywall/greywall.json` on macOS). Legacy `~/.greywall.json` is also supported. Pass `--settings ./greywall.json` to use a custom path. Config files support JSONC.
|
||||
|
||||
Example config:
|
||||
|
||||
@@ -60,7 +60,7 @@ You can also extend other config files using absolute or relative paths:
|
||||
|
||||
```json
|
||||
{
|
||||
"extends": "/etc/fence/company-base.json",
|
||||
"extends": "/etc/greywall/company-base.json",
|
||||
"filesystem": {
|
||||
"denyRead": ["~/company-secrets/**"]
|
||||
}
|
||||
@@ -143,7 +143,7 @@ Example:
|
||||
|
||||
### Default Denied Commands
|
||||
|
||||
When `useDefaults` is `true` (the default), fence blocks these dangerous commands:
|
||||
When `useDefaults` is `true` (the default), greywall blocks these dangerous commands:
|
||||
|
||||
- System control: `shutdown`, `reboot`, `halt`, `poweroff`, `init 0/6`
|
||||
- Kernel manipulation: `insmod`, `rmmod`, `modprobe`, `kexec`
|
||||
@@ -155,7 +155,7 @@ To disable defaults: `"useDefaults": false`
|
||||
|
||||
### Command Detection
|
||||
|
||||
Fence detects blocked commands in:
|
||||
Greywall detects blocked commands in:
|
||||
|
||||
- Direct commands: `git push origin main`
|
||||
- Command chains: `ls && git push` or `ls; git push`
|
||||
@@ -260,26 +260,26 @@ SSH host patterns support wildcards anywhere:
|
||||
|
||||
## Importing from Claude Code
|
||||
|
||||
If you've been using Claude Code and have already built up permission rules, you can import them into fence:
|
||||
If you've been using Claude Code and have already built up permission rules, you can import them into greywall:
|
||||
|
||||
```bash
|
||||
# Preview import (prints JSON to stdout)
|
||||
fence import --claude
|
||||
greywall import --claude
|
||||
|
||||
# Save to the default config path
|
||||
fence import --claude --save
|
||||
greywall import --claude --save
|
||||
|
||||
# Import from a specific file
|
||||
fence import --claude -f ~/.claude/settings.json --save
|
||||
greywall import --claude -f ~/.claude/settings.json --save
|
||||
|
||||
# Save to a specific output file
|
||||
fence import --claude -o ./fence.json
|
||||
greywall import --claude -o ./greywall.json
|
||||
|
||||
# Import without extending any template (minimal config)
|
||||
fence import --claude --no-extend --save
|
||||
greywall import --claude --no-extend --save
|
||||
|
||||
# Import and extend a different template
|
||||
fence import --claude --extend local-dev-server --save
|
||||
greywall import --claude --extend local-dev-server --save
|
||||
```
|
||||
|
||||
### Default Template
|
||||
@@ -294,7 +294,7 @@ Use `--no-extend` if you want a minimal config without these defaults, or `--ext
|
||||
|
||||
### Permission Mapping
|
||||
|
||||
| Claude Code | Fence |
|
||||
| Claude Code | Greywall |
|
||||
|-------------|-------|
|
||||
| `Bash(xyz)` allow | `command.allow: ["xyz"]` |
|
||||
| `Bash(xyz:*)` deny | `command.deny: ["xyz"]` |
|
||||
@@ -302,9 +302,9 @@ Use `--no-extend` if you want a minimal config without these defaults, or `--ext
|
||||
| `Write(path)` allow | `filesystem.allowWrite: [path]` |
|
||||
| `Write(path)` deny | `filesystem.denyWrite: [path]` |
|
||||
| `Edit(path)` | Same as `Write(path)` |
|
||||
| `ask` rules | Converted to deny (fence doesn't support interactive prompts) |
|
||||
| `ask` rules | Converted to deny (greywall doesn't support interactive prompts) |
|
||||
|
||||
Global tool permissions (e.g., bare `Read`, `Write`, `Grep`) are skipped since fence uses path/command-based rules.
|
||||
Global tool permissions (e.g., bare `Read`, `Write`, `Grep`) are skipped since greywall uses path/command-based rules.
|
||||
|
||||
## See Also
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Library Usage (Go)
|
||||
|
||||
Fence can be used as a Go library to sandbox commands programmatically.
|
||||
Greywall can be used as a Go library to sandbox commands programmatically.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
go get github.com/Use-Tusk/fence
|
||||
go get gitea.app.monadical.io/monadical/greywall
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
@@ -17,25 +17,25 @@ import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
|
||||
"github.com/Use-Tusk/fence/pkg/fence"
|
||||
"gitea.app.monadical.io/monadical/greywall/pkg/greywall"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Check platform support
|
||||
if !fence.IsSupported() {
|
||||
if !greywall.IsSupported() {
|
||||
fmt.Println("Sandboxing not supported on this platform")
|
||||
return
|
||||
}
|
||||
|
||||
// Create config
|
||||
cfg := &fence.Config{
|
||||
Network: fence.NetworkConfig{
|
||||
cfg := &greywall.Config{
|
||||
Network: greywall.NetworkConfig{
|
||||
AllowedDomains: []string{"api.example.com"},
|
||||
},
|
||||
}
|
||||
|
||||
// Create and initialize manager
|
||||
manager := fence.NewManager(cfg, false, false)
|
||||
manager := greywall.NewManager(cfg, false, false)
|
||||
defer manager.Cleanup()
|
||||
|
||||
if err := manager.Initialize(); err != nil {
|
||||
@@ -64,7 +64,7 @@ func main() {
|
||||
Returns `true` if the current platform supports sandboxing (macOS or Linux).
|
||||
|
||||
```go
|
||||
if !fence.IsSupported() {
|
||||
if !greywall.IsSupported() {
|
||||
log.Fatal("Platform not supported")
|
||||
}
|
||||
```
|
||||
@@ -74,7 +74,7 @@ if !fence.IsSupported() {
|
||||
Returns a default configuration with all network blocked.
|
||||
|
||||
```go
|
||||
cfg := fence.DefaultConfig()
|
||||
cfg := greywall.DefaultConfig()
|
||||
cfg.Network.AllowedDomains = []string{"example.com"}
|
||||
```
|
||||
|
||||
@@ -83,18 +83,18 @@ cfg.Network.AllowedDomains = []string{"example.com"}
|
||||
Loads configuration from a JSON file. Supports JSONC (comments allowed).
|
||||
|
||||
```go
|
||||
cfg, err := fence.LoadConfig(fence.DefaultConfigPath())
|
||||
cfg, err := greywall.LoadConfig(greywall.DefaultConfigPath())
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if cfg == nil {
|
||||
cfg = fence.DefaultConfig() // File doesn't exist
|
||||
cfg = greywall.DefaultConfig() // File doesn't exist
|
||||
}
|
||||
```
|
||||
|
||||
#### `DefaultConfigPath() string`
|
||||
|
||||
Returns the default config file path (`~/.config/fence/fence.json` on Linux, `~/Library/Application Support/fence/fence.json` on macOS, with fallback to legacy `~/.fence.json`).
|
||||
Returns the default config file path (`~/.config/greywall/greywall.json` on Linux, `~/Library/Application Support/greywall/greywall.json` on macOS, with fallback to legacy `~/.greywall.json`).
|
||||
|
||||
#### `NewManager(cfg *Config, debug, monitor bool) *Manager`
|
||||
|
||||
@@ -113,7 +113,7 @@ Creates a new sandbox manager.
|
||||
Sets up sandbox infrastructure (starts HTTP and SOCKS proxies). Called automatically by `WrapCommand` if not already initialized.
|
||||
|
||||
```go
|
||||
manager := fence.NewManager(cfg, false, false)
|
||||
manager := greywall.NewManager(cfg, false, false)
|
||||
defer manager.Cleanup()
|
||||
|
||||
if err := manager.Initialize(); err != nil {
|
||||
@@ -222,8 +222,8 @@ type SSHConfig struct {
|
||||
### Allow specific domains
|
||||
|
||||
```go
|
||||
cfg := &fence.Config{
|
||||
Network: fence.NetworkConfig{
|
||||
cfg := &greywall.Config{
|
||||
Network: greywall.NetworkConfig{
|
||||
AllowedDomains: []string{
|
||||
"registry.npmjs.org",
|
||||
"*.github.com",
|
||||
@@ -236,8 +236,8 @@ cfg := &fence.Config{
|
||||
### Restrict filesystem access
|
||||
|
||||
```go
|
||||
cfg := &fence.Config{
|
||||
Filesystem: fence.FilesystemConfig{
|
||||
cfg := &greywall.Config{
|
||||
Filesystem: greywall.FilesystemConfig{
|
||||
AllowWrite: []string{".", "/tmp"},
|
||||
DenyRead: []string{"~/.ssh", "~/.aws"},
|
||||
},
|
||||
@@ -247,8 +247,8 @@ cfg := &fence.Config{
|
||||
### Block dangerous commands
|
||||
|
||||
```go
|
||||
cfg := &fence.Config{
|
||||
Command: fence.CommandConfig{
|
||||
cfg := &greywall.Config{
|
||||
Command: greywall.CommandConfig{
|
||||
Deny: []string{
|
||||
"rm -rf /",
|
||||
"git push",
|
||||
@@ -261,7 +261,7 @@ cfg := &fence.Config{
|
||||
### Expose dev server port
|
||||
|
||||
```go
|
||||
manager := fence.NewManager(cfg, false, false)
|
||||
manager := greywall.NewManager(cfg, false, false)
|
||||
manager.SetExposedPorts([]int{3000})
|
||||
defer manager.Cleanup()
|
||||
|
||||
@@ -271,12 +271,12 @@ wrapped, _ := manager.WrapCommand("npm run dev")
|
||||
### Load and extend config
|
||||
|
||||
```go
|
||||
cfg, err := fence.LoadConfig(fence.DefaultConfigPath())
|
||||
cfg, err := greywall.LoadConfig(greywall.DefaultConfigPath())
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if cfg == nil {
|
||||
cfg = fence.DefaultConfig()
|
||||
cfg = greywall.DefaultConfig()
|
||||
}
|
||||
|
||||
// Add additional restrictions
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Linux Security Features
|
||||
|
||||
Fence uses multiple layers of security on Linux, with graceful fallback when features are unavailable.
|
||||
Greywall uses multiple layers of security on Linux, with graceful fallback when features are unavailable.
|
||||
|
||||
## Security Layers
|
||||
|
||||
@@ -13,13 +13,13 @@ Fence uses multiple layers of security on Linux, with graceful fallback when fea
|
||||
|
||||
## Feature Detection
|
||||
|
||||
Fence automatically detects available features and uses the best available combination.
|
||||
Greywall automatically detects available features and uses the best available combination.
|
||||
|
||||
To see what features are detected:
|
||||
|
||||
```bash
|
||||
# Check what features are available on your system
|
||||
fence --linux-features
|
||||
greywall --linux-features
|
||||
|
||||
# Example output:
|
||||
# Linux Sandbox Features:
|
||||
@@ -41,7 +41,7 @@ fence --linux-features
|
||||
|
||||
Landlock is applied via an **embedded wrapper** approach:
|
||||
|
||||
1. bwrap spawns `fence --landlock-apply -- <user-command>`
|
||||
1. bwrap spawns `greywall --landlock-apply -- <user-command>`
|
||||
2. The wrapper applies Landlock kernel restrictions
|
||||
3. The wrapper `exec()`s the user command
|
||||
|
||||
@@ -75,25 +75,25 @@ This provides **defense-in-depth**: both bwrap mounts AND Landlock kernel restri
|
||||
- **Impact**: `--unshare-net` is skipped; network is not fully isolated
|
||||
- **Cause**: Running in Docker, GitHub Actions, or other environments without `CAP_NET_ADMIN`
|
||||
- **Fallback**: Proxy-based filtering still works; filesystem/PID/seccomp isolation still active
|
||||
- **Check**: Run `fence --linux-features` and look for "Network namespace (--unshare-net): false"
|
||||
- **Check**: Run `greywall --linux-features` and look for "Network namespace (--unshare-net): false"
|
||||
- **Workaround**: Run with `sudo`, or in Docker use `--cap-add=NET_ADMIN`
|
||||
|
||||
> [!NOTE]
|
||||
> This is the most common "reduced isolation" scenario. Fence automatically detects this at startup and adapts. See the troubleshooting guide for more details.
|
||||
> This is the most common "reduced isolation" scenario. Greywall automatically detects this at startup and adapts. See the troubleshooting guide for more details.
|
||||
|
||||
### When bwrap is not available
|
||||
|
||||
- **Impact**: Cannot run fence on Linux
|
||||
- **Impact**: Cannot run greywall on Linux
|
||||
- **Solution**: Install bubblewrap: `apt install bubblewrap` or `dnf install bubblewrap`
|
||||
|
||||
### When socat is not available
|
||||
|
||||
- **Impact**: Cannot run fence on Linux
|
||||
- **Impact**: Cannot run greywall on Linux
|
||||
- **Solution**: Install socat: `apt install socat` or `dnf install socat`
|
||||
|
||||
## Blocked Syscalls (seccomp)
|
||||
|
||||
Fence blocks dangerous syscalls that could be used for sandbox escape or privilege escalation:
|
||||
Greywall blocks dangerous syscalls that could be used for sandbox escape or privilege escalation:
|
||||
|
||||
| Syscall | Reason |
|
||||
|---------|--------|
|
||||
@@ -111,13 +111,13 @@ Fence blocks dangerous syscalls that could be used for sandbox escape or privile
|
||||
|
||||
## Violation Monitoring
|
||||
|
||||
On Linux, violation monitoring (`fence -m`) shows:
|
||||
On Linux, violation monitoring (`greywall -m`) shows:
|
||||
|
||||
| Source | What it shows | Requirements |
|
||||
|--------|---------------|--------------|
|
||||
| `[fence:http]` | Blocked HTTP/HTTPS requests | None |
|
||||
| `[fence:socks]` | Blocked SOCKS connections | None |
|
||||
| `[fence:ebpf]` | Blocked filesystem access + syscalls | CAP_BPF or root |
|
||||
| `[greywall:http]` | Blocked HTTP/HTTPS requests | None |
|
||||
| `[greywall:socks]` | Blocked SOCKS connections | None |
|
||||
| `[greywall:ebpf]` | Blocked filesystem access + syscalls | CAP_BPF or root |
|
||||
|
||||
**Notes**:
|
||||
|
||||
@@ -127,7 +127,7 @@ On Linux, violation monitoring (`fence -m`) shows:
|
||||
|
||||
## Comparison with macOS
|
||||
|
||||
| Feature | macOS (Seatbelt) | Linux (fence) |
|
||||
| Feature | macOS (Seatbelt) | Linux (greywall) |
|
||||
|---------|------------------|---------------|
|
||||
| Filesystem control | Native | bwrap + Landlock |
|
||||
| Glob patterns | Native regex | Expanded at startup |
|
||||
@@ -181,12 +181,12 @@ sudo apk add bubblewrap socat
|
||||
For full violation visibility without root:
|
||||
|
||||
```bash
|
||||
# Grant CAP_BPF to the fence binary
|
||||
sudo setcap cap_bpf+ep /usr/local/bin/fence
|
||||
# Grant CAP_BPF to the greywall binary
|
||||
sudo setcap cap_bpf+ep /usr/local/bin/greywall
|
||||
```
|
||||
|
||||
Or run fence with sudo when monitoring is needed:
|
||||
Or run greywall with sudo when monitoring is needed:
|
||||
|
||||
```bash
|
||||
sudo fence -m <command>
|
||||
sudo greywall -m <command>
|
||||
```
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
### From Source (recommended for now)
|
||||
|
||||
```bash
|
||||
git clone https://github.com/Use-Tusk/fence
|
||||
cd fence
|
||||
go build -o fence ./cmd/fence
|
||||
sudo mv fence /usr/local/bin/
|
||||
git clone https://gitea.app.monadical.io/monadical/greywall
|
||||
cd greywall
|
||||
go build -o greywall ./cmd/greywall
|
||||
sudo mv greywall /usr/local/bin/
|
||||
```
|
||||
|
||||
### Using Go Install
|
||||
|
||||
```bash
|
||||
go install github.com/Use-Tusk/fence/cmd/fence@latest
|
||||
go install gitea.app.monadical.io/monadical/greywall/cmd/greywall@latest
|
||||
```
|
||||
|
||||
### Linux Dependencies
|
||||
@@ -32,30 +32,30 @@ sudo dnf install bubblewrap socat
|
||||
sudo pacman -S bubblewrap socat
|
||||
```
|
||||
|
||||
### Do I need sudo to run fence?
|
||||
### Do I need sudo to run greywall?
|
||||
|
||||
No, for most Linux systems. Fence works without root privileges because:
|
||||
No, for most Linux systems. Greywall works without root privileges because:
|
||||
|
||||
- Package-manager-installed `bubblewrap` is typically already setuid
|
||||
- Fence detects available capabilities and adapts automatically
|
||||
- Greywall detects available capabilities and adapts automatically
|
||||
|
||||
If some features aren't available (like network namespaces in Docker/CI), fence falls back gracefully - you'll still get filesystem isolation, command blocking, and proxy-based network filtering.
|
||||
If some features aren't available (like network namespaces in Docker/CI), greywall falls back gracefully - you'll still get filesystem isolation, command blocking, and proxy-based network filtering.
|
||||
|
||||
Run `fence --linux-features` to see what's available in your environment.
|
||||
Run `greywall --linux-features` to see what's available in your environment.
|
||||
|
||||
## Verify Installation
|
||||
|
||||
```bash
|
||||
fence --version
|
||||
greywall --version
|
||||
```
|
||||
|
||||
## Your First Sandboxed Command
|
||||
|
||||
By default, fence blocks all network access:
|
||||
By default, greywall blocks all network access:
|
||||
|
||||
```bash
|
||||
# This will fail - network is blocked
|
||||
fence curl https://example.com
|
||||
greywall curl https://example.com
|
||||
```
|
||||
|
||||
You should see something like:
|
||||
@@ -66,7 +66,7 @@ curl: (56) CONNECT tunnel failed, response 403
|
||||
|
||||
## Allow Specific Domains
|
||||
|
||||
Create a config file at `~/.config/fence/fence.json` (or `~/Library/Application Support/fence/fence.json` on macOS):
|
||||
Create a config file at `~/.config/greywall/greywall.json` (or `~/Library/Application Support/greywall/greywall.json` on macOS):
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -79,7 +79,7 @@ Create a config file at `~/.config/fence/fence.json` (or `~/Library/Application
|
||||
Now try again:
|
||||
|
||||
```bash
|
||||
fence curl https://example.com
|
||||
greywall curl https://example.com
|
||||
```
|
||||
|
||||
This time it succeeds!
|
||||
@@ -89,7 +89,7 @@ This time it succeeds!
|
||||
Use `-d` to see what's happening under the hood:
|
||||
|
||||
```bash
|
||||
fence -d curl https://example.com
|
||||
greywall -d curl https://example.com
|
||||
```
|
||||
|
||||
This shows:
|
||||
@@ -103,7 +103,7 @@ This shows:
|
||||
Use `-m` to see only violations and blocked requests:
|
||||
|
||||
```bash
|
||||
fence -m npm install
|
||||
greywall -m npm install
|
||||
```
|
||||
|
||||
This is useful for:
|
||||
@@ -117,7 +117,7 @@ This is useful for:
|
||||
Use `-c` to run compound commands:
|
||||
|
||||
```bash
|
||||
fence -c "echo hello && ls -la"
|
||||
greywall -c "echo hello && ls -la"
|
||||
```
|
||||
|
||||
## Expose Ports for Servers
|
||||
@@ -125,14 +125,14 @@ fence -c "echo hello && ls -la"
|
||||
If you're running a server that needs to accept connections:
|
||||
|
||||
```bash
|
||||
fence -p 3000 -c "npm run dev"
|
||||
greywall -p 3000 -c "npm run dev"
|
||||
```
|
||||
|
||||
This allows external connections to port 3000 while keeping outbound network restricted.
|
||||
|
||||
## Next steps
|
||||
|
||||
- Read **[Why Fence](why-fence.md)** to understand when fence is a good fit (and when it isn't).
|
||||
- Read **[Why Greywall](why-greywall.md)** to understand when greywall is a good fit (and when it isn't).
|
||||
- Learn the mental model in **[Concepts](concepts.md)**.
|
||||
- Use **[Troubleshooting](troubleshooting.md)** if something is blocked unexpectedly.
|
||||
- Start from copy/paste configs in **[`docs/templates/`](templates/README.md)**.
|
||||
|
||||
@@ -18,7 +18,7 @@ Goal: make CI steps safer by default: minimal egress and controlled writes.
|
||||
Run:
|
||||
|
||||
```bash
|
||||
fence --settings ./fence.json -c "make test"
|
||||
greywall --settings ./greywall.json -c "make test"
|
||||
```
|
||||
|
||||
## Add only what you need
|
||||
@@ -26,7 +26,7 @@ fence --settings ./fence.json -c "make test"
|
||||
Use monitor mode to discover what a job tries to reach:
|
||||
|
||||
```bash
|
||||
fence -m --settings ./fence.json -c "make test"
|
||||
greywall -m --settings ./greywall.json -c "make test"
|
||||
```
|
||||
|
||||
Then allowlist only:
|
||||
|
||||
@@ -18,7 +18,7 @@ Goal: allow fetching code from a limited set of hosts.
|
||||
Run:
|
||||
|
||||
```bash
|
||||
fence --settings ./fence.json git clone https://github.com/OWNER/REPO.git
|
||||
greywall --settings ./greywall.json git clone https://github.com/OWNER/REPO.git
|
||||
```
|
||||
|
||||
## SSH clone
|
||||
@@ -28,5 +28,5 @@ SSH traffic may go through SOCKS5 (`ALL_PROXY`) depending on your git/ssh config
|
||||
If it fails, use monitor/debug mode to see what was blocked:
|
||||
|
||||
```bash
|
||||
fence -m --settings ./fence.json git clone git@github.com:OWNER/REPO.git
|
||||
greywall -m --settings ./greywall.json git clone git@github.com:OWNER/REPO.git
|
||||
```
|
||||
|
||||
@@ -18,7 +18,7 @@ Goal: allow npm to fetch packages, but block unexpected egress.
|
||||
Run:
|
||||
|
||||
```bash
|
||||
fence --settings ./fence.json npm install
|
||||
greywall --settings ./greywall.json npm install
|
||||
```
|
||||
|
||||
## Iterate with monitor mode
|
||||
@@ -26,7 +26,7 @@ fence --settings ./fence.json npm install
|
||||
If installs fail, run:
|
||||
|
||||
```bash
|
||||
fence -m --settings ./fence.json npm install
|
||||
greywall -m --settings ./greywall.json npm install
|
||||
```
|
||||
|
||||
Then add the minimum extra domains required for your workflow (private registries, GitHub tarballs, etc.).
|
||||
|
||||
@@ -18,19 +18,19 @@ Goal: allow Python dependency fetching while keeping egress minimal.
|
||||
Run:
|
||||
|
||||
```bash
|
||||
fence --settings ./fence.json pip install -r requirements.txt
|
||||
greywall --settings ./greywall.json pip install -r requirements.txt
|
||||
```
|
||||
|
||||
For Poetry:
|
||||
|
||||
```bash
|
||||
fence --settings ./fence.json poetry install
|
||||
greywall --settings ./greywall.json poetry install
|
||||
```
|
||||
|
||||
## Iterate with monitor mode
|
||||
|
||||
```bash
|
||||
fence -m --settings ./fence.json poetry install
|
||||
greywall -m --settings ./greywall.json poetry install
|
||||
```
|
||||
|
||||
If you use private indexes, add those domains explicitly.
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
# Security Model
|
||||
|
||||
Fence is intended as defense-in-depth for running semi-trusted commands with reduced side effects (package installs, build scripts, CI jobs, unfamiliar repos).
|
||||
Greywall is intended as defense-in-depth for running semi-trusted commands with reduced side effects (package installs, build scripts, CI jobs, unfamiliar repos).
|
||||
|
||||
It is not designed to be a strong isolation boundary against actively malicious code that is attempting to escape.
|
||||
|
||||
## Threat model (what Fence helps with)
|
||||
## Threat model (what Greywall helps with)
|
||||
|
||||
Fence is useful when you want to reduce risk from:
|
||||
Greywall is useful when you want to reduce risk from:
|
||||
|
||||
- Supply-chain scripts that unexpectedly call out to the network
|
||||
- Tools that write broadly across your filesystem
|
||||
- Accidental leakage of secrets via "phone home" behavior
|
||||
- Unfamiliar repos that run surprising commands during install/build/test
|
||||
|
||||
## What Fence enforces
|
||||
## What Greywall enforces
|
||||
|
||||
### Network
|
||||
|
||||
@@ -25,7 +25,7 @@ Important: domain filtering does not inspect content. If you allow a domain, cod
|
||||
|
||||
#### How allowlisting works
|
||||
|
||||
Fence combines OS-level enforcement with proxy-based allowlisting:
|
||||
Greywall combines OS-level enforcement with proxy-based allowlisting:
|
||||
|
||||
- The OS sandbox / network namespace is expected to block direct outbound connections.
|
||||
- Domain allowlisting happens via local HTTP/SOCKS proxies and proxy environment variables (`HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`).
|
||||
@@ -41,11 +41,11 @@ Localhost is separate from "external domains":
|
||||
- **Writes are denied by default**; you must opt in with `allowWrite`.
|
||||
- **denyWrite** can block specific files/patterns even if the parent directory is writable.
|
||||
- **denyRead** can block reads from sensitive paths.
|
||||
- Fence includes an internal list of always-protected targets (e.g. shell configs, git hooks) to reduce common persistence vectors.
|
||||
- Greywall includes an internal list of always-protected targets (e.g. shell configs, git hooks) to reduce common persistence vectors.
|
||||
|
||||
### Environment sanitization
|
||||
|
||||
Fence strips dangerous environment variables before passing them to sandboxed commands:
|
||||
Greywall strips dangerous environment variables before passing them to sandboxed commands:
|
||||
|
||||
- `LD_*` (Linux): `LD_PRELOAD`, `LD_LIBRARY_PATH`, etc.
|
||||
- `DYLD_*` (macOS): `DYLD_INSERT_LIBRARIES`, `DYLD_LIBRARY_PATH`, etc.
|
||||
@@ -57,11 +57,11 @@ This prevents a library injection attack where a sandboxed process writes a mali
|
||||
- `-m/--monitor` helps you discover what a command *tries* to access (blocked only).
|
||||
- `-d/--debug` shows more detail to understand why something was blocked.
|
||||
|
||||
## Limitations (what Fence does NOT try to solve)
|
||||
## Limitations (what Greywall does NOT try to solve)
|
||||
|
||||
- **Hostile code containment**: assume determined attackers may escape via kernel/OS vulnerabilities.
|
||||
- **Resource limits**: CPU, memory, disk, fork bombs, etc. are out of scope.
|
||||
- **Content-based controls**: Fence does not block data exfiltration to *allowed* destinations.
|
||||
- **Content-based controls**: Greywall does not block data exfiltration to *allowed* destinations.
|
||||
- **Proxy limitations / protocol edge cases**: some programs may not respect proxy environment variables, so they won't get domain allowlisting unless you configure them to use a proxy (e.g. Node.js `http`/`https` without a proxy-aware client).
|
||||
|
||||
### Practical examples of proxy limitations
|
||||
@@ -71,14 +71,14 @@ The proxy approach works well for many tools (curl, wget, git, npm, pip), but no
|
||||
- Node.js native `http`/`https` (use a proxy-aware client, e.g. `undici` + `ProxyAgent`)
|
||||
- Raw socket connections (custom TCP/UDP protocols)
|
||||
|
||||
Fence's OS-level sandbox is still expected to block direct outbound connections; bypassing the proxy should fail rather than silently succeeding.
|
||||
Greywall's OS-level sandbox is still expected to block direct outbound connections; bypassing the proxy should fail rather than silently succeeding.
|
||||
|
||||
### Domain-based filtering only
|
||||
|
||||
Fence does not inspect request content. If you allow a domain, a sandboxed process can still exfiltrate data to that domain.
|
||||
Greywall does not inspect request content. If you allow a domain, a sandboxed process can still exfiltrate data to that domain.
|
||||
|
||||
### Not a hostile-code containment boundary
|
||||
|
||||
Fence is defense-in-depth for running semi-trusted code, not a strong isolation boundary against malware designed to escape sandboxes.
|
||||
Greywall is defense-in-depth for running semi-trusted code, not a strong isolation boundary against malware designed to escape sandboxes.
|
||||
|
||||
For implementation details (how proxies/sandboxes/bridges work), see [`ARCHITECTURE.md`](../ARCHITECTURE.md).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Config Templates
|
||||
|
||||
Fence includes built-in config templates for common use cases. Templates are embedded in the binary, so you can use them directly without copying files.
|
||||
Greywall includes built-in config templates for common use cases. Templates are embedded in the binary, so you can use them directly without copying files.
|
||||
|
||||
## Using templates
|
||||
|
||||
@@ -8,13 +8,13 @@ Use the `-t` / `--template` flag to apply a template:
|
||||
|
||||
```bash
|
||||
# Use a built-in template
|
||||
fence -t npm-install npm install
|
||||
greywall -t npm-install npm install
|
||||
|
||||
# Wraps Claude Code
|
||||
fence -t code -- claude
|
||||
greywall -t code -- claude
|
||||
|
||||
# List available templates
|
||||
fence --list-templates
|
||||
greywall --list-templates
|
||||
```
|
||||
|
||||
You can also copy and customize templates from [`internal/templates/`](/internal/templates/).
|
||||
|
||||
@@ -67,9 +67,9 @@ go test -v -count=1 ./internal/sandbox/...
|
||||
|
||||
#### Sandboxed Build Environments (Nix, etc.)
|
||||
|
||||
If you're packaging fence for a distribution (e.g., Nix, Homebrew, Debian), note that some integration tests will be skipped when running `go test` during the build.
|
||||
If you're packaging greywall for a distribution (e.g., Nix, Homebrew, Debian), note that some integration tests will be skipped when running `go test` during the build.
|
||||
|
||||
Fence's Landlock integration on Linux uses a wrapper approach: the `fence` binary re-executes itself with `--landlock-apply` inside the sandbox. Test binaries (e.g., `sandbox.test`) don't have this handler, so Landlock-specific tests automatically skip when not running as the `fence` CLI.
|
||||
Greywall's Landlock integration on Linux uses a wrapper approach: the `greywall` binary re-executes itself with `--landlock-apply` inside the sandbox. Test binaries (e.g., `sandbox.test`) don't have this handler, so Landlock-specific tests automatically skip when not running as the `greywall` CLI.
|
||||
|
||||
Tests that skip include those calling `skipIfLandlockNotUsable()`:
|
||||
|
||||
@@ -77,25 +77,25 @@ Tests that skip include those calling `skipIfLandlockNotUsable()`:
|
||||
- `TestLinux_LandlockProtectsGitHooks`
|
||||
- `TestLinux_LandlockProtectsGitConfig`
|
||||
- `TestLinux_LandlockProtectsBashrc`
|
||||
- `TestLinux_LandlockAllowsTmpFence`
|
||||
- `TestLinux_LandlockAllowsTmpGreywall`
|
||||
- `TestLinux_PathTraversalBlocked`
|
||||
- `TestLinux_SeccompBlocksDangerousSyscalls`
|
||||
|
||||
| Test Type | What it tests | Landlock coverage |
|
||||
|-----------|---------------|-------------------|
|
||||
| `go test` (integration) | Go APIs, bwrap isolation, command blocking | Skipped (test binary can't use `--landlock-apply`) |
|
||||
| `smoke_test.sh` | Actual `fence` CLI end-to-end | ✅ Full coverage |
|
||||
| `smoke_test.sh` | Actual `greywall` CLI end-to-end | ✅ Full coverage |
|
||||
|
||||
For full test coverage including Landlock, run the smoke tests against the built binary (see "Smoke Tests" section below).
|
||||
|
||||
**Nested sandboxing limitations:**
|
||||
|
||||
- **macOS**: Nested Seatbelt sandboxing is not supported. If the build environment already uses `sandbox-exec` (like Nix's Darwin sandbox), fence's tests cannot create another sandbox. The kernel returns `forbidden-sandbox-reinit`. This is a macOS limitation.
|
||||
- **macOS**: Nested Seatbelt sandboxing is not supported. If the build environment already uses `sandbox-exec` (like Nix's Darwin sandbox), greywall's tests cannot create another sandbox. The kernel returns `forbidden-sandbox-reinit`. This is a macOS limitation.
|
||||
- **Linux**: Tests should work in most build sandboxes, but Landlock tests will skip as explained above. Runtime functionality is unaffected.
|
||||
|
||||
### Smoke Tests
|
||||
|
||||
Smoke tests verify the compiled `fence` binary works end-to-end. Unlike integration tests (which test internal Go APIs), smoke tests exercise the CLI interface.
|
||||
Smoke tests verify the compiled `greywall` binary works end-to-end. Unlike integration tests (which test internal Go APIs), smoke tests exercise the CLI interface.
|
||||
|
||||
**File:** [`scripts/smoke_test.sh`](/scripts/smoke_test.sh)
|
||||
|
||||
@@ -105,7 +105,7 @@ Smoke tests verify the compiled `fence` binary works end-to-end. Unlike integrat
|
||||
- Filesystem restrictions via settings file
|
||||
- Command blocking via settings file
|
||||
- Network blocking
|
||||
- Environment variable injection (FENCE_SANDBOX, HTTP_PROXY)
|
||||
- Environment variable injection (GREYWALL_SANDBOX, HTTP_PROXY)
|
||||
- Tool compatibility (python3, node, git, rg) - ensure that frequently used tools don't break in sandbox
|
||||
|
||||
**Run:**
|
||||
@@ -115,10 +115,10 @@ Smoke tests verify the compiled `fence` binary works end-to-end. Unlike integrat
|
||||
./scripts/smoke_test.sh
|
||||
|
||||
# Test specific binary
|
||||
./scripts/smoke_test.sh ./path/to/fence
|
||||
./scripts/smoke_test.sh ./path/to/greywall
|
||||
|
||||
# Enable network tests (requires internet)
|
||||
FENCE_TEST_NETWORK=1 ./scripts/smoke_test.sh
|
||||
GREYWALL_TEST_NETWORK=1 ./scripts/smoke_test.sh
|
||||
```
|
||||
|
||||
## Platform-Specific Behavior
|
||||
@@ -158,7 +158,7 @@ The `integration_test.go` file provides helpers for writing sandbox tests:
|
||||
|
||||
```go
|
||||
// Skip helpers
|
||||
skipIfAlreadySandboxed(t) // Skip if running inside Fence
|
||||
skipIfAlreadySandboxed(t) // Skip if running inside Greywall
|
||||
skipIfCommandNotFound(t, "python3") // Skip if command missing
|
||||
|
||||
// Run a command under the sandbox
|
||||
@@ -237,10 +237,10 @@ go test -v -run TestSpecificTest ./internal/sandbox/...
|
||||
|
||||
```bash
|
||||
# Replicate what the test does
|
||||
./fence -c "the-command-that-failed"
|
||||
./greywall -c "the-command-that-failed"
|
||||
|
||||
# With a settings file
|
||||
./fence -s /path/to/settings.json -c "command"
|
||||
./greywall -s /path/to/settings.json -c "command"
|
||||
```
|
||||
|
||||
### Check platform capabilities
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
## Nested Sandboxing Not Supported
|
||||
|
||||
Fence cannot run inside another sandbox that uses the same underlying technology.
|
||||
Greywall cannot run inside another sandbox that uses the same underlying technology.
|
||||
|
||||
**macOS (Seatbelt)**: If you try to run fence inside an existing `sandbox-exec` sandbox (e.g., Nix's Darwin build sandbox), you'll see:
|
||||
**macOS (Seatbelt)**: If you try to run greywall inside an existing `sandbox-exec` sandbox (e.g., Nix's Darwin build sandbox), you'll see:
|
||||
|
||||
```text
|
||||
Sandbox: sandbox-exec(...) deny(1) forbidden-sandbox-reinit
|
||||
@@ -12,11 +12,11 @@ Sandbox: sandbox-exec(...) deny(1) forbidden-sandbox-reinit
|
||||
|
||||
This is a macOS kernel limitation - nested Seatbelt sandboxes are not allowed. There is no workaround.
|
||||
|
||||
**Linux (Landlock)**: Landlock supports stacking (nested restrictions), but fence's test binaries cannot use the Landlock wrapper (see [Testing docs](testing.md#sandboxed-build-environments-nix-etc)).
|
||||
**Linux (Landlock)**: Landlock supports stacking (nested restrictions), but greywall's test binaries cannot use the Landlock wrapper (see [Testing docs](testing.md#sandboxed-build-environments-nix-etc)).
|
||||
|
||||
## "bwrap: loopback: Failed RTM_NEWADDR: Operation not permitted" (Linux)
|
||||
|
||||
This error occurs when fence tries to create a network namespace but the environment lacks the `CAP_NET_ADMIN` capability. This is common in:
|
||||
This error occurs when greywall tries to create a network namespace but the environment lacks the `CAP_NET_ADMIN` capability. This is common in:
|
||||
|
||||
- **Docker containers** (unless run with `--privileged` or `--cap-add=NET_ADMIN`)
|
||||
- **GitHub Actions** and other CI runners
|
||||
@@ -25,7 +25,7 @@ This error occurs when fence tries to create a network namespace but the environ
|
||||
|
||||
**What happens now:**
|
||||
|
||||
Fence automatically detects this limitation and falls back to running **without network namespace isolation**. The sandbox still provides:
|
||||
Greywall automatically detects this limitation and falls back to running **without network namespace isolation**. The sandbox still provides:
|
||||
|
||||
- Filesystem restrictions (read-only root, allowWrite paths)
|
||||
- PID namespace isolation
|
||||
@@ -41,7 +41,7 @@ Fence automatically detects this limitation and falls back to running **without
|
||||
**To check if your environment supports network namespaces:**
|
||||
|
||||
```bash
|
||||
fence --linux-features
|
||||
greywall --linux-features
|
||||
```
|
||||
|
||||
Look for "Network namespace (--unshare-net): true/false"
|
||||
@@ -51,7 +51,7 @@ Look for "Network namespace (--unshare-net): true/false"
|
||||
1. **Run with elevated privileges:**
|
||||
|
||||
```bash
|
||||
sudo fence <command>
|
||||
sudo greywall <command>
|
||||
```
|
||||
|
||||
2. **In Docker, add capability:**
|
||||
@@ -96,20 +96,20 @@ On most systems with package-manager-installed bwrap, this error shouldn't occur
|
||||
This usually means:
|
||||
|
||||
- the process tried to reach a domain that is **not allowed**, and
|
||||
- the request went through fence's HTTP proxy, which returned `403`.
|
||||
- the request went through greywall's HTTP proxy, which returned `403`.
|
||||
|
||||
Fix:
|
||||
|
||||
- Run with monitor mode to see what was blocked:
|
||||
- `fence -m <command>`
|
||||
- `greywall -m <command>`
|
||||
- Add the required destination(s) to `network.allowedDomains`.
|
||||
|
||||
## "It works outside fence but not inside"
|
||||
## "It works outside greywall but not inside"
|
||||
|
||||
Start with:
|
||||
|
||||
- `fence -m <command>` to see what's being denied
|
||||
- `fence -d <command>` to see full proxy and sandbox detail
|
||||
- `greywall -m <command>` to see what's being denied
|
||||
- `greywall -d <command>` to see full proxy and sandbox detail
|
||||
|
||||
Common causes:
|
||||
|
||||
@@ -134,7 +134,7 @@ const response = await fetch(url, {
|
||||
});
|
||||
```
|
||||
|
||||
Fence's OS-level sandbox should still block direct connections; the above makes your requests go through the filtering proxy so allowlisting works as intended.
|
||||
Greywall's OS-level sandbox should still block direct connections; the above makes your requests go through the filtering proxy so allowlisting works as intended.
|
||||
|
||||
## Local services (Redis/Postgres/etc.) fail inside the sandbox
|
||||
|
||||
@@ -156,7 +156,7 @@ If you're running a server inside the sandbox that must accept connections:
|
||||
Writes are denied by default.
|
||||
|
||||
- Add the minimum required writable directories to `filesystem.allowWrite`.
|
||||
- Protect sensitive targets with `filesystem.denyWrite` (and note fence protects some targets regardless).
|
||||
- Protect sensitive targets with `filesystem.denyWrite` (and note greywall protects some targets regardless).
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Why Fence?
|
||||
# Why Greywall?
|
||||
|
||||
Fence exists to reduce the blast radius of running commands you don't fully trust (or don't fully understand yet).
|
||||
Greywall exists to reduce the blast radius of running commands you don't fully trust (or don't fully understand yet).
|
||||
|
||||
Common situations:
|
||||
|
||||
@@ -9,11 +9,11 @@ Common situations:
|
||||
- Running CI jobs where you want default-deny egress and tightly scoped writes
|
||||
- Auditing what a command *tries* to do before you let it do it
|
||||
|
||||
Fence is intentionally simple: it focuses on network allowlisting (by domain) and filesystem write restrictions (by path), wrapped in a pragmatic OS sandbox (macOS `sandbox-exec`, Linux `bubblewrap`).
|
||||
Greywall is intentionally simple: it focuses on network allowlisting (by domain) and filesystem write restrictions (by path), wrapped in a pragmatic OS sandbox (macOS `sandbox-exec`, Linux `bubblewrap`).
|
||||
|
||||
## What problem does it solve?
|
||||
|
||||
Fence helps you answer: "What can this command touch?"
|
||||
Greywall helps you answer: "What can this command touch?"
|
||||
|
||||
- **Network**: block all outbound by default; then allow only the domains you choose.
|
||||
- **Filesystem**: default-deny writes; then allow writes only where you choose (and deny sensitive writes regardless).
|
||||
@@ -21,9 +21,9 @@ Fence helps you answer: "What can this command touch?"
|
||||
|
||||
This is especially useful for supply-chain risk and "unknown repo" workflows where you want a safer default than "run it and hope".
|
||||
|
||||
## When Fence is useful even if tools already sandbox
|
||||
## When Greywall is useful even if tools already sandbox
|
||||
|
||||
Some coding agents and platforms ship sandboxing (Seatbelt/Landlock/etc.). Fence still provides value when you want:
|
||||
Some coding agents and platforms ship sandboxing (Seatbelt/Landlock/etc.). Greywall still provides value when you want:
|
||||
|
||||
- **Tool-agnostic policy**: apply the same rules to any command, not only inside one agent.
|
||||
- **Standardization**: commit/review a config once, use it across developers and CI.
|
||||
@@ -32,7 +32,7 @@ Some coding agents and platforms ship sandboxing (Seatbelt/Landlock/etc.). Fence
|
||||
|
||||
## Non-goals
|
||||
|
||||
Fence is **not** a hardened containment boundary for actively malicious code.
|
||||
Greywall is **not** a hardened containment boundary for actively malicious code.
|
||||
|
||||
- It does **not** attempt to prevent resource exhaustion (CPU/RAM/disk), timing attacks, or kernel-level escapes.
|
||||
- Domain allowlisting is not content inspection: if you allow a domain, code can exfiltrate via that domain.
|
||||
Reference in New Issue
Block a user