Commit Graph
47 Commits
Author SHA1 Message Date
Andrew NesbittandGitHub 6bd951d96e Merge pull request #23115 from Homebrew/vulns-osv-export-archaeology
generate-vulns-advisories: derive initial fixed via FormulaVersions
2026-07-14 22:39:17 +00:00
Andrew Nesbitt 4130be563c generate-vulns-advisories: derive initial fixed via FormulaVersions
For records with no existing file, walk homebrew-core git history
(newest-first) via FormulaVersions and use the pkg_version at the oldest
revision where the CVE still appears in resolved_ids as the `fixed`
boundary, instead of the current pkg_version. Existing records preserve
their on-disk ranges (per the merge behaviour in the previous commit),
so this only fires once per newly-annotated (formula, CVE) pair.

The FormulaVersions instance and its rev_list output are cached per
formula so subsequent CVEs for the same formula reuse the ~90s
path-filtered git rev-list and per-revision formula loads. OsvExport.run
now runs inside the SimulateSystem block so historical loads are
runner-OS-independent. Historical revisions are evaluated under the base
simulation only; a resolves inside on_linux/on_intel falls through to
the current pkg_version (documented; no such annotation exists in core
today).

Spot-checked against real homebrew-core: unzip CVE-2014-8139 -> 6.0_6
(current is 6.0_8), CVE-2022-0529 -> 6.0_8; libquicktime CVE-2016-2399
-> 1.2.4_5 (the resolves-added-later case; hand-correct to _4).
2026-07-14 14:09:30 -07:00
Andrew NesbittandGitHub 945b48cb9f Merge pull request #23112 from Homebrew/vulns-osv-export-merge
vulns/osv_export: merge into existing records instead of overwriting
2026-07-14 20:49:07 +00:00
Andrew NesbittandGitHub 70c621ff71 Merge branch 'main' into vulns-osv-export-merge 2026-07-14 12:38:48 -07:00
Andrew Nesbitt bea143bf74 vulns/osv_export: backfill published from modified; drop T.cast
When migrating a record written before `published` existed, fall back to
its `modified` timestamp rather than today's so first-rewrite doesn't
jump the publication date forward.

Narrow the upstream cache value with `is_a?(Hash)` at the call site
instead of `T.cast`, and collapse the failed-fetch guard to a single
`next if` now that reassignment isn't needed.
2026-07-14 12:37:18 -07:00
Andrew Nesbitt 8f9122b974 vulns/osv_export: merge into existing records instead of overwriting
Records now carry `published` and `database_specific: {source:
"generated"}`. `.run` reads any existing `<id>.json`, preserves its
`published` timestamp and `affected[].ranges` (so the `fixed` boundary
reflects when the annotation was first observed rather than drifting to
the current pkg_version), and only writes when the remaining content has
changed. Records for annotations no longer in core are simply not
visited, so they persist on the default branch.

A transient OSV.dev failure leaves an existing enriched record untouched
rather than stripping its summary/severity/references. The unchanged
comparison uses parsed hashes so key ordering in a hand-formatted
existing file does not cause spurious rewrites.
2026-07-14 12:23:19 -07:00
Andrew Nesbitt 714494585b vulns/osv_export: link OSV schema and tighten patch_ref return type
Add a pointer to ossf.github.io/osv-schema above SCHEMA_VERSION and note
where the Homebrew ecosystem/prefix were registered. patch_ref now
returns T::Hash[Symbol, T.any(String, T::Array[String])] via a PatchRef
alias; the input side stays T.untyped to match Formula#serialized_patches.
2026-07-14 10:20:00 -07:00
Andrew NesbittandGitHub c0966f6ddb Merge pull request #23103 from andrew/vulns-non-forge-head
vulns/scanner: fall back to verbatim head URL for non-forge repos
2026-07-14 16:57:02 +00:00
Andrew NesbittandGitHub a9f6cad1ad Merge branch 'main' into vulns-osv-export 2026-07-14 09:56:36 -07:00
Andrew Nesbitt d4470b95a2 vulns/osv_export: memoize upstream fetch per vuln id
When multiple formulae resolve the same CVE, fetch it from OSV.dev once
per run rather than once per (formula, id) pair. Uses Hash#fetch with a
block so a nil (fetch-failed) result is also cached.
2026-07-14 09:52:52 -07:00
Andrew NesbittandGitHub c78d1a43fa Merge branch 'main' into vulns-non-forge-head 2026-07-14 09:38:07 -07:00
Andrew Nesbitt d09f70139c dev-cmd/generate-vulns-advisories: entry point for OsvExport
Replaces the tap's brew-vulns --osv-export DIR with a hidden dev-cmd
following the generate-formula-api pattern. Iterates homebrew/core under
with_no_api_env + SimulateSystem, unions each formula's serialized_patches
across all OS/arch variations from to_hash_with_variations so
platform-gated resolves annotations are not silently dropped, and hands
[formula, patches] pairs to Homebrew::Vulns::OsvExport.

