Skip to main content

Security Model

Gig'MCP's threat model in one line: the gateway is trusted infrastructure; MCP servers are untrusted; the kernel (namespaces, seccomp) is the boundary between them; keys live only on the trusted side.

This page summarizes the threat model and the design decisions recorded in the gateway repo's DESIGN.md. The mechanisms themselves are detailed in Sandbox Isolation, Egress Proxy & Credential Injection, and Vault & Encryption.

The problem

Today, every MCP server you install holds your raw API keys and has unrestricted network and filesystem access. One malicious or compromised server — a typosquatted npm package, a poisoned update, a prompt-injected tool — can read every credential in its environment and send it anywhere.

Gig'MCP's answer: run anyone's server; the sandbox and the proxy make trust unnecessary.

Trust boundaries

TrustedUntrusted
The gateway binary (router, supervisor, proxy, vault, auth)All community MCP server code running in sandboxes
cmd/bootstrap — the in-sandbox init that configures networking, then drops all privileges before execing the serverAnything the server does after exec: its syscalls, its network traffic, its filesystem reads
The Linux kernel (namespaces, seccomp-BPF)
The signed registry index (ed25519-verified before parsing) and digest-pinned OCI imagesThe server author's source repository (the digest pin means "what was approved is what runs")
Your Docker Compose environment and GIG_MASTER_KEY

Attacker capabilities considered

A malicious MCP server is assumed to be able to:

  • Execute arbitrary code inside its sandbox.
  • Read its entire environment and filesystem view.
  • Make arbitrary network connections to any address, with any protocol, ignoring HTTPS_PROXY and any other environment-level guidance.
  • Attempt namespace escapes (unshare, setns, clone(CLONE_NEWUSER), clone3), mounts, ptrace, kernel key/BPF/module syscalls.
  • Lie in its MCP responses (prompt injection of the calling model is a client-side concern, out of scope here).

What it cannot do, by construction:

  • Read your real credentials. Tier 1 ("sealed") sandboxes contain only a high-entropy placeholder; the real key exists only in the gateway's vault and is injected at the proxy.
  • Reach non-allowlisted hosts. The sandbox's only route is the proxy; the proxy rejects CONNECTs to hosts outside the manifest's egress allowlist.
  • Impersonate another tenant. Identity is the connection's source IP, and the netns can only source addresses from its own /30 — the gateway allocated it.
  • See the host. Fresh mount, PID, user, net, IPC, UTS, and cgroup namespaces; cleared environment; read-only binds of exactly the files it was granted; private procfs.

The 20 design decisions

The full table is in DESIGN.md §2. The ones that matter most for security:

#DecisionSecurity consequence
3No Docker socket. The gateway spawns servers as bwrap child processes inside its own container. Egress networking is validated with NET_ADMIN only — no SYS_ADMIN, no privileged mode.A sandbox escape does not hand the attacker the Docker daemon (which is root on the host). The server process runs as uid 65534 with zero capabilities — verified by tests.
5Shared code/image, never shared process: one sandboxed instance per (server × user/profile).No cross-tenant state inside a server process.
6Tiered credential model (see below).Default tier keeps keys out of the sandbox entirely.
7Entitlements are author-declared, PR-gated into the registry, enforced as a hard cap by the proxy. Lint CI blocks bare wildcards and known exfiltration domains. Manifest changes on update force re-consent.The egress allowlist cannot silently widen.
8Registry CI compiles manifests into a signed index.json; the gateway verifies the ed25519 signature over the raw bytes before parsing anything.A compromised CDN or repo cannot feed the gateway a tampered catalog.
9OCI images pinned by digest in the manifest. The gateway pulls, re-verifies the digest of what actually arrived, then extracts.What was reviewed is byte-for-byte what runs.
11One MCP endpoint per profile with per-profile bearer tokens; manifests mark tools default: true/false.Least-privilege tool exposure per client.
13Embedded, hand-rolled CONNECT MITM proxy; identity binding is network-level (source IP per netns); allowlist checked at CONNECT time before a TLS leaf is minted; route isolation — not environment variables — is the enforcement.Env-only proxying was proven bypassable and rejected; the per-request audit log falls out of the IP→identity lookup for free.
15Envelope encryption for the vault: per-secret DEKs under XChaCha20-Poly1305, wrapped by a master KEK from GIG_MASTER_KEY. The KEK is never stored in the database.A database dump without the KEK is useless.
18The Go gateway is the sole auth authority (generic OIDC client today; local email+password login is part of the decision but not yet implemented). The Next.js dashboard never owns sessions.One audited code path for authentication.
20Impersonation is config-only: an admin can see a user's view but cannot execute tools or touch secrets. Time-boxed, banner-visible, loudly audited. (Not currently implemented.)Admin compromise does not become credential compromise.

The remaining decisions (deployment shape, storage drivers, license, frontend, multi-user) are operational; see DESIGN.md for the complete record.

Tier 1 vs Tier 2: sealed and entrusted

Each server manifest declares a tier:

  • Tier 1 — sealed (default). The sandbox environment contains only a placeholder token. The egress proxy swaps it for the real key on allowlisted HTTPS calls. The key never enters the sandbox, so even total compromise of the server code cannot exfiltrate it.
  • Tier 2 — entrusted. The real secret goes into the sandbox environment. This exists for credentials the proxy cannot inject — database connection strings, certificate-pinned clients. The egress allowlist still applies, but a Tier 2 server can exfiltrate its own secret through an allowed domain (e.g., write it into a GitHub gist if github.com is allowlisted). The tier label surfaces this trade-off at install time.
  • Tier 3 — local-resource servers are out of scope. The catalog targets SaaS APIs (Slack, GitHub, Google, Ubiquiti, …).
warning

Tier 2 weakens the core guarantee for that one credential. Prefer Tier 1 servers, and treat a Tier 2 install as "this server can read this secret."

Residual and accepted risks

These are documented in DESIGN.md §3 and deliberately accepted:

  • Tier 2 self-exfiltration through allowed domains, as above.
  • Shared-kernel isolation. All sandboxes share the host kernel; a kernel 0-day breaks tenant separation. Acceptable for self-hosting and a curated catalog; gVisor/microVMs would be revisited if hosting truly hostile workloads.
  • Docker-level seccomp=unconfined is currently required so bwrap can create unprivileged user namespaces. Compensating control: an application-level seccomp-BPF filter installed inside every sandbox closes the nested-userns escape and other escalation vectors (see Sandbox Isolation). A scoped custom Docker seccomp profile is a follow-up hardening item that has not shipped.
  • Compose environment variables are visible via docker inspect. A *_FILE Docker-secret variant exists for the OIDC client secret; extending it to the other sensitive values (including GIG_MASTER_KEY) is planned but not yet wired.

What's shipped vs planned

Honest status as of this writing:

  • Shipped: bwrap sandboxing with full namespace isolation, the egress proxy with source-IP identity binding and Tier 1 injection, the envelope-encrypted vault, signed-index verification, digest-pinned OCI pulls, the scoped in-sandbox seccomp filter, the iptables FORWARD DROP belt-and-suspenders.
  • Planned/deferred: Landlock filesystem rules and cgroup resource limits per sandbox (the hardening plan), a full allowlist-style seccomp profile, a custom Docker seccomp profile replacing seccomp=unconfined, the idle-reaping policy, Tier 2 env injection flow, local email+password login, and config-only impersonation. Registry image digests are placeholders pending the build pipeline.