Homebrew Supply Chain Risks on macOS Developer Fleets
Homebrew is the default package manager on developer Macs, yet most fleet visibility tools and EDRs provide little structured insight into taps, formulae, casks, and unrequested installs. Here is what actually lands on disk and how to monitor it continuously with fleet rules.
- homebrew
- macos
- supply-chain
- fleet-rules
- fleet
Homebrew is the default way developers install tools on macOS. It powers compilers, runtimes, databases, and utilities that never appear in MDM inventories or typical EDR process logs.
Security and platform teams often discover the gap only after an incident: a third-party tap introduced vulnerable or malicious code, an agent pulled in an unrequested dependency, or a cask installed something that persisted on disk long after the demo.
The visibility problem
Most existing controls were not designed for this surface:
- MDM profiles and app catalogs see managed software. They do not parse Homebrew receipts or the Cellar.
- EDR agents watch execution and network. They rarely maintain a clean, diffable inventory of which formulae and casks actually resolved on each Mac.
- Periodic vulnerability scans or SBOMs run at build or registry time. They miss what a developer or coding agent installed directly on a workstation between scans.
The result is the same pattern seen with npm lockfiles and MCP configs: risky changes land on disk outside any PR or central review.
What actually creates supply chain risk in Homebrew
Several characteristics make Homebrew a first-class concern for developer fleets:
- Third-party taps come from arbitrary GitHub repositories. There is no equivalent to the review process for
homebrew/coreorhomebrew/cask. - Formulae and casks can execute code during install or build. Even without obvious preinstall scripts, the build system and upstream tarballs introduce risk.
- Unrequested installs happen constantly. A direct
brew installfor one tool can pull in a tree of supporting packages that stay on the machine. - Receipts and the Cellar contain the ground truth of what is present, including versions and origins that drift over time.
- Agents and humans both use the same command. A background process or coding agent can add packages the same way a person does.
These are not theoretical. Past supply chain events have shown that low-level tools pulled via package managers on developer machines become persistence or credential targets.
What Koban records for the homebrew surface
Koban reads Homebrew state from known paths on disk, including receipts and metadata. For each item it captures:
- name and version
- origin (the tap, such as
homebrew/core,homebrew/cask, or a third-party tap) - installedOnRequest flag (true when the user or script explicitly requested it, false for automatic dependencies)
- other provenance details where available
The agent snapshots this inventory on a configurable schedule and on file changes. It diffs against the previous snapshot and evaluates rules locally before any data leaves the Mac.
This is the same artifact-focused approach used for lockfiles and AI client configs. The goal is simple: answer whether something new, unexpected, or known-bad appeared since the last heartbeat.
Practical fleet rules for Homebrew
Fleet rules run on the agent against the structured inventory. You write them in YAML using a closed vocabulary. Rules can trigger on added, modified, removed, or present (the last one is useful for catching software that was already installed when the rule was published).
Here are the patterns teams use most often for Homebrew.
Flag packages from untrusted taps
- id: homebrew.untrusted-tap
surface: homebrew
triggers: [added, modified, present]
match: fieldNotInList
field: origin
allowed: [homebrew/core, homebrew/cask]
severity: notable
title: Third-party tap
rationale: Package came from a Homebrew tap outside the official core and cask repos.This rule uses present so it also surfaces existing installs when the rule first reaches a Mac.
Surface unrequested dependency installs
- id: homebrew.unrequested-install
surface: homebrew
triggers: [added]
match: flagEquals
flag: installedOnRequest
expected: false
severity: info
title: Pulled in as a dependency
rationale: Package was installed automatically as a dependency, not requested by the user.Info severity keeps noise low while still giving visibility into what accumulated on machines.
Known compromised or high-risk packages
- id: homebrew.ioc.compromised-copilot-for-xcode
surface: homebrew
triggers: [added, modified, present]
match: fieldContainsAny
field: name
values: [copilot-for-xcode]
severity: critical
title: Compromised Homebrew package
rationale: Package matches a published compromise indicator and should be reviewed.You can extend the values list with any indicators relevant to your environment.
Default rules and baselines
Koban ships built-in rules that cover common cases, including the untrusted tap check and several suspicious command patterns that apply across surfaces. Most teams start with the defaults (or the baseline production configuration in the docs) and add or tighten rules for their specific risk tolerance.
Full rule reference and more examples live in the fleet rules documentation.
How this fits the rest of the stack
Homebrew monitoring is deliberately narrow and complementary:
- It does not block installs or require kernel entitlements.
- It does not replace MDM for profile and app management.
- It does not duplicate EDR process or network telemetry.
It adds the missing artifact layer for the developer toolchain: a continuous, diffable view of what actually resolved into the Cellar and caskroom on each Mac, evaluated against your policies before findings leave the device.
When a finding appears in Fleet or routes to Slack or your SIEM, you see the Mac, the exact package, the tap or origin, the path on disk, and which rule matched. That is usually enough to start an investigation or update a baseline.
Practitioner takeaway
If your engineers rely on Homebrew (and almost all macOS developer fleets do), treat it as a supply chain surface worth instrumenting. The installs that matter are the ones that land on disk and stay there, whether they came through a PR, an agent, or a quick brew install to unblock work.
Koban gives you that inventory and the ability to write simple, auditable rules against it. The agent is free and open source. Fleet adds the enrollment, policy distribution, and alerting layer.
Start with the default rules, enable the homebrew surface if it is not already on, and add the untrusted tap and unrequested install checks. You will see what your fleet is actually running in the places traditional controls leave dark.
For the complete rule vocabulary and configuration examples, see the fleet rules documentation.
Questions about a specific pattern or how to combine Homebrew rules with your existing npm or MCP policies? The docs and the rule examples in recent incident posts are the best place to begin.