Skip to content

Add brew vulns command#23080

Merged
MikeMcQuaid merged 21 commits into
Homebrew:mainfrom
andrew:vulns-cmd
Jul 14, 2026
Merged

Add brew vulns command#23080
MikeMcQuaid merged 21 commits into
Homebrew:mainfrom
andrew:vulns-cmd

Conversation

@andrew

@andrew andrew commented Jul 13, 2026

Copy link
Copy Markdown
Member

Adds a brew vulns command that checks installed formulae for known security vulnerabilities against the OSV.dev database. This upstreams the scanner from the homebrew-brew-vulns tap so users get vulnerability reporting without installing a separate tap and gem, and so it can read the SBOM data brew already writes into each keg.

Tracking issue with the full rationale and migration plan: Homebrew/homebrew-brew-vulns#111.

With no arguments it scans every installed formula; named formulae, --deps, --brewfile and --eval-all narrow or widen the set. Results are filtered by CVSS severity with --severity and rendered as text or --json. Patches that declare resolves suppress the matching advisories unless --no-ignore-patches is passed (building on #22466).

The layout follows livecheck: a thin cmd/vulns.rb entry point delegating to modules under Library/Homebrew/vulns/ (scanner orchestration, OSV client on Utils::Curl, Vulnerability OSV record wrapper, a strict SemVer 2.0 comparator, a CVSS v3.x/v4.0 base-score calculator, and text/JSON output). No gems are added; the small pieces of purl, vers and cvss-suite that were needed have been reimplemented inline. SARIF and CycloneDX output from the tap version are dropped for now and can come back later as plain JSON serialisation.

Opening as a draft for early feedback on the module layout and CLI surface before polishing docs further.


  • Have you followed our Contributing guidelines?
  • Have you checked for other open Pull Requests for the same change?
  • Have you explained what your changes do? Performance claims (e.g. "this is faster") must include Hyperfine benchmarks.
  • Have you explained why you'd like these changes included, not just what they do?
  • For bug fixes, have you given step-by-step brew commands to reproduce the bug?
  • Have you written new tests (excluding integration tests)? Here's an example.
  • Have you successfully run brew lgtm (style, typechecking and tests) locally?

  • AI was used to generate or assist with generating this PR.

A combo of translation and review from https://github.com/Homebrew/homebrew-brew-vulns with bits of claude and codex


Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new brew vulns command to scan formulae for known vulnerabilities using OSV.dev, reusing SBOM metadata when available and integrating patch resolves suppression into the results.

Changes:

  • Add the brew vulns CLI command with options for scope selection, severity filtering, and JSON/text output.
  • Implement the OSV client, scanning orchestration, SemVer range evaluation, CVSS v3.x severity scoring, and output formatting under Library/Homebrew/vulns/.
  • Add RSpec coverage plus documentation and shell completions/manpage updates for the new command.

Reviewed changes

Copilot reviewed 22 out of 23 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
manpages/brew.1 Adds brew vulns to the generated manpage.
Library/Homebrew/vulns/vulnerability.rb OSV vulnerability record wrapper with severity and version-range evaluation.
Library/Homebrew/vulns/semver.rb SemVer 2.0 comparator used for OSV SEMVER ranges.
Library/Homebrew/vulns/scanner.rb Scanner that derives repo/tag targets (SBOM or formula URL), queries OSV, and applies patch suppression.
Library/Homebrew/vulns/output.rb Text and JSON renderers, including sanitization of OSV-sourced strings.
Library/Homebrew/vulns/osv.rb OSV API client (query batch + per-vuln fetch) using Utils::Curl.
Library/Homebrew/vulns/cvss.rb CVSS v3.0/v3.1 base score + severity bucketing.
Library/Homebrew/vulns.rb Aggregating require entrypoint for the vulns subsystem.
Library/Homebrew/test/vulns/vulnerability_spec.rb Unit tests for OSV record parsing, severity extraction, and range matching.
Library/Homebrew/test/vulns/semver_spec.rb Unit tests for SemVer parsing/comparison behavior.
Library/Homebrew/test/vulns/scanner_spec.rb Scanner tests covering targeting, OSV interaction, filtering, and patch suppression.
Library/Homebrew/test/vulns/output_spec.rb Output formatting tests for both text and JSON formats.
Library/Homebrew/test/vulns/osv_spec.rb OSV client tests including pagination and error handling.
Library/Homebrew/test/vulns/cvss_spec.rb CVSS scoring and severity bucketing tests.
Library/Homebrew/test/support/fixtures/vulns/sbom.spdx.json SBOM fixture for extracting source URL/tag data.
Library/Homebrew/test/cmd/vulns_spec.rb Command-level tests for arg validation, output mode, and failure behavior.
Library/Homebrew/sorbet/rbi/dsl/homebrew/cmd/vulns.rbi Tapioca-generated RBI for Homebrew::Cmd::Vulns args accessors.
Library/Homebrew/cmd/vulns.rb Implements the new brew vulns command and option handling.
docs/Manpage.md Adds user-facing documentation for brew vulns.
completions/zsh/_brew Adds zsh completion entries for brew vulns.
completions/internal_commands_list.txt Registers vulns as an internal command for completion generation.
completions/fish/brew.fish Adds fish completion entries for brew vulns.
completions/bash/brew Adds bash completion entries for brew vulns.
Files not reviewed (1)
  • Library/Homebrew/sorbet/rbi/dsl/homebrew/cmd/vulns.rbi: File type not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Library/Homebrew/vulns/semver.rb

@MikeMcQuaid MikeMcQuaid left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good so far! Very close to mergeable as-is honestly.

Comment thread Library/Homebrew/cmd/vulns.rb Outdated
Comment thread Library/Homebrew/cmd/vulns.rb Outdated
Comment thread Library/Homebrew/cmd/vulns.rb Outdated
Comment thread Library/Homebrew/cmd/vulns.rb Outdated
Comment thread Library/Homebrew/vulns/semver.rb
@andrew andrew marked this pull request as ready for review July 13, 2026 21:48
Comment thread Library/Homebrew/vulns/scanner.rb
Comment thread Library/Homebrew/cmd/vulns.rb Outdated
andrew added 3 commits July 13, 2026 17:04
Restores the optional-argument form from the tap so `brew vulns --brewfile`
defaults to ./Brewfile (or HOMEBREW_BUNDLE_FILE). `--brewfile=<path>` still
selects a specific file; the bare/empty value is normalised to nil for
Bundle::Brewfile.read.
Widen repo_url to also consider the formula homepage, fall back to
stable.specs[:tag] then the stable version string when no tag can be
extracted from the source URL, and read the SBOM versionInfo alongside
downloadLocation. This recovers coverage for formulae like curl, git,
node and libssh2 whose stable URL is not a supported forge archive.
@andrew andrew requested a review from p-linnane July 14, 2026 00:11

@p-linnane p-linnane left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. The Brewfile, tag/version, and SBOM versionInfo fixes look good and cover the packages that matter (curl, node, rust, ruby, git, and libssh2 all scan now). One tap fallback is still missing: repo_url returns nil unless a URL is on GitHub, GitLab, or Codeberg, so the verbatim (source_url if @stable_tag) || head_url path is gone. That still skips 7 installed formulae here (bash, gmp, gnu-tar, go, make, openconnect, and zsh), each with a non-forge head. It's low priority, since OSV's GIT ecosystem returns nothing for those hosts today, so this is parity and future-proofing rather than a real detection loss. If you restore it, a non-forge-head fixture would cover the path. Not blocking though.

@MikeMcQuaid MikeMcQuaid left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@MikeMcQuaid MikeMcQuaid added this pull request to the merge queue Jul 14, 2026
Merged via the queue into Homebrew:main with commit 0022e7f Jul 14, 2026
41 checks passed
andrew added a commit to Homebrew/homebrew-brew-vulns that referenced this pull request Jul 14, 2026
--eval-all was removed during review of Homebrew/brew#23080 in favour
of the brew-wide tap trust mechanism.
pull Bot pushed a commit to specialized806/brew that referenced this pull request Jul 14, 2026
repo_url only normalises GitHub, GitLab and Codeberg, so formulae whose
stable, head and homepage URLs are all hosted elsewhere (bash, gmp,
gnu-tar, go, make, openconnect, zsh) were skipped outright. Restore the
tap's last-resort fallback: query OSV with the source URL verbatim when
its path yielded a tag, otherwise the head URL verbatim. OSV's GIT
ecosystem returns nothing for these hosts today, so this is parity with
the tap and future-proofing rather than a detection change.

Follow-up to Homebrew#23080.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants