Skip to content

[Sandbox] brew policy preset cannot bootstrap Homebrew: sandbox lacks filesystem write to /home/linuxbrew #3913

@latenighthackathon

Description

@latenighthackathon

Description

The brew policy preset advertises "Homebrew (Linuxbrew) package manager access" and whitelists the linuxbrew binary paths, but the sandbox cannot actually install Homebrew. Two filesystem constraints in the baseline block the install script:

  1. nemoclaw-blueprint/policies/openclaw-sandbox.yaml sets filesystem_policy.read_write to [/tmp, /dev/null, /sandbox/.openclaw, /sandbox/.nemoclaw] plus the workdir. /home/linuxbrew/ is not on the list, so Landlock denies writes there.
  2. Dockerfile.base runs the sandbox as the unprivileged sandbox user with no sudo (useradd -r -g sandbox -d /sandbox -s /bin/bash sandbox). Homebrew's install script's first step is sudo to create and chown /home/linuxbrew/.linuxbrew, which the sandbox cannot grant.

Result: applying the brew preset, connecting into the sandbox, and running the documented Homebrew bootstrap one-liner fails with:

==> Checking for `sudo` access (which may request your password)...
Insufficient permissions to install Homebrew to "/home/linuxbrew/.linuxbrew" (the default prefix).

Two QA reports already documented the symptom: #1767 (filed 2026-04-10), #3757 (filed 2026-05-18). #3846 is an interim docs-only PR clarifying that users must install Homebrew first, but that PR cannot actually unblock the install because of the filesystem gap.

Why the brew preset is the outlier

Looking at how the other presets actually provision their binaries:

Preset Binary source
npm Node + npm pre-installed via apt in Dockerfile.base
pypi Python + pip pre-installed via apt
huggingface Uses pre-installed Python
github git pre-installed; gh was a phantom and was removed in #3377
local-inference Routes via host gateway, no in-sandbox binary
slack / discord / telegram / wechat / whatsapp Plugins baked into the agent via the plugin system
brew Nothing pre-installed and the sandbox cannot install it

The gh precedent (#3377) shows the project's approach when a preset advertises a tool that isn't actually present: drop the phantom binary from the preset. The WeChat precedent (#3682 in v0.0.46, closing #3677) shows the opposite approach for a tool that should be available: bake it into the sandbox base image.

Proposed fix (Option A): bake Homebrew into the sandbox base image

Follow the #3682 pattern. In Dockerfile.base, after the existing user setup:

USER root
RUN mkdir -p /home/linuxbrew/.linuxbrew/bin \
    && chown -R sandbox:sandbox /home/linuxbrew \
    && gosu sandbox git clone --depth=1 --branch=stable \
        https://github.com/Homebrew/brew \
        /home/linuxbrew/.linuxbrew/Homebrew \
    && ln -s /home/linuxbrew/.linuxbrew/Homebrew/bin/brew \
        /home/linuxbrew/.linuxbrew/bin/brew \
    && gosu sandbox /home/linuxbrew/.linuxbrew/bin/brew --version
USER sandbox

Then add /home/linuxbrew to filesystem_policy.read_write in openclaw-sandbox.yaml so brew can install formulae at runtime under that prefix.

Apply the same change to agents/hermes/Dockerfile.base so Hermes sandboxes get the same behavior.

The image-build path runs as root, so the chown step works. Once the base image is published, every sandbox starts with a working brew under /home/linuxbrew/.linuxbrew/bin/brew, and brew install <package> Just Works after applying the preset.

Cost

Approximately 80 to 150 MB on the base image (Homebrew core, no formulae). Acceptable relative to the existing ~2.4 GB sandbox image and consistent with the WeChat-plugin trade-off the project already accepted.

Alternative (Option B), not recommended

Remove the brew preset entirely (matching the #3377 approach for the gh phantom binary). Cheaper at the image level but a user-visible regression: removes a preset that's currently in the Balanced tier menu, and steers Linux users without .deb packages toward unsupported workarounds.

Acceptance criteria

  • brew --version succeeds inside a freshly-created sandbox with no user setup beyond applying the preset.
  • brew install hello succeeds, downloads the bottle, and prints the install marker.
  • The preset's existing binary whitelist remains correct.
  • E2E smoke test added for the brew bootstrap path.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions