Default PATH behavior is inconsistent across Linux and macOS backends
- Dominant language
- Rust
- Stars
- 1.3k
- Forks
- 79
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 117
Description
### Relevant area(s)
Linux, macOS
### Brief description of your issue
The non-Windows containment backends do not share a documented contract for the default `PATH` supplied to sandboxed workloads. This issue is split from #1102 after PR #1120 aligned the Windows ProcessContainer environment behavior.
Current behavior still differs by backend:
| Backend | `process.env` omitted | `process.env` set, no `PATH=` |
|---|---|---|
| Seatbelt (macOS) | `/usr/bin:/bin:/usr/sbin:/sbin` | same default |
| LXC (Linux) | inherits host `PATH` | liblxc default `/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin` |
| Bubblewrap (Linux) | no `PATH` supplied by MXC | no `PATH` supplied by MXC |
Bubblewrap clears the environment without restoring `PATH`, so command resolution falls back to the shell's distro-specific compiled default. This has produced different results between Debian/Ubuntu and RHEL. LXC also changes its `PATH` behavior when an unrelated environment variable is added because a non-empty `process.env` switches it from inherited environment behavior to liblxc's cleared-environment default. Seatbelt supplies a stable default, but that contract is not shared or documented across the non-Windows backends.
### Steps to reproduce
1. Build MXC on Linux or macOS.
2. Run a config that prints `PATH` and resolves a command normally found under `sbin`, with `process.env` omitted.
3. Add an unrelated variable such as `"env": ["FOO=bar"]` and run the same config again.
4. Compare Bubblewrap and LXC on Debian/Ubuntu and RHEL, and compare Seatbelt on macOS.
Example process configuration:
```json
"process": {
"commandLine": "bash -c 'echo \"PATH=[${PATH-}]\"; command -v iptables || echo NO_IPTABLES'"
}
```
### Expected behavior
Linux and macOS backends follow a single documented default-environment contract. Adding an unrelated environment variable does not unexpectedly change command resolution.
### Actual behavior
Bubblewrap can leave `PATH` unset, LXC switches between the host path and liblxc's default based on whether `process.env` is non-empty, and Seatbelt applies a separate fixed default. Command resolution therefore varies by backend and host distribution.
Additional context: nightly run [33731889129](https://github.com/microsoft/mxc/actions/runs/33731889129) failed on RHEL 10 while the Debian/Ubuntu Bubblewrap jobs passed because their shell fallback paths included `sbin`.
Contributor guide
Assessment
This issue has not been assessed yet.