--dry-run lists record ids without writing or querying OSV.dev.
Consumed by Homebrew/homebrew-advisory-database's regenerate workflow.
2026-07-14 09:35:34 -07:00
Andrew Nesbitt aa746060d6 vulns: add OsvExport for Homebrew-ecosystem OSV records
Ports the OSV record exporter from Homebrew/homebrew-brew-vulns. Emits
one BREW-<formula>-<CVE> record per security id declared in a formula's
patch resolves list, under the registered Homebrew ecosystem with
pkg:brew purls, marking the currently shipped pkg_version as the fixed
boundary. Upstream summary/severity/references are copied from OSV.dev
where available.

This is the generator for Homebrew/homebrew-advisory-database; the
dev-cmd entry point follows in the next commit.
2026-07-14 09:35:34 -07:00
Andrew Nesbitt 22d03a1650 vulns/scanner: hoist stable repo_url/tag derivation
Compute stable_repo_url and stable_tag once at the top of build_target
and reuse them in both the installed and non-installed branches, rather
than repeating the same target_repo_url/tag chain twice.
2026-07-14 09:17:11 -07:00
Andrew NesbittandGitHub 19a23e1f3d Merge pull request #23104 from andrew/deps-brewfile
cmd/deps: accept --brewfile as an input source
2026-07-14 16:05:16 +00:00
Andrew Nesbitt 4b423089c6 cmd/deps: merge --brewfile inputs with named arguments
Previously --brewfile silently replaced any named arguments; combine
them instead so `brew deps foo --brewfile` includes foo alongside the
Brewfile entries, and dedupe the merged list.
2026-07-14 07:48:07 -07:00
Andrew Nesbitt 1d4cad75a4 Extract target_repo_url and cover the SBOM fallback path
Move the verbatim source/head URL fallback into a Scanner.target_repo_url
class method so build_target's three call sites share one implementation
written in the ||= style suggested in review, and add a spec for the
installed-keg SBOM branch where the SBOM downloadLocation host is not a
supported forge.
2026-07-14 07:30:54 -07:00
Andrew Nesbitt 4c904dc1d5 cmd/deps: accept --brewfile as an input source
Read brew and cask entries from a Brewfile and treat them as if they
had been passed as named arguments, so --brewfile composes with --tree,
--graph, --for-each, --union and the default flat listing. --formula and
--cask filter which entry types are loaded. A bare --brewfile reads
./Brewfile and --brewfile=<path> reads a specific file, matching
brew vulns.
2026-07-14 07:20:49 -07:00
Andrew Nesbitt 719e9562f3 vulns/scanner: fall back to verbatim head URL for non-forge repos
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 #23080.
2026-07-14 06:56:57 -07:00
Andrew Nesbitt 570b1f07f9 Merge remote-tracking branch 'fork/vulns-cmd' into vulns-cmd 2026-07-13 17:06:51 -07:00
Andrew Nesbitt 20563c04be Restore vulns scanner target fallbacks from the tap
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.
2026-07-13 17:05:06 -07:00
Andrew Nesbitt 5d56078a1e Accept bare --brewfile in brew vulns
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.
2026-07-13 17:04:57 -07:00
Andrew NesbittandGitHub e1e3bcfb21 Merge branch 'main' into vulns-cmd 2026-07-13 14:48:03 -07:00
Andrew Nesbitt d51148c873 Use tap trust for brew vulns 2026-07-13 14:34:04 -07:00
Andrew Nesbitt 4a81eacf1f Inline minimum vulnerability severity 2026-07-13 14:31:43 -07:00
Andrew NesbittandGitHub 6d474d7e42 Merge branch 'Homebrew:main' into vulns-cmd 2026-07-13 05:48:53 -07:00
Andrew Nesbitt 7abeaefa61 Regenerate man page and completions for brew vulns 2026-07-12 22:53:16 +01:00
Andrew Nesbitt d7e60e7c14 Add brew vulns command 2026-07-12 22:47:09 +01:00
Andrew Nesbitt 87cf9fed34 Scan installed keg's SBOM source URL, not the current formula
For installed formulae, read the source download URL from the keg's
sbom.spdx.json (SPDXRef-Archive-*-src) so the OSV query and reported
version reflect what is actually on disk. Patch suppression only applies
when the scanned keg matches the current recipe's PkgVersion. When an
outdated keg has no SBOM the formula is recorded in
Results#outdated_without_sbom for the caller to surface.
2026-07-12 22:47:09 +01:00
Andrew Nesbitt 6d53ee38ba Add Homebrew::Vulns::Output text and JSON renderers 2026-07-12 21:14:56 +01:00
Andrew Nesbitt b390ec387a Add Homebrew::Vulns::Scanner#scan orchestration and Results 2026-07-12 20:58:12 +01:00
Andrew Nesbitt faf548e838 Add Homebrew::Vulns::Scanner URL/tag/resolves extraction helpers 2026-07-12 20:45:25 +01:00
Andrew Nesbitt 0df30eb6c9 Validate OSV querybatch result count matches queries 2026-07-12 20:38:34 +01:00
Andrew Nesbitt df6e7a6387 Follow per-result next_page_token in OSV querybatch 2026-07-12 20:15:16 +01:00
Andrew Nesbitt 9963b6bb9b Add Homebrew::Vulns::OSV client on Utils::Curl 2026-07-12 20:09:55 +01:00
Andrew Nesbitt a9a0392667 Add Homebrew::Vulns::Vulnerability OSV record wrapper 2026-07-12 19:18:53 +01:00
Andrew Nesbitt 876abd4213 Add Homebrew::Vulns::CVSS v3.x base score and severity 2026-07-12 19:02:06 +01:00
Andrew Nesbitt d10df41000 Trim Semver module comments to match brew density 2026-07-12 19:02:06 +01:00
Andrew Nesbitt 692fe388fd Reject leading zeroes and empty identifiers in Semver parser 2026-07-12 18:45:13 +01:00
Andrew Nesbitt c509bee291 Add Homebrew::Vulns::Semver comparator 2026-07-12 18:36:20 +01:00
Andrew Nesbitt af3973f157 Suggest commands for typos 2026-07-12 15:38:02 +01:00
Andrew Nesbitt 1d459d5297 docs/Formula-Cookbook: use unzip for :unofficial example and fix CycloneDX link
Swap the libtool/Big Sur example for unzip per review: the libtool fix is
technically a backport of upstream libtool applied to third-party tarballs,
which muddies the :unofficial definition. unzip's Debian-maintained patches
against a dormant upstream are a cleaner example.

Add a note that :unofficial patches should be reported upstream, linking to
the existing guidance in the Patches section.

Drop the #components_items_pedigree_patches fragment from the CycloneDX link;
the page is a JS-rendered schema viewer and html-proofer cannot find the
anchor in the static HTML.
2026-06-22 11:47:21 -04:00
Andrew Nesbitt 177c8f9dcc docs/Formula-Cookbook: document patch type and resolves 2026-06-22 11:35:55 -04:00
Andrew Nesbitt 10ba461203 patch: describe each type and drop :monkey
`:monkey` is CycloneDX's value for runtime modification, which a
source-level `patch do` block cannot express, so omit it from the DSL.
2026-06-22 11:35:55 -04:00
Andrew Nesbitt 4ead861923 patch: add type and resolves DSL for annotating patches 2026-06-22 11:35:55 -04:00
Andrew NesbittandGitHub 11a246e46d Merge branch 'main' into patches-in-to-hash 2026-05-29 17:54:26 +01:00
Andrew Nesbitt 4415455735 formula: include patches in to_hash 2026-05-29 17:32:25 +01:00