capgate 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,167 +1,290 @@
1
- # capgate
2
-
3
- **Compile MCP tool manifests into sandbox policies.**
4
-
5
- `capgate` is a pure TypeScript library that reads [Model Context Protocol](https://modelcontextprotocol.io) server manifests and emits concrete sandbox policies bubblewrap argv, egress allowlist rules, environment injection lists, and declared-but-unenforced assertionssuitable for consumption by a host runtime.
6
-
7
- It is a compiler, not a runtime. It does not execute tools, resolve secrets, or speak MCP on the wire.
8
-
9
- ```
10
- manifest (JSON) → Capability[] (parsed) → NormalizedPolicy (merged) → adapter output
11
- ```
12
-
13
- Status: **v0.0.1 design partner preview.** The grammar, IR, and bwrap adapter are implemented and golden-tested. APIs may change before v0.1.
14
-
15
- ---
16
-
17
- ## Install
18
-
19
- ```bash
20
- npm install capgate
21
- ```
22
-
23
- Requires Node.js ≥ 18.
24
-
25
- ## Quick example
26
-
27
- ```ts
28
- import { compile, lowerToBwrap } from 'capgate';
29
-
30
- const manifest = {
31
- name: 'filesystem',
32
- version: '0.6.2',
33
- tools: [
34
- {
35
- name: 'read_file',
36
- description: 'Read a file from the workspace.',
37
- inputSchema: { type: 'object' },
38
- capabilities: ['fs:read:/workspace/**'],
39
- },
40
- {
41
- name: 'write_file',
42
- description: 'Write a file to the workspace.',
43
- inputSchema: { type: 'object' },
44
- capabilities: ['fs:read,write,create:/workspace/**'],
45
- },
46
- ],
47
- };
48
-
49
- const policy = compile(manifest);
50
- const artifact = lowerToBwrap(policy);
51
-
52
- // artifact.argv — ready for execFile("bwrap", argv)
53
- // artifact.egress — host egress proxy rules (empty here)
54
- // artifact.notes — audit-friendly diagnostics
55
- ```
56
-
57
- See [`tests/fixtures/policy/`](tests/fixtures/policy) for worked examples covering filesystem, fetch, and puppeteer manifests.
58
-
59
- ### CLI
60
-
61
- ```bash
62
- capgate compile manifest.json --target bwrap --pretty
63
- cat manifest.json | capgate compile - --target bwrap
64
- ```
65
-
66
- Exits non-zero on parse errors (3), unknown arguments (2), or `CompilationError` (4). See `capgate --help`.
67
-
68
- ---
69
-
70
- ## Why this exists
71
-
72
- MCP tool manifests declare *what* a tool does; they do not declare *what host resources it needs*. Today every runtime either trusts servers fully (Claude Desktop, most wrappers) or wraps them in a one-size-fits-all container (AIO Sandbox, E2B). Neither approach lets a security policy be *derived from the manifest*. capgate closes that gap: a pure function from `ServerManifest` to adapter-specific policies.
73
-
74
- ## Scope for v0.1
75
-
76
- **In scope:**
77
- - Capability grammar covering `fs`, `net`, `exec`, `env`, `ipc`, `clock`, `assert`.
78
- - Lowering to three targets: `bwrap` (Linux namespace sandbox), egress-proxy rules (net allowlist), Worker `resourceLimits` (in-process JS isolation).
79
- - Golden-file tests from real MCP server manifests.
80
-
81
- **Out of scope (deferred):**
82
- - Firecracker / microVM adapter — needed for production but not for proving the abstraction.
83
- - E2B / Daytona / Blaxel adapters — API stability varies; wait for a design partner.
84
- - seccomp-bpf syscall filters — requires a separate IR; out of the capability model.
85
- - MCP client/server implementation — this library consumes manifests, it does not speak MCP on the wire.
86
-
87
- ## Capability grammar
88
-
89
- Capabilities are strings of the form `<kind>:<actions>:<scope>[?refinement=value&...]`.
90
-
91
- ```
92
- fs:read,write:/workspace/**
93
- fs:read:/usr/share/zoneinfo
94
- net:connect:api.github.com:443
95
- net:connect:* # any host, any port; implicit blockPrivate=true
96
- exec:spawn:git
97
- exec:spawn:chromium?nestedSandbox=true
98
- env:inject:GITHUB_PAT
99
- ipc:connect:x11
100
- clock:tzdata
101
- assert:postgres.read_only_txn:"all queries run in READ ONLY TRANSACTION"
102
- ```
103
-
104
- The grammar rejects ambiguity (relative paths, bad ports, non-UPPER_SNAKE env vars) at parse time — fail-closed, always.
105
-
106
- ## Design notes
107
-
108
- ### Why capabilities are typed and discriminated
109
-
110
- Early drafts used `{ resource: string; actions: string[]; scope: object }`. That failed the go/no-go test: every adapter had to re-parse `resource` to know what kind of capability it was looking at. The current discriminated union (`kind: 'fs' | 'net' | ...`) makes adapter code a flat switch; no string parsing past the grammar layer.
111
-
112
- ### Why enforceable vs declared
113
-
114
- The go/no-go exercise revealed two capabilities that cannot be enforced at the sandbox layer: `fetch`'s RFC1918 block (sandbox can only toggle net on/off) and `postgres`'s read-only transaction guarantee (lives inside the MCP server). Silently dropping them would be a security lie. Promoting them to a first-class `assert:` capability keeps them in the audit trail: adapters emit them as metadata, the host is expected to verify them out-of-band, and the compiler fails compilation if an assertion is unrecognized by any configured validator (deferred to v0.2).
115
-
116
- ### Why the grammar is string-based
117
-
118
- JSON-object capabilities are verbose and bury the kind under keys. The string form `fs:read,write:/workspace/**` is one line in a manifest, greps cleanly, and round-trips losslessly through the grammar.
119
-
120
- ### Why `nestedSandbox` is a refinement, not a kind
121
-
122
- Chromium carries its own sandbox that fights namespace isolation. Every production sandbox tool has a special case for this. Rather than a new capability kind, `nestedSandbox=true` is a refinement on an existing `exec:` capability — the adapter sees it during lowering and emits a different bwrap profile (user/pid/ipc namespaces kept for inner-sandbox compatibility). The IR stays small; the edge case is explicit and documented.
123
-
124
- ## Non-goals that matter
125
-
126
- - **The compiler does not decide trust.** Capability declarations come from the manifest; the compiler does not infer them from tool descriptions. Inference belongs in a separate auditing tool. A manifest that under-declares is a bug in the manifest.
127
- - **The compiler does not execute.** It emits policy artifacts. Running bwrap, wiring proxies, and spawning Workers is the host's job.
128
- - **The compiler does not resolve secrets.** `env:inject:GITHUB_PAT` carries the name only. A secret store resolves the value at runtime, outside this library.
129
-
130
- ## Failure modes
131
-
132
- - Unknown capability kind → `CompilationError('CAP_UNKNOWN_KIND')`.
133
- - Capability a configured adapter cannot lower → `CompilationError('ADAPTER_UNSUPPORTED')` *(impl. pending)*.
134
- - Manifest missing required fields → `CompilationError('MANIFEST_SHAPE')`.
135
-
136
- All compilation errors are fatal. There is no warning mode.
137
-
138
- ## Validation
139
-
140
- Before committing to the capability-grammar abstraction, we ran a [go/no-go exercise](tests/fixtures/policy/GO_NO_GO.md) against 10 real MCP servers. 9/10 lowered mechanically to bwrap; 1 (puppeteer) surfaced the need for a `nestedSandbox` refinement; 2 (fetch, postgres) motivated the first-class `assert:` capability kind. That inventory is durable and names each server, its source, and the capability string set that should lower to it.
141
-
142
- ## Test strategy
143
-
144
- Golden files. One fixture manifest → one expected policy per adapter. Every PR that changes grammar, IR, or an adapter must update the golden files in the same commit. Reviewers read the diff. This is the primary correctness mechanism; unit tests on the grammar are secondary.
145
-
146
- ```bash
147
- npm test # run all tests
148
- npm run test:update-goldens # regenerate golden files after intentional changes
149
- ```
150
-
151
- ## Open questions before v0.1
152
-
153
- 1. **Egress proxy choice.** mitmproxy (great DX, slow, not prod-grade) vs nftables (hard to author, prod-grade, Linux-only) vs Envoy (prod-grade, ops-heavy). Current plan: ship a thin YAML spec the compiler emits, plus one reference binding to mitmproxy for dev. Let ops pick their own enforcement.
154
- 2. **Path glob semantics.** bwrap binds directories, not globs. A `fs:read:/workspace/**` capability lowers to `--ro-bind /workspace /workspace`, which is a *superset* of the declared scope. Runtime enforcement of globs is an MCP-server concern.
155
- 3. **Server-level vs tool-level capabilities.** v0.0 unions them. Finer-grained per-tool sandboxing (one sandbox per invocation) is possible but expensive — deferred until a user asks for it.
156
-
157
- ## Contributing
158
-
159
- Design-partner stage. If you run MCP servers in production and have feedback on the grammar or adapter output, please open a [discussion](https://github.com/razukc/capgate/discussions) or file an issue with a concrete manifest and your expected output. See [CONTRIBUTING.md](CONTRIBUTING.md) for what's most useful right now.
160
-
161
- ## Security
162
-
163
- capgate compiles declarations into sandbox policies downstream hosts trust — bugs here can silently over-grant. Please report privately per [SECURITY.md](SECURITY.md).
164
-
165
- ## License
166
-
167
- MIT — see [LICENSE](LICENSE).
1
+ # capgate
2
+
3
+ **Compile MCP tool manifests into sandbox policies.**
4
+
5
+ MCP servers today either run with full host trust (Claude Desktop, most wrappers) or get wrapped in a one-size-fits-all container. Neither lets you say *this server needs `fs:read:/workspace/**` and `net:connect:api.github.com:443`, nothing else* and have a sandbox policy fall out of that declaration.
6
+
7
+ `capgate` is the missing compile step. It reads a [Model Context Protocol](https://modelcontextprotocol.io) server manifest, parses capability strings, and emits a concrete sandbox policy your host can hand straight to bubblewrap or `docker run`.
8
+
9
+ ```
10
+ manifest (JSON) → Capability[] → NormalizedPolicy → adapter (bwrap | docker) → argv + egress + env + assertions
11
+ ```
12
+
13
+ It is a **sandbox compiler for MCP servers**, not a runtime. It does not execute tools, resolve secrets, or speak MCP on the wire. Its job is to make the sandbox boundary **reviewable in a PR before the first agent call** — what the server is allowed to reach lives in the repo, not in someone's `docker run` muscle memory.
14
+
15
+ **For platform and security engineers** who can't ship MCP servers under blanket host trust and don't want to hand-write bwrap argv or `docker run` flags per server. **Not for** end-user agent UIs (this isn't a runtime), or for teams who want post-hoc tool-call auditing — that's a different lane (see [How capgate compares](#how-capgate-compares) below for the short version, or [A working map of MCP security tools](https://razukc.github.io/capgate/positioning/) for the full discussion).
16
+
17
+ ---
18
+
19
+ ## Install
20
+
21
+ ```bash
22
+ npm install capgate
23
+ ```
24
+
25
+ Requires Node.js ≥ 18.
26
+
27
+ ## 30-second example
28
+
29
+ ```ts
30
+ import { compile, lowerToDocker } from 'capgate';
31
+
32
+ const docker = lowerToDocker(compile({
33
+ name: 'my-server',
34
+ version: '0.1.0',
35
+ tools: [{ name: 'read_file', capabilities: ['fs:read:/workspace/**'] }],
36
+ }));
37
+
38
+ console.log(docker.argv.join(' '));
39
+ // → --rm --cap-drop ALL --security-opt no-new-privileges --read-only
40
+ // --tmpfs /tmp --network none --volume /workspace:/workspace:ro
41
+ ```
42
+
43
+ One capability in, one container policy out. No declared network → `--network none`. Read-only declared → `:ro` mount. No env declared → no env crosses the boundary. The CLI prints the same artifact for `bwrap`.
44
+
45
+ ## CLI
46
+
47
+ ```bash
48
+ capgate compile manifest.json --target bwrap --pretty
49
+ capgate compile manifest.json --target docker --pretty
50
+ capgate compile manifest.json --target egress --egress-target squid --pretty
51
+ capgate compile manifest.json --target egress --egress-target nftables --pretty
52
+ cat manifest.json | capgate compile - --target docker
53
+ ```
54
+
55
+ `--target egress` emits a static proxy config for a host-run proxy (`--egress-target squid|nftables`, default `squid`). Exits non-zero on parse errors (3), unknown arguments (2), or `CompilationError` (4). See `capgate --help`.
56
+
57
+ ---
58
+
59
+ ## Worked example: `github` server with PAT
60
+
61
+ The 30-second example is a single tool with a single capability. A realistic MCP server has several tools, several capability kinds, and a threat model that motivates the sandbox in the first place.
62
+
63
+ **The threat.** An MCP `github` server runs with a personal access token in its environment. A tool description carrying adversarial text triggers an outbound request to attacker-controlled infrastructure, exfiltrating the PAT. A default container won't stop this — it inherits the host environment and reaches any host on the internet.
64
+
65
+ **The verdict.** capgate compiles the manifest below into a policy whose egress allowlist contains exactly one entry: `api.github.com:443`. An egress proxy honoring that allowlist refuses any outbound request that isn't api.github.com, blocking PAT exfiltration to a third party. No host env is inherited; only `GITHUB_PERSONAL_ACCESS_TOKEN` is named for the host's secret store to inject at exec time.
66
+
67
+ ```ts
68
+ import { compile, lowerToBwrap, lowerToDocker } from 'capgate';
69
+
70
+ const manifest = {
71
+ name: '@modelcontextprotocol/server-github',
72
+ version: '0.6.2',
73
+ tools: [
74
+ {
75
+ name: 'create_issue',
76
+ description: 'Create an issue on a GitHub repository',
77
+ capabilities: [
78
+ 'net:connect:api.github.com:443',
79
+ 'env:inject:GITHUB_PERSONAL_ACCESS_TOKEN',
80
+ ],
81
+ },
82
+ {
83
+ name: 'search_code',
84
+ description: 'Search code in a local checkout',
85
+ capabilities: [
86
+ 'fs:read:/workspace/**',
87
+ 'net:connect:api.github.com:443',
88
+ ],
89
+ },
90
+ {
91
+ name: 'apply_patch',
92
+ description: 'Apply a code patch to the local checkout',
93
+ capabilities: ['fs:read,write:/workspace/**'],
94
+ },
95
+ ],
96
+ };
97
+
98
+ const policy = compile(manifest);
99
+ const bwrap = lowerToBwrap(policy);
100
+ const docker = lowerToDocker(policy, { readOnlyRootfs: true });
101
+
102
+ // Both artifacts share the same shape:
103
+ // .argv — flags ready for execFile()
104
+ // .egress — host egress-proxy allowlist (compiler-emitted, host-enforced)
105
+ // .envInjections — env var names the host must inject from a secret store
106
+ // .assertions — declared guarantees the sandbox cannot enforce; host verifies
107
+ // .notes — audit-friendly diagnostics (drift, edge cases, host decisions)
108
+ ```
109
+
110
+ The compiler unions per-tool capabilities into a server-level policy: `apply_patch` widens `/workspace` from `:ro` to `:rw`, and only one env name survives the merge.
111
+
112
+ ```jsonc
113
+ // docker.egress === bwrap.egress
114
+ [{ "host": "api.github.com", "port": 443, "blockPrivate": true }]
115
+ ```
116
+
117
+ Adapter `argv` (docker shown in full; bwrap abridged):
118
+
119
+ ```
120
+ # docker (full)
121
+ --rm --cap-drop ALL --security-opt no-new-privileges --read-only
122
+ --tmpfs /tmp
123
+ --volume /workspace:/workspace:rw
124
+ --env GITHUB_PERSONAL_ACCESS_TOKEN
125
+
126
+ # bwrap (abridged see fixture for full output)
127
+ --unshare-uts --unshare-cgroup-try --unshare-user-try --unshare-pid --unshare-ipc
128
+ --die-with-parent --new-session
129
+ --ro-bind-try /usr /usr --ro-bind-try /lib /lib --ro-bind-try /etc/ssl /etc/ssl
130
+ --proc /proc --tmpfs /tmp
131
+ --bind /workspace /workspace
132
+ --clearenv --setenv PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
133
+ --setenv HOME /tmp
134
+ ```
135
+
136
+ Note what's *missing* from the docker `argv`: no inherited host env, no host network, no extra capabilities, no writable rootfs. capgate emits the policy; enforcement is the host's job.
137
+
138
+ Full golden outputs: [`bwrap/github.json`](tests/fixtures/policy/policies/bwrap/github.json), [`docker/github.json`](tests/fixtures/policy/policies/docker/github.json). Worked examples for `filesystem`, `fetch` (egress + assertions), and `puppeteer` (nested-sandbox edge case) live alongside them.
139
+
140
+ ---
141
+
142
+ ## What's stable, what's evolving
143
+
144
+ `v0.0.x` is published for adopters who want to pin against capgate today. Stability commitments:
145
+
146
+ | Surface | Status in v0.0.x |
147
+ |---|---|
148
+ | Capability string grammar (`fs`, `net`, `env`, `assert` kinds) | **Stable.** String form will not change; new refinements are additive. |
149
+ | Adapter output shape (`argv`, `egress`, `envInjections`, `assertions`, `notes`) | **Stable.** Fields are additive; existing fields keep their semantics. |
150
+ | `compile()` and `lowerToBwrap` / `lowerToDocker` exports | **Stable.** |
151
+ | `lowerToEgress(policy, { target })` (`squid` / `nftables`) | **Usable.** Artifact shape (`config`, `filename`, `unenforceable`, `notes`) is additive; more `EgressTarget` values land without breaking existing ones. |
152
+ | `exec`, `ipc`, `clock` capability kinds | **Usable.** May gain refinements (like `exec:?nestedSandbox=true` did); existing forms keep working. |
153
+ | Adapter option objects (e.g. `lowerToDocker(policy, { readOnlyRootfs })`) | **Evolving.** Will expand in v0.1 as more adapters land. |
154
+ | `assert:` validator hook | **Metadata-only in v0.0.x.** Runtime hook lands in v0.2. |
155
+
156
+ Pin a minor range against `v0.0.x` for production review pipelines. Grammar additions land in `v0.1`; existing strings keep parsing.
157
+
158
+ ## How capgate compares
159
+
160
+ MCP-server security splits across three lanes. capgate is in the static-technical lane. The other two aren't competitors — most teams running MCP servers in production end up wanting more than one.
161
+
162
+ | Lane | What it does | When you'd use it |
163
+ |---|---|---|
164
+ | **Static technical** (capgate) | Reads a manifest, emits sandbox argv + egress allowlist. Static artifact, no runtime. | You want the sandbox policy reviewable in PR before the server ever runs. |
165
+ | **Static governance** | Reads a manifest, emits a compliance report against a threat catalog or policy framework. | You want a procedural sign-off on a server before it's adopted. |
166
+ | **Dynamic attestation** | Logs and cryptographically signs each tool call at runtime. | You need a tamper-evident record of what the server actually did. |
167
+
168
+ Two adjacent concerns are *not* on this map: per-request authentication (gateways / OAuth — about *who* is calling) and runtime threat detection (pattern-watching, anomaly alerts — about flagging in real time). Both are real categories; both are different conversations. See [A working map of MCP security tools](https://razukc.github.io/capgate/positioning/) for the full discussion.
169
+
170
+ If you arrived here from a comparison post and you wanted dynamic attestation or static governance, capgate isn't that — but the artifact it emits can be the input to either.
171
+
172
+ ---
173
+
174
+ ## Validated servers
175
+
176
+ Before committing to the capability-grammar abstraction, we ran a [go/no-go exercise](tests/fixtures/policy/GO_NO_GO.md) against 10 real MCP servers. The full inventory (capability strings, source links, lowering notes) lives in [`GO_NO_GO.md`](tests/fixtures/policy/GO_NO_GO.md); the summary:
177
+
178
+ | Server | Capabilities (excerpt) | Status | Manifest | bwrap | docker |
179
+ |---|---|---|---|---|---|
180
+ | [filesystem](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem) | `fs:read,write:<roots>` | mechanical | [filesystem.json](tests/fixtures/policy/manifests/filesystem.json) | [✓](tests/fixtures/policy/policies/bwrap/filesystem.json) | [✓](tests/fixtures/policy/policies/docker/filesystem.json) |
181
+ | [fetch](https://github.com/modelcontextprotocol/servers/tree/main/src/fetch) | `net:connect:*`, `assert:fetch.block_rfc1918` | mechanical (assert) | [fetch.json](tests/fixtures/policy/manifests/fetch.json) | [✓](tests/fixtures/policy/policies/bwrap/fetch.json) | [✓](tests/fixtures/policy/policies/docker/fetch.json) |
182
+ | [git](https://github.com/modelcontextprotocol/servers/tree/main/src/git) | `fs:read,write:<repo>`, `exec:spawn:git`, `net:connect:*` | mechanical | — | — | — |
183
+ | [memory](https://github.com/modelcontextprotocol/servers/tree/main/src/memory) | `fs:read,write:$MEMORY_FILE_PATH` | mechanical | — | — | — |
184
+ | [time](https://github.com/modelcontextprotocol/servers/tree/main/src/time) | `fs:read:/usr/share/zoneinfo`, `clock:tzdata` | mechanical | — | — | — |
185
+ | [github](https://github.com/modelcontextprotocol/servers-archived/tree/main/src/github) | `net:connect:api.github.com:443`, `env:inject:GITHUB_PERSONAL_ACCESS_TOKEN` | mechanical | [github.json](tests/fixtures/policy/manifests/github.json) | [✓](tests/fixtures/policy/policies/bwrap/github.json) | [✓](tests/fixtures/policy/policies/docker/github.json) |
186
+ | [postgres](https://github.com/modelcontextprotocol/servers-archived/tree/main/src/postgres) | `net:connect:<db>:<port>`, `assert:postgres.read_only_txn` | mechanical (assert) | — | — | — |
187
+ | [sqlite](https://github.com/modelcontextprotocol/servers-archived/tree/main/src/sqlite) | `fs:read,write:<db_path>` | mechanical | — | — | — |
188
+ | [brave-search](https://github.com/modelcontextprotocol/servers-archived/tree/main/src/brave-search) | `net:connect:api.search.brave.com:443`, `env:inject:BRAVE_API_KEY` | mechanical | — | — | — |
189
+ | [puppeteer](https://github.com/modelcontextprotocol/servers-archived/tree/main/src/puppeteer) | `exec:spawn:chromium?nestedSandbox=true`, `ipc:connect:x11` | nested-sandbox | [puppeteer.json](tests/fixtures/policy/manifests/puppeteer.json) | [✓](tests/fixtures/policy/policies/bwrap/puppeteer.json) | [✓](tests/fixtures/policy/policies/docker/puppeteer.json) |
190
+
191
+ Four of the ten ship as golden-file fixtures for both adapters; the rest follow one of the four shapes and are tracked in `GO_NO_GO.md` for the next grammar review. **MCP server author?** If your server isn't listed and you'd like a fixture review, [open an issue](https://github.com/razukc/capgate/issues/new) with a link to the manifest.
192
+
193
+ ## Capability grammar
194
+
195
+ Capabilities are strings of the form `<kind>:<actions>:<scope>[?refinement=value&...]`.
196
+
197
+ ```
198
+ fs:read,write:/workspace/**
199
+ fs:read:/usr/share/zoneinfo
200
+ net:connect:api.github.com:443
201
+ net:connect:* # any host, any port; implicit blockPrivate=true
202
+ exec:spawn:git
203
+ exec:spawn:chromium?nestedSandbox=true
204
+ env:inject:GITHUB_PAT
205
+ ipc:connect:x11
206
+ clock:tzdata
207
+ assert:postgres.read_only_txn:"all queries run in READ ONLY TRANSACTION"
208
+ ```
209
+
210
+ The grammar rejects ambiguity (relative paths, bad ports, non-UPPER_SNAKE env vars) at parse time — fail-closed, always.
211
+
212
+ ## Scope for v0.1
213
+
214
+ **In scope:**
215
+ - Capability grammar covering `fs`, `net`, `exec`, `env`, `ipc`, `clock`, `assert`.
216
+ - Lowering to `bwrap` (Linux namespace sandbox), `docker` (`docker run` argv), and `egress` (proxy config — `squid` / `nftables`, **shipped**). Worker `resourceLimits` (in-process JS isolation) is the next target.
217
+ - Golden-file tests from real MCP server manifests.
218
+
219
+ **Out of scope (deferred):**
220
+ - Firecracker / microVM adapter — needed for production but not for proving the abstraction.
221
+ - E2B / Daytona / Blaxel adapters — API stability varies; wait for a design partner.
222
+ - seccomp-bpf syscall filters — requires a separate IR; out of the capability model.
223
+ - MCP client/server implementation — this library consumes manifests, it does not speak MCP on the wire.
224
+
225
+ ## Design notes
226
+
227
+ ### Why capabilities are typed and discriminated
228
+
229
+ Early drafts used `{ resource: string; actions: string[]; scope: object }`. That failed the go/no-go test: every adapter had to re-parse `resource` to know what kind of capability it was looking at. The current discriminated union (`kind: 'fs' | 'net' | ...`) makes adapter code a flat switch; no string parsing past the grammar layer.
230
+
231
+ ### Why enforceable vs declared
232
+
233
+ The go/no-go exercise revealed two capabilities that cannot be enforced at the sandbox layer: `fetch`'s RFC1918 block (sandbox can only toggle net on/off) and `postgres`'s read-only transaction guarantee (lives inside the MCP server). Silently dropping them would be a security lie. Promoting them to a first-class `assert:` capability keeps them in the audit trail: adapters emit them as metadata, the host is expected to verify them out-of-band, and the compiler fails compilation if an assertion is unrecognized by any configured validator (deferred to v0.2).
234
+
235
+ ### Why the grammar is string-based
236
+
237
+ JSON-object capabilities are verbose and bury the kind under keys. The string form `fs:read,write:/workspace/**` is one line in a manifest, greps cleanly, and round-trips losslessly through the grammar.
238
+
239
+ ### Why `nestedSandbox` is a refinement, not a kind
240
+
241
+ Chromium carries its own sandbox that fights namespace isolation. Every production sandbox tool has a special case for this. Rather than a new capability kind, `nestedSandbox=true` is a refinement on an existing `exec:` capability — the adapter sees it during lowering and emits a different bwrap profile (user/pid/ipc namespaces kept for inner-sandbox compatibility). The IR stays small; the edge case is explicit and documented.
242
+
243
+ ### Why egress lowers to a proxy config, not a proxy
244
+
245
+ `egress[]` is emitted by the bwrap and docker adapters but enforced by neither — the host is told to wire a proxy. The neither-adapter-can-actually-do-net property is real: bwrap's `--unshare-net` is all-or-nothing (it always isolates now; see the net posture in `bwrap.ts`), and Docker's default bridge NATs but doesn't allowlist. Closing that gap by *running* a proxy would turn capgate into a gateway and drag a long-running, root-adjacent process into a library whose whole value is being a static compiler.
246
+
247
+ The move keeps capgate a compiler: a third lowering target, `lowerToEgress(policy, { target })`, compiles `policy.net` into a config blob for a proxy the host *already runs* — `squid` (allowlist by hostname via CONNECT, no TLS interception) and `nftables` (allowlist by IP+port in-kernel, bypass-proof, plus the `blockPrivate` drops) ship today. Both configs are fail-closed: squid ends in an unconditional `http_access deny all`, nftables defaults to `policy drop`, and an empty `policy.net` compiles to a deny-ALL config. The artifact carries an `unenforceable[]` field naming every declared rule the chosen target *cannot* honor (e.g. nftables can't express `api.github.com` — it filters IPs, not rotating hostnames), so "portable" stays honest: it compiles everywhere and tells you what each backend loses. Envoy/Cloudflare/microVM targets are later entries behind the same `EgressTarget` switch; the IR does not change. This keeps Docker MCP Gateway and Cloudflare as *targets you compile to*, not competitors — the manifest stays the single reviewable source of truth, and enforcement is borrowed, not built.
248
+
249
+ ## Non-goals that matter
250
+
251
+ - **The compiler does not decide trust.** Capability declarations come from the manifest; the compiler does not infer them from tool descriptions. Inference belongs in a separate auditing tool. A manifest that under-declares is a bug in the manifest.
252
+ - **The compiler does not execute.** It emits policy artifacts. Running bwrap, wiring proxies, and spawning Workers is the host's job.
253
+ - **The compiler does not resolve secrets.** `env:inject:GITHUB_PAT` carries the name only. A secret store resolves the value at runtime, outside this library.
254
+
255
+ ## Failure modes
256
+
257
+ - Unknown capability kind → `CompilationError('CAP_UNKNOWN_KIND')`.
258
+ - Capability a configured adapter cannot lower → `CompilationError('ADAPTER_UNSUPPORTED')` *(impl. pending)*.
259
+ - Manifest missing required fields → `CompilationError('MANIFEST_SHAPE')`.
260
+
261
+ All compilation errors are fatal. There is no warning mode.
262
+
263
+ ## Test strategy
264
+
265
+ Golden files. One fixture manifest → one expected policy per adapter. Every PR that changes grammar, IR, or an adapter must update the golden files in the same commit. Reviewers read the diff. This is the primary correctness mechanism; unit tests on the grammar are secondary.
266
+
267
+ ```bash
268
+ npm test # run all tests
269
+ npm run test:update-goldens # regenerate golden files after intentional changes
270
+ ```
271
+
272
+ ## Open questions before v0.1
273
+
274
+ 1. **Egress proxy choice.** mitmproxy (great DX, slow, not prod-grade) vs nftables (hard to author, prod-grade, Linux-only) vs Envoy (prod-grade, ops-heavy). Direction settled: capgate stays a compiler and emits a config blob per target rather than running a proxy — see [Why egress lowers to a proxy config, not a proxy](#why-egress-lowers-to-a-proxy-config-not-a-proxy). Both `squid` and `nftables` now ship as reference bindings (they cover complementary cases — hostname-CONNECT vs in-kernel IP allowlist). Remaining sub-question is whether a dev-only mitmproxy emitter is worth carrying.
275
+ 2. **Path glob semantics.** bwrap binds directories, not globs. A `fs:read:/workspace/**` capability lowers to `--ro-bind /workspace /workspace`, which is a *superset* of the declared scope. Runtime enforcement of globs is an MCP-server concern.
276
+ 3. **Server-level vs tool-level capabilities.** v0.0 unions them. Finer-grained per-tool sandboxing (one sandbox per invocation) is possible but expensive — deferred until a user asks for it.
277
+
278
+ ## Contributing
279
+
280
+ If you have a concrete manifest + unexpected compiler output, file an issue with both. See [CONTRIBUTING.md](CONTRIBUTING.md) for what else is useful.
281
+
282
+ Design-partner stage: if you're already reviewing MCP servers in production and willing to share how your review process works, [issue #1](https://github.com/razukc/capgate/issues/1) has a question for you.
283
+
284
+ ## Security
285
+
286
+ capgate compiles declarations into sandbox policies downstream hosts trust — bugs here can silently over-grant. Please report privately per [SECURITY.md](SECURITY.md).
287
+
288
+ ## License
289
+
290
+ Apache License 2.0 — see [LICENSE](LICENSE) and [NOTICE](NOTICE).
package/dist/cli.js CHANGED
@@ -10,12 +10,13 @@
10
10
  // This is deliberately minimal. Anything fancier (watch mode, multi-target,
11
11
  // YAML output) belongs behind a feature flag, not here.
12
12
  import { readFileSync } from 'node:fs';
13
- import { compile, lowerToBwrap, CompilationError } from './policy/index.js';
13
+ import { compile, lowerToBwrap, lowerToDocker, lowerToEgress, CompilationError } from './policy/index.js';
14
14
  function parseArgs(argv) {
15
15
  const args = {
16
16
  command: undefined,
17
17
  input: undefined,
18
18
  target: 'bwrap',
19
+ egressTarget: 'squid',
19
20
  pretty: false,
20
21
  help: false,
21
22
  };
@@ -28,6 +29,8 @@ function parseArgs(argv) {
28
29
  args.pretty = true;
29
30
  else if (a === '--target')
30
31
  args.target = rest[++i];
32
+ else if (a === '--egress-target')
33
+ args.egressTarget = rest[++i];
31
34
  else if (!args.command)
32
35
  args.command = a;
33
36
  else if (!args.input)
@@ -35,19 +38,21 @@ function parseArgs(argv) {
35
38
  }
36
39
  return args;
37
40
  }
38
- const USAGE = `capgate — compile MCP manifests into sandbox policies
39
-
40
- Usage:
41
- capgate compile <manifest.json|-> [--target bwrap] [--pretty]
42
-
43
- Options:
44
- --target <name> Adapter to lower to. Default: bwrap. Supported: bwrap.
45
- --pretty Indent JSON output with 2 spaces.
46
- -h, --help Show this message.
47
-
48
- Examples:
49
- capgate compile manifests/filesystem.json --pretty
50
- cat manifest.json | capgate compile - --target bwrap
41
+ const USAGE = `capgate — compile MCP manifests into sandbox policies
42
+
43
+ Usage:
44
+ capgate compile <manifest.json|-> [--target bwrap] [--pretty]
45
+
46
+ Options:
47
+ --target <name> Adapter to lower to. Default: bwrap. Supported: bwrap, docker, egress.
48
+ --egress-target <name> Egress backend when --target egress. Default: squid. Supported: squid, nftables.
49
+ --pretty Indent JSON output with 2 spaces.
50
+ -h, --help Show this message.
51
+
52
+ Examples:
53
+ capgate compile manifests/filesystem.json --pretty
54
+ cat manifest.json | capgate compile - --target bwrap
55
+ capgate compile manifests/github.json --target egress --egress-target nftables --pretty
51
56
  `;
52
57
  function readInput(path) {
53
58
  if (path === '-')
@@ -83,8 +88,18 @@ function main() {
83
88
  case 'bwrap':
84
89
  output = lowerToBwrap(policy);
85
90
  break;
91
+ case 'docker':
92
+ output = lowerToDocker(policy);
93
+ break;
94
+ case 'egress':
95
+ if (args.egressTarget !== 'squid' && args.egressTarget !== 'nftables') {
96
+ process.stderr.write(`capgate: unsupported --egress-target "${args.egressTarget}" (supported: squid, nftables)\n`);
97
+ process.exit(2);
98
+ }
99
+ output = lowerToEgress(policy, { target: args.egressTarget });
100
+ break;
86
101
  default:
87
- process.stderr.write(`capgate: unsupported --target "${args.target}" (supported: bwrap)\n`);
102
+ process.stderr.write(`capgate: unsupported --target "${args.target}" (supported: bwrap, docker, egress)\n`);
88
103
  process.exit(2);
89
104
  }
90
105
  const indent = args.pretty ? 2 : 0;
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"bwrap.d.ts","sourceRoot":"","sources":["../../../src/policy/adapters/bwrap.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,MAAM,WAAW,aAAa;IAC5B,0FAA0F;IAC1F,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,oDAAoD;IACpD,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,+EAA+E;IAC/E,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,oEAAoE;IACpE,UAAU,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAClD,6DAA6D;IAC7D,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,yEAAyE;IACzE,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAID,wBAAgB,YAAY,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,GAAE,YAAiB,GAAG,aAAa,CAoH7F"}
1
+ {"version":3,"file":"bwrap.d.ts","sourceRoot":"","sources":["../../../src/policy/adapters/bwrap.ts"],"names":[],"mappings":"AA4BA,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,MAAM,WAAW,aAAa;IAC5B,0FAA0F;IAC1F,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,oDAAoD;IACpD,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,+EAA+E;IAC/E,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,oEAAoE;IACpE,UAAU,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAClD,6DAA6D;IAC7D,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,yEAAyE;IACzE,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAID,wBAAgB,YAAY,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,GAAE,YAAiB,GAAG,aAAa,CAwH7F"}