Sandboxing runs each build action in a directory that holds only its declared inputs, so a tool cannot quietly read other files. Without it, Bazel cannot see undeclared inputs, may treat stale outputs as current, and can store wrong results in a shared cache that every developer then reuses.
What the sandbox does
Bazel builds an execroot directory for each action. It contains the action's input files and acts as the working directory. Bazel then uses an operating system technique, containers on Linux and sandbox-exec on macOS, to constrain the action within it. Compilers and other tools do not see source files they should not access, unless they know absolute paths.
Two honest limits from the documentation: sandboxing does not hide the host environment, and processes can still read files elsewhere on the file system. On platforms with user namespaces, though, they cannot modify files outside the working directory.
Why that matters for supply chain integrity
The Bazel documentation gives the reasoning plainly.
- Undeclared inputs break correctness. If a tool reads a file that is not listed as an input, then a change to that file does not trigger a rebuild. Bazel believes the output is current.
- Bad cache entries spread. An incorrect entry in a shared cache affects every developer, and wiping the cache is not a feasible routine fix.
- It predicts remote execution. If a build works under sandboxing, it will likely work under remote execution, where only declared files are uploaded.
From a security view, hidden inputs are hidden risk. A file your build reads but your inventory does not list cannot be scanned, reviewed or pinned.
How to use it
| Goal | Step |
|---|---|
| Find hidden dependencies | Enable the sandboxed strategy and fix breakages |
| Keep it consistent | Set it in the shared rc file, not on one laptop |
| Check CI matches local | Run the same sandbox settings in CI |
| Catch leftovers | Build in a bare container with only the source tree |
When a build breaks after you turn sandboxing on, the failure message usually names a file the action tried to read. Declare it as an input, or remove the dependency on it.
What sandboxing does not do
It is not a malware sandbox. An action that is allowed to run can still run hostile code from a hostile dependency within its declared files. Think of it as a correctness control that has security side effects, not a containment boundary for untrusted code.
Pairing it with other controls
- Keep the remote cache write path narrow, as covered in the post on who may write to it.
- Pin tools inside the workspace. Bazel's caching page notes it does not track tools outside the workspace, so two users with different compilers at the same path can share wrong hits.
- Keep environment variables out of actions unless explicitly allowed with the action environment flag.
Where Safeguard fits
Safeguard can inventory the dependencies your repository declares through SBOM and dependency scanning, and reachability analysis helps you decide which findings matter first. You can try a free scan on a repository to see what it finds. Check coverage for your specific build files before relying on it.
Quick check
Is the Bazel sandbox a security boundary against malicious code?
No. It restricts file access to keep builds correct. Do not rely on it to contain an untrusted dependency.
What is an undeclared input?
A file an action reads that is not listed in the action's dependencies. Bazel cannot know to rebuild when it changes.
Sources
Last reviewed: 19 October 2026.