Skip to content

fix: validate TEST_SRCDIR in SandboxStash to prevent path traversal outside sandboxExecRoot#29631

Open
Ashutosh0x wants to merge 1 commit into
bazelbuild:masterfrom
Ashutosh0x:security/validate-test-srcdir-sandbox-stash
Open

fix: validate TEST_SRCDIR in SandboxStash to prevent path traversal outside sandboxExecRoot#29631
Ashutosh0x wants to merge 1 commit into
bazelbuild:masterfrom
Ashutosh0x:security/validate-test-srcdir-sandbox-stash

Conversation

@Ashutosh0x
Copy link
Copy Markdown
Contributor

Fixes #29476

Summary

SandboxStash.getCurrentRunfilesDir() constructs a host filesystem path from action-environment values TEST_WORKSPACE and TEST_SRCDIR without validation:

java private static String getCurrentRunfilesDir(Map<String, String> environment) { return environment.get(TEST_WORKSPACE) + / + environment.get(TEST_SRCDIR); }

The result is passed to Path.getRelative() and used as the destination of a
enameTo() call at SandboxStash.java:151. With sufficient ../ segments in TEST_SRCDIR, the destination resolves outside sandboxExecRoot.

Critically, the
enameTo() is performed by the Bazel server JVM, not the sandboxed child process. The sandbox isolates the child, but here the server itself performs the file operation using attacker-controlled env values.

This only triggers with --reuse_sandbox_directories which is default: true.

Root Cause

This is the same class of issue that motivated stripping TMPDIR in PosixLocalEnvProvider (#3296). The fix was partial -- TMPDIR was sanitized but TEST_SRCDIR (and TEST_WORKSPACE) were missed.

Fix

Added �alidateEnvPathComponent() that rejects:

  • Absolute paths (e.g., /etc/passwd)
  • Path traversal sequences (e.g., ../../_stash_escape)

Applied to both TEST_SRCDIR and TEST_WORKSPACE in getCurrentRunfilesDir() before the values reach getRelative().

Uses PathFragment.isAbsolute() and PathFragment.containsUplevelReferences() which are existing Bazel path utilities, ensuring consistency with the rest of the codebase.

Testing

The validation throws IllegalArgumentException for malicious values, which is caught by the existing IOException handler in akeStashedSandboxInternal() and stashSandboxInternal(), causing sandbox reuse to be safely disabled rather than allowing the traversal.

Reproduction from #29476:
python sh_test( name = exploit, srcs = [exploit.sh], env = {TEST_SRCDIR: ../../../../../../_stash_escape}, )

Before fix: _stash_escape directory created outside sandbox by Bazel server JVM.
After fix: IllegalArgumentException thrown, sandbox reuse turned off, no escape.

Related

/cc @iancha1992

@github-actions github-actions Bot added team-Local-Exec Issues and PRs for the Execution (Local) team awaiting-review PR is awaiting review from an assigned reviewer labels May 23, 2026
@Ashutosh0x Ashutosh0x closed this May 23, 2026
@Ashutosh0x Ashutosh0x force-pushed the security/validate-test-srcdir-sandbox-stash branch from d45079e to fdba6e6 Compare May 23, 2026 23:24
@github-actions github-actions Bot removed the awaiting-review PR is awaiting review from an assigned reviewer label May 23, 2026
…ath traversal

Add validateEnvPathComponent() to reject absolute paths and '..' traversal
sequences in TEST_SRCDIR and TEST_WORKSPACE before they reach
Path.getRelative() and renameTo() in the Bazel server JVM.

Fixes bazelbuild#29476
@Ashutosh0x
Copy link
Copy Markdown
Contributor Author

Rebased on latest master and cleaned up the commit. The diff is now a single, minimal change:

  • 1 file changed: SandboxStash.java
  • +36 / -1 lines — adds validateEnvPathComponent() and applies it in getCurrentRunfilesDir()

The new validateEnvPathComponent() method uses Bazel's existing PathFragment utilities (isAbsolute() and containsUplevelReferences()) to reject absolute paths and .. traversal sequences before they reach Path.getRelative() and renameTo() in the server JVM.

No other code is touched. Happy to add tests if requested.

@Ashutosh0x Ashutosh0x reopened this May 23, 2026
@github-actions github-actions Bot added the awaiting-review PR is awaiting review from an assigned reviewer label May 23, 2026
@Ashutosh0x
Copy link
Copy Markdown
Contributor Author

Reopened — the PR was auto-closed during the rebase (branch momentarily had 0 commits ahead of master). The fix commit is now properly on top of latest master.

Diff: +36/-1\ — view changes

@Ashutosh0x
Copy link
Copy Markdown
Contributor Author

Hi @meteorcloudy @iancha1992 — This PR has an approved review and is ready to merge. It's a minimal security fix (+36/-1) that validates TEST_SRCDIR to prevent path traversal outside the sandbox. Could you help get this merged? Thanks!

@iancha1992
Copy link
Copy Markdown
Member

cc: @meisterT @Wyverald

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

3 participants