Skip to content

Commit a8682c6

Browse files
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>
1 parent 3536ac4 commit a8682c6

2 files changed

Lines changed: 77 additions & 7 deletions

File tree

docs/errors/MCPX_DOCKER_SNAP_APPARMOR.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ Trade-off: the Docker-based scanner plugins cannot run under `sandbox`, so they
5050
are **skipped** and the affected server's `security_scan.status` becomes
5151
`degraded` (the always-on in-process `tpa-descriptions` scanner still runs).
5252
This is MCP-34.4 / D3 option (b) — clean, surfaced degradation. See
53-
[Security Isolation → Scanner behaviour](../docker-isolation.md#scanner-behaviour-under-each-mode-mcp-344).
53+
[Security Isolation → Scanner behaviour](../features/docker-isolation.md#scanner-behaviour-under-each-mode-mcp-344).
5454

5555
### 3. Disable the scanner for this server (dry-run shown by default)
5656

docs/features/docker-isolation.md

Lines changed: 76 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
---
22
id: docker-isolation
3-
title: Docker Security Isolation
4-
sidebar_label: Docker Isolation
3+
title: Security Isolation (Docker · Sandbox · None)
4+
sidebar_label: Security Isolation
55
sidebar_position: 1
6-
description: Run MCP servers in isolated Docker containers for enhanced security
7-
keywords: [docker, isolation, security, containers]
6+
description: Confine MCP servers with Docker containers, native Landlock sandboxing, or no isolation
7+
keywords: [docker, isolation, sandbox, landlock, security, containers]
88
---
99

10-
# Docker Security Isolation
10+
# Security Isolation (Docker · Sandbox · None)
1111

12-
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.
16+
:::
1317

1418
## Overview
1519

@@ -21,6 +25,54 @@ Docker isolation automatically wraps stdio-based MCP servers in Docker container
2125
- **Resource Limits**: Memory and CPU limits prevent resource exhaustion
2226
- **Automatic Runtime Detection**: Maps commands to appropriate Docker images
2327

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 |
33+
|------|--------------|----------------|--------------|
34+
| `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 |
37+
38+
```json
39+
{
40+
"docker_isolation": { "mode": "sandbox" },
41+
"mcpServers": [
42+
{ "name": "trusted-local", "command": "uvx", "args": ["x"], "isolation": { "mode": "none" } }
43+
]
44+
}
45+
```
46+
47+
### Back-compat with the legacy `enabled` flag
48+
49+
The older boolean `docker_isolation.enabled` (and per-server `isolation.enabled`) still works and is mapped to a mode:
50+
51+
- an explicit `mode` always wins;
52+
- otherwise `enabled: true``docker`, `enabled: false``none`;
53+
- a missing isolation config ⇒ `none`.
54+
55+
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 |
66+
|------|------------------------|------------------------------------------|----------------------------------------------------|
67+
| `docker` | Run normally | Runs | As scanned |
68+
| `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"}
74+
```
75+
2476
## Configuration
2577

2678
### Global Docker Isolation
@@ -259,6 +311,24 @@ docker rm -f $(docker ps -q --filter "label=mcpproxy.managed=true")
259311

260312
See [Shutdown Behavior](/operations/shutdown-behavior) for detailed subprocess lifecycle documentation.
261313

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.
322+
323+
## Platform support matrix
324+
325+
| Platform | `docker` | `sandbox` | `none` | Docker scanner plugins |
326+
|----------|----------|-----------|--------|------------------------|
327+
| Linux (kernel ≥ 5.13) | ✅ (needs Docker daemon) | ✅ Landlock + rlimits (no uid/gid drop) || ✅ under `docker`; skipped+degraded under `sandbox`/`none` |
328+
| Linux (kernel &lt; 5.13) | ✅ (needs Docker daemon) | ⚠️ best-effort: rlimits apply, Landlock partial/unavailable || same as above |
329+
| macOS | ✅ (Docker Desktop) | ⚠️ no-op ⇒ effectively `none` || ✅ under `docker`; n/a otherwise |
330+
| Windows | ✅ (Docker Desktop) | ⚠️ no-op ⇒ effectively `none` || ✅ under `docker`; n/a otherwise |
331+
262332
## Security Considerations
263333

264334
Docker isolation provides strong security boundaries but consider:

0 commit comments

Comments
 (0)