| Run model | Language servers run | Extensions run | Extension tech | Everything in container? | Other security-relevant notes |
|---|---|---|---|---|---|
| Plain Zed on host | Host (native binary, spawned with user privileges) | Host (in WASM sandbox via wasmtime); spawning of LSP/native binaries prompts user | WASM (Component Model + WIT), Rust-compiled | No — GUI + LSPs touch host filesystem and creds | Curated extension registry; smaller ecosystem (less to vet); pure Rust core (no V8/Node); GPL-licensed; auto-update behavior depends on settings |
| Plain Lapce on host | Host (native binary) | Host (in WASM sandbox via wasmtime, WASI Preview 1) | WASI WASM (Rust, C, AssemblyScript) | No | Smallest plugin ecosystem (least attack surface, but also least battle-testing); small team / slow security response; pre-1.0; Apache 2.0; no formal marketplace moderation |
| Plain VSCode on host | Host (separate Node.js or native process, user privileges) | Host (Node.js extension host, full user privileges) | Node.js / npm | No | Largest attack surface in 2025-2026: GlassWorm worm, prettier-vscode-plus → OctoRAT, 105+ malicious extensions detected in 2025; leaked publisher tokens enable supply chain pushes; auto-update on by default; Electron/V8/Node memory-corruption surface; trusts MS marketplace |
| code-server in Docker (browser UI) | Container (Node process) | Container (Node.js extension host inside container) | Node.js / npm | Yes — everything is in the container, browser is just the UI | Strongest containment: a malicious extension can only see what's in the container, not your host SSH keys or AWS creds. But: Microsoft Marketplace ToS forbids non-MS clients → forced to Open VSX (which had its own GlassWorm/namespace-squat incidents); needs reverse-proxy + auth in front (it's a web server); browser keyboard-shortcut friction; Coder-maintained, not Microsoft |
| VSCode browser (vscode.dev) | None for most languages (browser-only) | Browser sandbox (very restricted) | JS in browser sandbox | N/A (no container, no real backend) | Browser sandbox is the tightest extension model that exists; but the editor is also the most limited — no terminal, no real LSP, no debugging. Useful for quick edits, not daily dev |
| Zed + Dev Containers | Container (zed-remote server spawns them inside) | Host (WASM sandbox) — extensions are not yet container-aware | WASM | Partial — LSPs/terminal/code-exec in container; extensions still on host | The split is well-architected: container does heavy lifting, host runs GUI + sandboxed extensions. Per Zed docs: host extensions are used as-is, no separate per-container management yet. Works via docker exec transport. Requires docker binary (symlink Podman). Newer feature (v0.218, Jan 2026), still evolving |
| Lapce + remote dev to container | Container (lapce-proxy) | Container (lapce-proxy hosts the WASM sandbox there) | WASI WASM | Yes for the dev surface; GUI stays on host | Cleanest of the "split" models from a containment standpoint — extensions and LSPs both inside the container. Friction: requires sshd inside container (extra moving part, key management, doesn't fit ephemeral spawn-per-request well) |
| VSCode + Dev Containers (Remote-Containers) | Container (vscode-server spawns inside) | Container for "workspace" extensions; host for "UI" extensions | Node.js / npm | Yes for the dev surface (workspace extensions); host runs UI extensions + the proprietary Remote-Containers extension | Best containment story VSCode offers: a malicious workspace extension is bounded by the container. But: still Node-based extensions (no sandbox within the container); Remote-Containers extension itself is Microsoft-proprietary; auto-update can still poison your install base; you trust the container's contents (image supply chain becomes the new attack surface) |
| VSCode Remote-SSH to remote host | Remote host | Remote host (Node.js, full user privs there) | Node.js / npm | No (unless the remote is a container, e.g. via docker exec provider) |
Moves blast radius from your laptop to the remote box. Useful if the remote is more disposable than your laptop, worse if it's a shared production-adjacent server |
Helix in container over docker exec |
Container | No extensions (Helix has none) | N/A | Yes | Maximum minimalism: zero extension marketplace, zero supply chain. Modal terminal editor in Rust. Trade-off: no GUI, no plugin ecosystem at all. Genuinely the lowest-risk option |
Neovim in container over docker exec |
Container | Container | Lua (no sandbox), but plugins are typically git-pinned by user, not from a marketplace | Yes | Plugins run with user (container) privileges and have no sandbox, but the install model is "git clone a specific commit" rather than "auto-updating marketplace" — different threat model, mostly without the marketplace supply-chain attack vector |
The matrix really has two axes that matter to you: where the extension code executes (host vs container = blast radius) and what isolation the extension runs under (full Node privileges vs WASM sandbox = what it can do inside that blast radius).
Best of both: extension in a sandbox and in a container. That's Lapce + remote-dev-to-container or code-server in Docker, depending on whether you weight the WASM sandbox (Lapce) or the all-in-one container story (code-server) more heavily. For your spawn-per-request agent setup, Lapce's sshd requirement is annoying enough that Zed + Dev Containers is probably the pragmatic winner — extensions run client-side but in a WASM sandbox, and everything you actually care about isolating (code execution, LSPs, terminal) is in the container.
The one row that's genuinely best on pure security is Helix in a container — no extensions means no extension supply chain — but you give up the GUI and the ecosystem, which is a big ask if you're used to VSCode-style workflows.