5.0 KiB
Configuration
Fence reads settings from ~/.fence.json by default (or pass --settings ./fence.json). Config files support JSONC.
Example config:
{
"network": {
"allowedDomains": ["github.com", "*.npmjs.org", "registry.yarnpkg.com"],
"deniedDomains": ["evil.com"]
},
"filesystem": {
"denyRead": ["/etc/passwd"],
"allowWrite": [".", "/tmp"],
"denyWrite": [".git/hooks"]
},
"command": {
"deny": ["git push", "npm publish"]
}
}
Config Inheritance
You can extend built-in templates or other config files using the extends field. This reduces boilerplate by inheriting settings from a base and only specifying your overrides.
Extending a template
{
"extends": "code",
"network": {
"allowedDomains": ["private-registry.company.com"]
}
}
This config:
- Inherits all settings from the
codetemplate (LLM providers, package registries, filesystem protections, command restrictions) - Adds
private-registry.company.comto the allowed domains list
Extending a file
You can also extend other config files using absolute or relative paths:
{
"extends": "./base-config.json",
"network": {
"allowedDomains": ["extra-domain.com"]
}
}
{
"extends": "/etc/fence/company-base.json",
"filesystem": {
"denyRead": ["~/company-secrets/**"]
}
}
Relative paths are resolved relative to the config file's directory. The extended file is validated before merging.
Detection
The extends value is treated as a file path if it contains / or \, or starts with .. Otherwise it's treated as a template name.
Merge behavior
- Slice fields (domains, paths, commands) are appended and deduplicated
- Boolean fields use OR logic (true if either base or override enables it)
- Integer fields (ports) use override-wins semantics (0 keeps base value)
Chaining
Extends chains are supported—a file can extend a template, and another file can extend that file. Circular extends are detected and rejected. Maximum chain depth is 10.
See templates.md for available templates.
Network Configuration
| Field | Description |
|---|---|
allowedDomains |
List of allowed domains. Supports wildcards like *.example.com |
deniedDomains |
List of denied domains (checked before allowed) |
allowUnixSockets |
List of allowed Unix socket paths (macOS) |
allowAllUnixSockets |
Allow all Unix sockets |
allowLocalBinding |
Allow binding to local ports |
allowLocalOutbound |
Allow outbound connections to localhost, e.g., local DBs (defaults to allowLocalBinding if not set) |
httpProxyPort |
Fixed port for HTTP proxy (default: random available port) |
socksProxyPort |
Fixed port for SOCKS5 proxy (default: random available port) |
Wildcard Domain Access
Setting allowedDomains: ["*"] enables relaxed network mode:
- Direct network connections are allowed (sandbox doesn't block outbound)
- Proxy still runs for apps that respect
HTTP_PROXY deniedDomainsis only enforced for apps using the proxy
Warning
Security tradeoff: Apps that ignore
HTTP_PROXYwill bypassdeniedDomainsfiltering entirely.
Use this when you need to support apps that don't respect proxy environment variables.
Filesystem Configuration
| Field | Description |
|---|---|
denyRead |
Paths to deny reading (deny-only pattern) |
allowWrite |
Paths to allow writing |
denyWrite |
Paths to deny writing (takes precedence) |
allowGitConfig |
Allow writes to .git/config files |
Command Configuration
Block specific commands from being executed, even within command chains.
| Field | Description |
|---|---|
deny |
List of command prefixes to block (e.g., ["git push", "rm -rf"]) |
allow |
List of command prefixes to allow, overriding deny |
useDefaults |
Enable default deny list of dangerous system commands (default: true) |
Example:
{
"command": {
"deny": ["git push", "npm publish"],
"allow": ["git push origin docs"]
}
}
Default Denied Commands
When useDefaults is true (the default), fence blocks these dangerous commands:
- System control:
shutdown,reboot,halt,poweroff,init 0/6 - Kernel manipulation:
insmod,rmmod,modprobe,kexec - Disk operations:
mkfs*,fdisk,parted,dd if= - Container escape:
docker run -v /:/,docker run --privileged - Namespace escape:
chroot,unshare,nsenter
To disable defaults: "useDefaults": false
Command Detection
Fence detects blocked commands in:
- Direct commands:
git push origin main - Command chains:
ls && git pushorls; git push - Pipelines:
echo test | git push - Shell invocations:
bash -c "git push"orsh -lc "ls && git push"
Other Options
| Field | Description |
|---|---|
allowPty |
Allow pseudo-terminal (PTY) allocation in the sandbox (for MacOS) |
See Also
- Config templates:
docs/templates/ - Workflow guides:
docs/recipes/