Years ago I wrote a tool called Brewdler that brought Bundler-style dependency management to Homebrew. You could list your packages in a Brewfile and run a single command to install them. Homebrew eventually absorbed it as brew bundle, and it’s now the standard way to manage reproducible macOS environments.
Homebrew is everywhere now. It ships preinstalled on every GitHub Actions macOS and Ubuntu runner. It’s the default way to install development tools on macOS, and it’s growing on Linux too.
Most package managers have security tooling built around them. Bundler has bundle audit. npm has npm audit. Cargo has cargo audit. These tools check your installed packages against vulnerability databases and tell you what needs updating. That tooling exists because these ecosystems plug into GitHub’s dependency graph. Security advisories flow through Dependabot. The whole supply chain security stack treats them as first-class citizens.
Homebrew hasn’t had that yet. There’s no brew audit for CVEs, no dependency graph integration, no automatic security alerts when a formula you have installed gets a disclosed vulnerability.
So I built brew-vulns, a Homebrew subcommand that scans your installed packages for CVEs. Install it via gem install brew-vulns or through Homebrew itself.
$ brew vulns
Scanning 127 installed formulae...
Querying OSV for vulnerabilities...
node (22.11.0) - 2 vulnerabilities:
[HIGH] CVE-2025-23083 - Diagnostics Channel 'net' Events...
[MEDIUM] CVE-2025-23085 - Memory leak in HTTP/2 session...
openssl@3 (3.4.0) - 1 vulnerability:
[MEDIUM] CVE-2024-13176 - Timing side channel in ECDSA...
Found 3 vulnerabilities in 2 packages
It queries the OSV database, the same source Dependabot and other security tools use. For each installed formula, it looks up the source repository and version, then checks for any disclosed vulnerabilities affecting that version. It works for packages hosted on GitHub, GitLab, or Codeberg.
You can scan a specific formula, include its dependencies with --deps, or point it at a Brewfile with --brewfile. There’s a --severity flag to filter by severity level, and output formats for CI: --json, --sarif for GitHub code scanning, and --cyclonedx for SBOM generation.
The SARIF output works with GitHub’s code scanning. You can add a workflow that runs brew vulns --sarif and uploads the results, and vulnerabilities will show up in the Security tab alongside your other scanning alerts. zizmor was a big inspiration here. It does static analysis on GitHub Actions workflows and has the same integration points: text output for local use, SARIF for code scanning, JSON for scripting. That pattern of meeting developers where they already have security tooling set up is worth copying.
- name: Scan Homebrew packages
run: brew vulns --sarif > brew-vulns.sarif
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: brew-vulns.sarif
The CycloneDX output generates an SBOM with vulnerability information embedded. You can submit that to GitHub’s dependency graph API or feed it into other tooling. Homebrew packages should show up in the same places your npm and gem dependencies already appear.
I wrote before about GitHub Actions as a package manager. Those runners come with Homebrew and dozens of formulas preinstalled. If you’re thinking about your CI supply chain, system packages are part of the attack surface too. Homebrew did have lockfile support for a while. Running brew bundle would generate a Brewfile.lock.json recording exact versions. That was removed in November 2024 because it didn’t get the adoption the maintainers hoped for. Maybe the timing was off; lockfiles are most useful when there’s tooling that consumes them.
There are gaps. I can only query packages whose source lives on a supported forge, and only if the version tag follows a recognizable pattern. Some formulas install from tarballs with URLs that don’t map cleanly to a repository. But for packages with GitHub-hosted sources and standard versioning, which is most of what Homebrew installs, it works.
I’m also adding similar vulnerability commands to git-pkgs, which will let you query vulnerability history across your dependency graph over time: when a vulnerable package was introduced, how long it was present, who fixed it. Both tools share the same foundation: the Ruby implementations of supply chain security specs I’ve been building over the past year. purl for package identifiers, vers for version range matching, sbom for CycloneDX generation, sarif for code scanning output. Homebrew is too widely used to be invisible to security tooling.
gem install brew-vulns / github.com/andrew/brew-vulns