Refactor and improve documentation, add examples
This commit is contained in:
75
docs/security-model.md
Normal file
75
docs/security-model.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# 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).
|
||||
|
||||
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)
|
||||
|
||||
Fence 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
|
||||
|
||||
### Network
|
||||
|
||||
- **Default deny**: outbound network is blocked unless explicitly allowed.
|
||||
- **Allowlisting by domain**: you can specify `allowedDomains` (with wildcard support like `*.example.com`).
|
||||
- **Localhost controls**: inbound binding and localhost outbound are separately controlled.
|
||||
|
||||
Important: domain filtering does **not** inspect content. If you allow a domain, code can exfiltrate via that domain.
|
||||
|
||||
#### How allowlisting works (important nuance)
|
||||
|
||||
Fence 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`).
|
||||
|
||||
If a program does not use proxy env vars (or uses a custom protocol/stack), it may **not benefit from domain allowlisting**. In that case it typically fails with connection errors rather than being "selectively allowed."
|
||||
|
||||
Localhost is separate from "external domains":
|
||||
|
||||
- `allowLocalOutbound=false` can intentionally block connections to local services like Redis on `127.0.0.1:6379` (see the dev-server example).
|
||||
|
||||
### Filesystem
|
||||
|
||||
- **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.
|
||||
|
||||
## Visibility / auditing
|
||||
|
||||
- `-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)
|
||||
|
||||
- **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.
|
||||
- **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
|
||||
|
||||
The proxy approach works well for many tools (curl, wget, git, npm, pip), but **not by default** for some stacks:
|
||||
|
||||
- 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.
|
||||
|
||||
### 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.
|
||||
|
||||
### 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.
|
||||
|
||||
For implementation details (how proxies/sandboxes/bridges work), see [`ARCHITECTURE.md`](../ARCHITECTURE.md).
|
||||
Reference in New Issue
Block a user