You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: fix Docusaurus broken link + put three-modes content in served doc
CI build/Cloudflare-Pages failed: onBrokenLinks:throw flagged the error doc's
link to ../docker-isolation.md, which the website does not serve (its `include`
list only builds features/**, errors/**, etc. — not the top-level
docs/docker-isolation.md). Port the Isolation Modes / Sandbox / Scanner-
behaviour / Honest-limitations / Platform-matrix content into the served
docs/features/docker-isolation.md (the user-facing isolation page) and repoint
the MCPX_DOCKER_SNAP_APPARMOR link to ../features/docker-isolation.md.
Verified: website `npm run build` succeeds locally (no broken links).
Co-Authored-By: Paperclip <noreply@paperclip.ing>
MCPProxy provides Docker isolation for stdio MCP servers to enhance security by running each server in its own isolated container.
12
+
MCPProxy can confine stdio MCP servers so a malicious or buggy server cannot freely touch the host. There are **three isolation modes** — `docker`, `sandbox`, and `none` — selected by `docker_isolation.mode` (global) or `isolation.mode` (per-server). Most of this page describes **Docker** mode (the default and most capable); see [Isolation Modes](#isolation-modes) for the native **Sandbox** mode and the scanner behaviour under each mode.
13
+
14
+
:::note
15
+
The global config key is still `docker_isolation` for backward compatibility, but its `mode` field selects any of the three modes — it is not Docker-only.
-**Resource Limits**: Memory and CPU limits prevent resource exhaustion
22
26
-**Automatic Runtime Detection**: Maps commands to appropriate Docker images
23
27
28
+
## Isolation Modes
29
+
30
+
MCPProxy resolves an **isolation mode** for every stdio server. Set it globally with `docker_isolation.mode` and override per-server with `isolation.mode`:
31
+
32
+
| Mode | What it does | Where it works | uid/gid drop |
|`docker`| Wraps the server in a Docker container (process/FS/network isolation, resource limits). The default and most capable mode. | Any host with a working Docker daemon. | Yes (container user) |
35
+
|`sandbox`| Runs the server **natively** under a Linux [Landlock](https://docs.kernel.org/userspace-api/landlock.html) filesystem allowlist + `setrlimit` resource caps — **no Docker required**. For hosts where Docker isolation is unavailable or broken (e.g. snap-docker + AppArmor). | Linux 5.13+ only. macOS/Windows: documented no-op ⇒ behaves like `none`. |**No** — see [Honest limitations](#honest-limitations)|
36
+
|`none`| No confinement; the server runs directly on the host. | Everywhere. | n/a |
Per-server precedence: explicit per-server `mode` → per-server legacy `enabled` → global `mode` → global legacy `enabled`.
56
+
57
+
### Sandbox mode (Landlock)
58
+
59
+
`sandbox` mode confines a stdio server **without Docker** by applying a Linux Landlock LSM ruleset (a writable-path allowlist) plus `setrlimit` resource caps to the process before it `exec`s, then preserving the raw stdin/stdout JSON-RPC pipes. It needs no user namespaces, so it is unaffected by `kernel.apparmor_restrict_unprivileged_userns=1` — which is exactly why it works where bubblewrap/userns-based sandboxes are blocked (e.g. Ubuntu 24.04 with snap-docker).
60
+
61
+
### Scanner behaviour under each mode (MCP-34.4)
62
+
63
+
The security **scanner plugins** are Docker-based. Under a non-Docker isolation mode they cannot run, so MCPProxy **degrades cleanly and surfaces it** rather than failing silently:
64
+
65
+
| Mode | Docker scanner plugins | In-process scanner (`tpa-descriptions`) | Scan result for a server with only Docker scanners |
|`sandbox` / `none`|**Skipped** with an honest, mode-specific reason pointing at [`MCPX_DOCKER_SNAP_APPARMOR`](/errors/MCPX_DOCKER_SNAP_APPARMOR)|**Still runs**|`security_scan.status: "degraded"` (a low/zero risk score from incomplete coverage is not reported as a trustworthy all-clear) |
69
+
70
+
This is **decision D3 option (b)**: clean, surfaced degradation. A native (non-Docker) scanner runtime — option (a) — is a larger follow-up and is not yet implemented. To run the full Docker-based scanner fleet, use `mode: docker` on a host with a working Docker daemon, or replace snap-docker with a distro Docker package (see the error doc). The skip is also logged at startup:
71
+
72
+
```
73
+
WARN Isolation mode runs no Docker for scanner plugins; Docker-based scanners will be skipped … {"isolation_mode": "sandbox"}
See [Shutdown Behavior](/operations/shutdown-behavior) for detailed subprocess lifecycle documentation.
261
313
314
+
## Honest limitations
315
+
316
+
`sandbox` mode is deliberately scoped. Known limitations:
317
+
318
+
-**No uid/gid drop.** Dropping to an unprivileged uid/gid requires `CAP_SETUID`/`CAP_SETGID` (i.e. running as root). When mcpproxy runs unprivileged, the uid/gid drop is **best-effort and typically a no-op** — the sandboxed process keeps the launching user's identity. Landlock (filesystem) and `setrlimit` (resource caps) still apply. Docker mode does drop to a container user. This is an honest trade-off, not a bug.
319
+
-**Linux-only.** Landlock is a Linux 5.13+ feature. On older kernels the launcher degrades best-effort (fewer access-right bits enforced). On macOS/Windows `sandbox` is a documented **no-op** and behaves like `none`.
320
+
-**Filesystem + resources only.** Landlock confines the filesystem write-allowlist; it does not provide network namespacing. For network-sensitive servers, use `docker` mode with `network_mode: none`.
321
+
-**Docker-based scanners do not run under `sandbox`/`none`.** They are skipped (the scan reports `degraded`). A native scanner runtime is a future enhancement.
0 commit comments