Skip to content

Sandbox security

The sandbox exists to run code you do not trust, so what it trusts is the whole question. This page summarises the sandbox’s posture and points at the authority; the book’s Security page is that authority, and it covers the desktop application, not this service. For this service, see Security.

The trust boundary is the CPU, not any software inside the guest. KVM (or Hypervisor.framework), the host kernel, and the host-side process acting as the virtual machine monitor are trusted. Everything inside the guest, including the in-guest agent, is not — a hostile guest controlling that agent is assumed, and only effects that cross the boundary count.

It follows that a sandbox with no explicit configuration shares no host directory and reaches no network, and that what is shared is the policy, settled before the VM starts and printed where you can read it.

The monitor process is one trusted component with a large surface, and two flags widen it:

  • --display loads virglrenderer and Mesa into the monitor and opens the host GPU’s render node, so guest-controlled data reaches a renderer running with your privileges. A headless VM opens neither. This is surface the feature costs, not a capability the sandbox grants: without --gpu, nothing in the guest gets acceleration.
  • --gpu widens it further and differently. A display’s guest data reaches the renderer as pixels to decode; a --gpu guest is handed the 3D submission path, so untrusted code composes commands a renderer executes with your privileges. That is why it is a toggle: off by default, printed in the posture, refused where libkrun lacks the feature.

The book’s Architecture page carries the measurement behind both statements, with the host and the date it was taken on.

The sandbox boots guests, so there is something there to attack. The host-side decoders of the guest’s wire protocol are fuzzed, from a committed corpus, with a smoke lane in its CI.

What has not happened: any external review, any audit, any release. There is one maintainer. Until the first supported release (v0.1.0), every version is a development snapshot, no version receives backported fixes, and nothing there should be treated as production-ready. Its security page states the posture the code is written to; it is not evidence the code achieves it.

Worth reporting:

  • A guest reaching the host filesystem, network, or another sandbox outside what was configured.
  • A hostile guest causing a host panic, hang, or resource leak through the supervisor. The host path is written against a no-panic rule.
  • Injected secrets — environment values, injected file contents — appearing in logs, errors, or the console.

Not a bug there, so reports stay signal:

  • Anything that starts from a compromised host. The host kernel, the hypervisor and the process’s own uid are trusted.
  • Hosts below the supported floor, including an unpatched host kernel. Patching the substrate is the operator’s half of the contract.
  • The caller harming the caller. The person running the sandbox is trusted; policy binds the guest. Pointing it at a bad image, or exhausting your own machine, is misuse rather than a vulnerability.
  • A guest burning its own budget. Resource pressure inside the configured limits is the containment working.
  • Dependency advisories with no path through the code, unless untrusted guest input can actually reach the vulnerable code.

Because the sandbox is an application rather than a platform, multi-tenant concerns it deliberately does not own are not bugs there.

A sandbox vulnerability goes to the sandbox project privately, through GitHub’s security advisories: the Security tab, or the reporting form directly. Please do not open a public issue for a suspected vulnerability. There is no bounty, and acknowledgement is a maintainer’s, within about a week.

A vulnerability in this service — the console, the API, your account — goes to us instead, at the address on the Security page.