Skip to content

fix: use lstat() in CreateTarget to prevent symlink traversal outside sandbox_root#29645

Open
Ashutosh0x wants to merge 1 commit into
bazelbuild:masterfrom
Ashutosh0x:security/no-symlink-follow-sandbox-root
Open

fix: use lstat() in CreateTarget to prevent symlink traversal outside sandbox_root#29645
Ashutosh0x wants to merge 1 commit into
bazelbuild:masterfrom
Ashutosh0x:security/no-symlink-follow-sandbox-root

Conversation

@Ashutosh0x
Copy link
Copy Markdown
Contributor

Fixes #28515

Summary

CreateTarget() in linux-sandbox-pid1.cc uses stat() to check whether a path already exists before creating mount targets under sandbox_root. Since stat() follows symlinks, a pre-seeded symlink under sandbox_root causes subsequent mkdir()/link() calls to operate on the host filesystem outside sandbox_root.

This is a robustness/hardening issue: hermetic sandbox setup code runs before pivot_root/chroot and performs host filesystem operations. If sandbox_root/<component> is unexpectedly a symlink, mount target creation can write outside the intended sandbox directory.

Root Cause

// BEFORE (vulnerable): stat() follows symlinks
if (stat(path, &sb) == 0) {
    // sb reflects the TARGET of any symlink, not the symlink itself
    // mkdir/link will operate at the symlink target (outside sandbox_root)
}

Fix

Two changes to CreateTarget():

  1. Replaced stat() with lstat() -- lstat() does not follow symlinks, so it reports the symlink itself rather than its target.

  2. Added explicit symlink rejection -- if lstat() detects a symlink (S_ISLNK), CreateTarget() now returns -1 with errno = ELOOP, preventing any further operations on the path.

// AFTER (safe): lstat() does not follow symlinks
if (lstat(path, &sb) == 0) {
    if (S_ISLNK(sb.st_mode)) {
        // Reject symlinks: following them could escape the sandbox root.
        errno = ELOOP;
        return -1;
    }
    // ... normal directory/file handling
}

Reproduction (from #28515)

proof_root="$(mktemp -d)"
sandbox_root="$proof_root/sandbox"
outside_root="$proof_root/outside"
mkdir -p "$sandbox_root"
ln -s "$outside_root" "$sandbox_root/mnt"
# Run linux-sandbox with hermetic mode -- CreateTarget will follow the symlink
# Before fix: "$outside_root/<something>" gets created on the host
# After fix: CreateTarget returns ELOOP, mount setup fails safely

Related

/cc @meisterT

@github-actions github-actions Bot added the awaiting-review PR is awaiting review from an assigned reviewer label May 26, 2026
@iancha1992 iancha1992 added the team-Local-Exec Issues and PRs for the Execution (Local) team label May 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting-review PR is awaiting review from an assigned reviewer team-Local-Exec Issues and PRs for the Execution (Local) team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

hermetic linux-sandbox: mount target creation can follow pre-seeded symlinks under sandbox_root and create host paths outside sandbox_root

2 participants