Huny's Dev Blog
huny.dev

Docker Sandboxes sbx cp Vulnerability (CVE-2026-103916): How Parent Symlinks Bypass Agent Isolation and What v0.51.0 Fixes

Examine how CVE-2026-103916 lets sandboxed AI agents read or overwrite host files via sbx cp symlinks, why leaf-only -L checks fail on parent directories, and how to verify the v0.51.0 patch.

Hun Jang
Hun Jang Nov 5, 2026

A conceptual illustration showing the v0.51.0 path-confinement shield blocking parent-symlink escapes over the upper sbx cp copy channel, alongside the lower allowlisted virtio-fs workspace channel. This is not an actual tool screenshot.

A high-severity vulnerability in Docker Sandboxes (sbx CLI)—CVE-2026-103916 (CVSS 3.1 8.2 High, CWE-59)—allows an AI coding agent such as Claude Code, OpenAI Codex, or Gemini CLI running inside an isolated sandbox to read or overwrite arbitrary files on the developer's host machine by planting a symbolic link inside its approved workspace and waiting for a routine sbx cp command. Alongside a separate host Git configuration execution flaw (CVE-2026-121614, fixed in v0.50.0), Docker shipped the complete fix for CVE-2026-103916 in Docker Sandboxes v0.51.0 on November 3, 2026.

The key operational takeaway: even when a microVM's virtio-fs mount enforces a strict folder allowlist, host-side file transfer commands like sbx cp operate as a second channel with the operator's full host permissions. Because an earlier patch attempt targeted for v0.48.0 (October 13, 2026) proved incomplete, every user on versions 0.28.0 through 0.50.x must upgrade to v0.51.0 or later—and never rely solely on leaf-level symlink checks (such as -L) when copying files into or out of an agent-writable workspace.

This article synthesizes the technical disclosure by Peyton Kennedy at Endor Labs, the official CVE-2026-103916 record, and the ACN security advisory. It does not execute exploits against vulnerable sbx binaries; the local Python checks below verify parent- versus leaf-component symlink confinement logic in a temporary directory.

1. Why the microVM Allowlist Did Not Stop sbx cp

Docker Sandboxes isolates AI coding agents inside a lightweight virtual machine (microVM) with its own Linux kernel, filesystem, and Docker daemon. Developers grant the sandbox access only to specific project directories shared into the guest via virtio-fs. Inside the microVM, even mounting the entire virtio-fs share as root cannot reach host files outside the approved allowlist.

The vulnerability exists because sbx cp moves bytes through a separate channel that bypassed the allowlist entirely.

Dimension
Channel 1: virtio-fs Shared Workspace
Channel 2: sbx cp Host Transfer CLI (v0.28.0 – v0.50.x)
Execution Context & Privileges
Enforced by the microVM boundary; guest processes cannot traverse outside shared mounts
Executed on the host OS by the sbx CLI process running with the developer's full user permissions
Allowlist Enforcement
Strictly governed by the workspace allowlist
Allowlist not consulted. The host CLI resolves symlinks on the host filesystem and reads or writes the resolved target
How a Planted Symlink Behaves
A symlink inside the workspace pointing to /Users/me/.ssh dangles harmlessly inside the guest VM because the target path does not exist there
When the operator runs sbx cp on the host, the host CLI follows the symlink on the host filesystem where /Users/me/.ssh does exist
Operator Visibility
sbx mount prints Mounted NOTION_MARKDOWN_ESCAPED_LT_SENTINELresolved> at NOTION_MARKDOWN_ESCAPED_LT_SENTINELtarget>, exposing unexpected targets
sbx cp exits 0 with no output and does not print the resolved host path, hiding the redirection from the operator

Because the shared workspace is mounted read-write, a prompt-injected agent can replace any workspace subdirectory with a symlink pointing to a sensitive host location, then suggest a normal-looking sbx cp command to export build results or import a file.

An earlier vulnerability, CVE-2026-17106 (fixed in v0.38.0), prevented archive entries from escaping relative to the extraction root during copy-out. However, it did not validate the extraction root itself or intermediate parent directories on copy-in.

As documented in the Endor Labs research, a symlink in an sbx cp host path can occupy four distinct positions, and the CLI's -L flag guarded only one of them:

