bug(docker): snapshots of gVisor (runsc) sandboxes silently drop all writes under runsc's default --overlay2=root:self

Author: DrejTCreated Sep 13, 2026Updated Sep 18, 2026

What happened

Forking a child from a live Docker-backed sandbox can come back missing files that exist on the parent's live filesystem at fork time — in our repro, a globally npm install -g'd CLI binary. The snapshot/commit and the resulting fork both report success; nothing surfaces the missing files anywhere.

Repro (no OpenSandbox code involved — bare docker commit)

bash
docker exec <container> npm install -g <pkg>
docker exec <container> which <pkg-bin>        # present, works

docker commit <container> test-image
docker run --rm test-image which <pkg-bin>     # ABSENT

This reproduces on a single, solo commit — no concurrent commit anywhere near it, no retries, nothing racing. We confirmed via Alineo.spawn()/fork(), which calls POST /v1/sandboxes/{id}/snapshots and restores from it, and independently via a bare docker commit of the same container outside any OpenSandbox code path — same result both times.

Ruled out:

  • Hardlinks — every file under the missing package's tree has a link count of 1.
  • A separate mount/volumedocker inspect --format '{{json .Mounts}}' is [], .Config.Volumes is null, and the missing directory's device number matches every other directory under the same parent path (including a sibling package directory that does survive the commit).
  • Concurrency — reproduces on a solo commit with nothing else in flight. (We originally suspected two simultaneous fork() calls against one sandbox as the trigger — see "Related" — but the same corruption occurs with only ever one commit in flight, so that wasn't it.)

Environment

Docker runtime, overlayfs storage driver, kernel 6.19.14-108.fc42.x86_64 (Fedora 42), execd_image v1.0.19/v1.0.22, runsc (gVisor) as the sandbox's own container runtime.

Impact

Any workflow that installs something into a sandbox and then forks it (e.g. alineo's RLM fan-out, where a parent installs a CLI/dependency once and forks multiple children from it) can silently produce children missing that install, with no error at any layer — the fork, the snapshot, and the restore all report success.

Related

Also worth closing regardless of the above: the Docker runtime's createSnapshot() has no concurrency guard — two simultaneous POST .../snapshots against the same sandbox are both accepted, unlike the Kubernetes runtime, which explicitly rejects a second in-flight snapshot per sandbox with 409. Not the cause of the corruption described above (confirmed reproducible on a solo commit), but a separate, real gap in its own right — worth the same protection either way.

Source: opensandbox-group/OpenSandbox