Allow binding sockets in the macOS sandbox when networking is blocked (https://github.com/bazelbuild/bazel/pull/30865)

### Description

The macOS sandbox denied `bind()` outright when network access was blocked, so any action that starts a local server failed under `--experimental_sandbox_default_allow_network=false` or the `block-network` tag. This adds three rules to the generated SBPL profile: binding to any local address, and Unix domain sockets in both directions. Servers commonly bind the wildcard address (`0.0.0.0` or `::`), which the `localhost` filter does not match, which is why the bind rule is unrestricted.

Outbound traffic stays restricted to loopback, so a blocked spawn still cannot reach another host: connecting to the default gateway and to a public address both fail with `EPERM`, while loopback and the machine's own addresses succeed.

One limitation is worth flagging for review and is documented in the code. Inbound traffic cannot be constrained the same way, because macOS decides `network-inbound` from the local address alone, and its `localhost` filter matches *every* address assigned to the machine rather than just `127.0.0.1` and `::1`. Filtering `network-inbound` on the remote address is not an option either: such a rule compiles but has no effect, confirmed by placing `(deny network-inbound (remote ip "*:*"))` last in the profile and observing that accepts still succeed, whereas the same rule keyed on the local address breaks listening. A peer elsewhere on the network can therefore reach a spawn that listens on a non-loopback address. The Linux sandbox does not have this gap because its network namespace only ever has a loopback interface. Closing it would mean disallowing the wildcard bind, which is the bug this PR fixes.

The remaining commits are test-only.

The new coverage is added as integration tests rather than as assertions on the generated profile text, since exercising real binds through the sandbox is what actually establishes that the profile works, and it runs on Linux as well. `DarwinSandboxedSpawnRunnerTest` is left untouched.

The networking integration test gains cases for binding to `127.0.0.1`, `::1`, `localhost`, a Unix socket, and a non-loopback address of the machine, plus a check that blocked spawns cannot reach a non-loopback address. Where the expected outcome genuinely differs per platform it is asserted either way rather than skipped, so no case is silently dropped on either OS.

`--sandbox_fake_hostname` is only implemented by the linux-sandbox and is silently accepted elsewhere. That test previously returned early outside Linux; it now runs the same test with and without the flag and asserts that the hostname becomes `localhost` on Linux and is unchanged everywhere else.

`testing_server.py` retried every bind failure with a new port forever, which would hang a caller waiting for the `started` line if the address could never be bound. It now only retries on `EADDRINUSE`.

### Motivation

Fixes #14828.

### Build API Changes

No

### Checklist

- [x] I have added tests for the new use cases (if any).
- [ ] I have updated the documentation (if applicable).

### Release Notes

RELNOTES: The macOS sandbox now allows actions to bind sockets when network access is blocked, matching the behavior of the Linux sandbox. Note that macOS cannot restrict inbound connections by peer, so an action that listens on a non-loopback address is reachable from other hosts on the network; outbound traffic remains restricted to loopback.

Closes #30865.

PiperOrigin-RevId: 972401681
Change-Id: Ibe06f9a541e75d1e59c905523c4d1ce029e71395
3 files changed
tree: 9776fde0392b596f9eba1afdc4da933d8962d440
  1. .bazelci/
  2. .devcontainer/
  3. .gemini/
  4. .github/
  5. docs/
  6. examples/
  7. scripts/
  8. site/
  9. src/
  10. third_party/
  11. tools/
  12. .bazelrc
  13. .bazelversion
  14. .gitattributes
  15. .gitignore
  16. AGENTS.md
  17. AUTHORS
  18. bazel_downloader.cfg
  19. BUILD
  20. CHANGELOG.md
  21. CODE_OF_CONDUCT.md
  22. CODEOWNERS
  23. combine_distfiles.py
  24. combine_distfiles_to_tar.sh
  25. compile.sh
  26. CONTRIBUTING.md
  27. CONTRIBUTORS
  28. distdir.bzl
  29. extensions.bzl
  30. LICENSE
  31. maven_install.json
  32. MODULE.bazel
  33. MODULE.bazel.lock
  34. oneversion_allowlist.csv
  35. oneversion_allowlist_for_tests.csv
  36. pyproject.toml
  37. README.md
  38. repositories.bzl
  39. requirements.txt
  40. SECURITY.md
README.md

Bazel

{Fast, Correct} - Choose two

Build and test software of any size, quickly and reliably.

  • Speed up your builds and tests: Bazel rebuilds only what is necessary. With advanced local and distributed caching, optimized dependency analysis and parallel execution, you get fast and incremental builds.

  • One tool, multiple languages: Build and test Java, C++, Android, iOS, Go, and a wide variety of other language platforms. Bazel runs on Windows, macOS, and Linux.

  • Scalable: Bazel helps you scale your organization, codebase, and continuous integration solution. It handles codebases of any size, in multiple repositories or a huge monorepo.

  • Extensible to your needs: Easily add support for new languages and platforms with Bazel's familiar extension language. Share and re-use language rules written by the growing Bazel community.

Getting Started

Documentation

Reporting a Vulnerability

To report a security issue, please email security@bazel.build with a description of the issue, the steps you took to create the issue, affected versions, and, if known, mitigations for the issue. Our vulnerability management team will respond within 3 working days of your email. If the issue is confirmed as a vulnerability, we will open a Security Advisory. This project follows a 90 day disclosure timeline.

Contributing to Bazel

See CONTRIBUTING.md

Build status