chainsaw brew

Guard (Install-Time) Updated

Run brew through Chainsaw — refuse disabled formulae, risky casks and unvetted taps at install time

Run brew through Chainsaw — refuse disabled formulae, risky casks and unvetted taps at install time

SubcommandWhat it does
chainsaw brew envFetch your org’s compiled brew.env policy
chainsaw brew inventoryUpload installed homebrew/core formulae to Chainsaw
chainsaw brew [args...]

Run brew with an install-time supply-chain check in front of it.

Guarded: brew install, brew reinstall, brew upgrade (no names = every outdated package, listed with brew outdated --json=v2) and brew bundle (every brew and cask line of the Brewfile: –file, –global, HOMEBREW_BUNDLE_FILE, else ./Brewfile). Anything else delegates immediately.

Formulae: a disabled formula is refused, a deprecated one warns. Signed in, each formula’s current version also goes to your Chainsaw server’s preflight, exactly as chainsaw npm does. Casks: a disabled cask is refused; a deprecated cask, an unpinned download (sha256 :no_check), a vendor installer (.pkg) or Ruby hooks warn; auto-updating apps are noted. Third-party taps (user/tap/name) are refused: nothing upstream vets them. After reviewing one, allow it with chainsaw guard allow homebrew:user/tap/name.

Unlike the other wrappers these checks read formulae.brew.sh — the same API brew itself fetches (CHAINSAW_HOMEBREW_API_URL overrides it). CHAINSAW_OFFLINE=1 skips them. A lookup that fails prints “could not verify” and the install proceeds, like an unreachable server preflight.

Exit codes: 0 when the install proceeds (Chainsaw then returns brew’s own exit code), 1 when Chainsaw refuses.

Subcommands: chainsaw brew env (your org’s brew.env policy) and chainsaw brew inventory (upload what is installed).

To make the check automatic, add the shell shims: eval "$(chainsaw guard init)".

Examples

chainsaw brew install jq
chainsaw brew install --cask firefox
chainsaw brew bundle --file ~/dotfiles/Brewfile
chainsaw brew upgrade

Flags

This command forwards its arguments to the underlying tool unchanged, so it parses no flags of its own. Anything after the command name goes to the wrapped package manager verbatim.

chainsaw brew env

Fetch your org’s compiled brew.env policy

chainsaw brew env [flags]

Fetch the brew.env your Chainsaw server compiles from org policy (forbidden formulae, casks, taps and licences, cask options, bottle routing) and print it.

–write put it in your user brew.env (~/.homebrew/brew.env, or $XDG_CONFIG_HOME/homebrew/brew.env) –system put it in /etc/homebrew/brew.env for every user (run as root; chainsaw never runs sudo itself)

Written as a marked block: every other line in the file is kept, and a re-run replaces the block in place. The response is refused unless every line is a comment, blank, or HOMEBREW_NAME=value — and settings that would make brew run a program (HOMEBREW_*_PATH, EDITOR, BROWSER, CURLRC, git remotes) are refused too. brew applies the file on its next run.

Examples

chainsaw brew env
chainsaw brew env --write
sudo chainsaw brew env --system --repo homebrew

Flags

FlagTypeDefaultDescription
--repostring—Homebrew repository name on the server; unset emits only the deny-lists, with no bottle routing
--systembool—Write to /etc/homebrew/brew.env (requires root)
--writebool—Write to your user brew.env instead of printing

The global flags apply here too.

chainsaw brew inventory

Upload installed homebrew/core formulae to Chainsaw

chainsaw brew inventory [flags]

Run brew info --json=v2 --installed and upload it as a declared target, so installed formulae get CVE alerts. Declared inventory is never presented as observed install traffic.

–file uploads a JSON document saved earlier from the same command (e.g. on a machine without network access). –dry-run reads and counts it and sends nothing.

Exit codes: 0 uploaded (or dry run), 2 brew failed or the upload failed, 3 not signed in, 4 bad flags or not a brew info document.

Examples

chainsaw brew inventory
chainsaw brew inventory --target build-mac-01
brew info --json=v2 --installed > inv.json && chainsaw brew inventory --file inv.json

Flags

FlagTypeDefaultDescription
--dry-runbool—Read and count the inventory; upload nothing
--filestring—Upload this saved brew info --json=v2 --installed output instead of running brew
--targetstring—Target name to record the inventory under (default: this host’s name)

The global flags apply here too.