Skip to content

Secure Visual Studio Code

Visual Studio Code behaves more like a browser than a normal CLI. The desktop app can open marketplace, sync, account, update, and GitHub endpoints. Extensions can also make network requests and spawn local commands.

The built-in vscode profile is a compatibility profile for that shape. It wraps the code launcher with a per-run shim, keeps the VS Code process attached to firma run, and routes cooperative HTTP traffic through the Sidecar.

ConcernBehavior
Launch commandSupports firma run --profile vscode -- code .
Process lifetimeForces --wait and --new-window through a runtime code shim
VS Code statePersists user-data and extensions under .firma/vscode/
Desktop runtimeUses a writable per-run XDG_RUNTIME_DIR for VS Code IPC
Chromium inner sandboxDisabled because firma run provides the outer sandbox boundary
GitHub sign-inPrefers VS Code’s device-code flow inside the isolated profile
MappingCONNECT rules for VS Code, marketplace, accounts, and GitHub sign-in
Sandbox CA trust storesystem roots + firma-ca (AppendSystemRoots)

The shim is created inside the per-run runtime directory. It is not installed globally, does not replace /usr/bin/code, and only affects the current firma run session.

VS Code user data and installed extensions persist next to the resolved config under .firma/vscode/user-data and .firma/vscode/extensions. The per-run runtime directory is still used for the shim, desktop IPC files, and other process-local state.

Terminal window
firma config --profile vscode --posture dev

This selects the vscode mapping. The mapping is CONNECT-level in v1: VS Code core services, marketplace hosts, Settings Sync, and Microsoft and GitHub account or repository flows are classified as communication.external.send. That includes GitHub.com, hosted GitHub Enterprise (*.ghe.com), and the Google and Apple identity-provider hosts GitHub can use during sign-in. Add the matching extra mapping when you want an embedded agent, such as Copilot, OpenAI/Codex, or Anthropic/Claude.

Terminal window
firma run --config .firma/firma.toml --profile vscode -- code .

firma run -- code . also auto-selects the vscode profile because code is an alias for the profile. Passing --profile vscode keeps scripts explicit.

The profile rejects VS Code arguments that would bypass the managed runtime state, including --reuse-window, --user-data-dir, and --extensions-dir. Use the default command shape above unless you are deliberately testing launch behavior.

GitHub sign-in uses VS Code’s device-code flow by default inside the isolated profile. This avoids browser callback paths that can break across the sandbox network namespace while still supporting GitHub.com, hosted GitHub Enterprise, and GitHub social sign-in through Google or Apple.

To reset the isolated VS Code profile for a project, remove the project-local state directory:

Terminal window
rm -rf .firma/vscode

This does not remove the host VS Code profile under ~/.config/Code or host extensions under ~/.vscode/extensions.

  • Project-local state. Accounts, extensions, Settings Sync state, and extension installs live under .firma/vscode for the resolved config. The state is intentionally separate from the host VS Code profile.
  • Linux desktop integration. The profile passes through display-related environment, creates a writable per-run desktop runtime directory, and links the host Wayland and D-Bus sockets into it when present. This keeps VS Code’s own IPC files writable without making the host runtime directory writable.
  • Chromium sandboxing. The shim adds --no-sandbox for VS Code’s inner Chromium sandbox on Linux. The bwrap backend remains the sandbox boundary.
  • Extensions are broad. Extensions run with VS Code’s permissions. Their network traffic is only covered when it uses the sandboxed process and reaches hosts covered by the mapping, extra selected mappings, or your added rules.
  • Idle adapter relays are closed. On Linux bwrap, idle sandbox-to-Sidecar adapter relays are closed after two minutes so browser-style keep-alive sockets do not exhaust the local bridge during extension installs.
  • Integrated terminal commands are not governed in v1. Network egress from terminal commands is still constrained by the backend boundary. Per-command local-exec decisions for integrated terminals depend on the separate command interception work.
  • Linux bwrap is the validated path. macOS vz and Windows/WSL2 wsl2 remain proxy-only compatibility backends unless you opt into a structural mode documented in Wrap an agent with firma run.