Symlink Position
Direction & Example
Followed by Default?
Gated by -L Flag?
Security Impact (CVE-2026-103916)
1. Copy-out destination, last component (leaf)
Sandbox → Host copy where the target folder or file is a symlink (e.g., work/results → ~/.ssh)
Yes
No (-L is irrelevant on destinations)
Arbitrary host file write/overwrite. Can overwrite ~/.zshrc, ~/.gitconfig, ~/.ssh/authorized_keys, or .git/hooks in any existing directory
2. Copy-out destination, parent component
Sandbox → Host copy where an ancestor directory of the target is a symlink (e.g., work/out/sub/file where work/out is a link)
Yes
No
Arbitrary host file write/overwrite into any existing host directory tree
3. Copy-in source, last component (leaf)
Host → Sandbox copy where the final filename itself is a symlink (e.g., work/leaf.txt → ~/secret/notes.txt)
No
Yes (followed only when -L is passed)
The only position properly guarded by default; without -L, the link is copied as a dangling symlink into the guest
4. Copy-in source, parent component
Host → Sandbox copy where a parent folder is a symlink (e.g., work/vendor → ~/.aws, copying work/vendor/credentials)
Yes
No (followed even without -L)
Arbitrary host file read into the sandbox. Because the final component (credentials) is a regular file, the CLI follows the parent symlink and copies the host file into the guest

Furthermore, when a copy-in operation using a parent symlink fails because the destination directory inside the sandbox does not exist, the CLI error message (Can't add file /Users/me/... to tar) leaks the resolved host path.

Multiple security updates landed across Docker Sandboxes, Buildx, and Docker Desktop in early November 2026. Distinguish the exact version thresholds below:

Identifier & Component
Affected Versions
Fixed Version
Summary & Operational Note
CVE-2026-103916
(Docker Sandboxes sbx cp)
0.28.0 through NOTION_MARKDOWN_ESCAPED_LT_SENTINEL 0.51.0
0.51.0 (Released Nov 3, 2026)
Host-side path symlink escape in sbx cp (CWE-59). An initial fix planned for 0.48.0 on Oct 13, 2026 was incomplete; verify that binaries are on 0.51.0 or newer
CVE-2026-121614
(Docker Sandboxes Git Config)
0.31.0 through NOTION_MARKDOWN_ESCAPED_LT_SENTINEL 0.50.0
0.50.0
Improper neutralization of repository-controlled Git configuration when running host-side Git commands in direct-mode sandboxes with read-write mounts (CWE-15)
Docker Buildx & Docker Desktop
(Concurrent advisories)
Buildx 0.21.0 to NOTION_MARKDOWN_ESCAPED_LT_SENTINEL 0.37.2
Desktop NOTION_MARKDOWN_ESCAPED_LT_SENTINEL 4.98.0
Buildx 0.37.2
Desktop 4.98.0
Included in the early November 2026 Docker security advisories; update alongside the standalone sbx CLI

4. Verifying Component-by-Component Path Confinement in Python

To see why checking only the final filename (os.path.islink(path)) fails against parent-directory symlinks—and how host-side file utilities should validate paths before copying—consider the dependency-free Python script below.

It contrasts a naive leaf-only check against a component-walking validator that inspects every prefix under workspace_root and verifies that os.path.realpath stays confined inside the workspace.

Scope Verified Locally

Running this script in a local Linux Python environment confirmed three test cases:

  1. Leaf symlink (work/leaf.txt): Blocked by both the leaf-only check and the component-walking validator (leaf_symlink_blocked:leaf.txt).
  1. Parent directory symlink (work/vendor/notes.txt): Passed right through naive_leaf_only_check() because notes.txt is a regular file, whereas verify_workspace_confinement() caught the intermediate symlink at vendor (parent_symlink_detected:vendor).
  1. Normal workspace subdirectory (work/artifacts/build.log): Allowed cleanly (confined:...).

In production Go or C/Rust CLI tools, path validation should also eliminate time-of-check to time-of-use (TOCTOU) races by combining confinement libraries such as cyphar/filepath-securejoin or openat2(..., RESOLVE_NO_SYMLINKS | RESOLVE_BENEATH) at file-open time.

5. Practical Remediation Checklist

  • Upgrade Docker Sandboxes to v0.51.0 or later immediately: Run sbx version and ensure your installation is on 0.51.0+ (do not stop at 0.48.0 or 0.50.0).
  • Inspect realpath and scan for symlinks before copying: If you must run sbx cp against a workspace path before upgrading—or when reviewing a copy command suggested by an agent—verify the canonical path and check for planted symlinks first:
  • Stage host copies outside the shared workspace: When transferring files between host and sandbox via sbx cp, use a dedicated host staging folder that has never been mounted into the sandbox rather than copying directly into or out of the agent-writable workspace tree.
  • Audit .git/config and hooks in shared repositories: In light of CVE-2026-121614, inspect .git/config (such as core.pager, core.fsmonitor, or core.sshCommand) and .git/hooks/ before running host-side Git commands on a repository mounted read-write into an agent sandbox.

References

Last verified: November 5, 2026

Korean version: Docker Sandboxes sbx cp 취약점(CVE-2026-103916) 해부: AI 에이전트의 심볼릭 링크 탈출과 v0.51.0 점검하기Docker Sandboxes sbx cp 취약점(CVE-2026-103916) 해부: AI 에이전트의 심볼릭 링크 탈출과 v0.51.0 점검하기

추천 글