Expose formula patches in the JSON API (and optionally annotate them with CVEs) #6869
Replies: 20 comments 12 replies
|
Yeh, these both make sense to me! PRs welcome. |
|
22459 merged, patch data now in the api:
Example from llvm: next up, part 2 |
|
Part 2 patch to add |
|
PR for part two: Homebrew/brew#22466 Ended up going with patch do
url "https://deb.debian.org/.../libquicktime_1.2.4-12.debian.tar.xz"
sha256 "..."
type :backport
resolves "CVE-2016-2399", "CVE-2017-9122"
apply "patches/CVE-2016-2399.patch", "patches/CVE-2017-9122_et_al.patch"
end
"type": "backport",
"resolves": [
{"type": "security", "id": "CVE-2016-2399"},
{"type": "security", "id": "CVE-2017-9122"}
]The inference Mike suggested is in there too: CVE ids found in the patch |
|
For backfilling the existing 1,191 patches across 809 formulae, here's where the data sits today and where By patch kind
External patches by source (n=972)
Already inferable with no formula changes (once #22466 lands): 25 unique CVEs across The 497 GitHub commit patches are the big prize for automation since OSV indexes fix-commits → CVEs directly. The 272 Homebrew-hosted raw patches are almost entirely macOS/compiler build fixes and will mostly end up with no |
|
Homebrew/brew#22466 has been merged and shipped in homebrew 6.0.4 now, I've rebased Homebrew/homebrew-core#285534, if this is looking good I can start to roll through more and more of the formula with patches to add them in |
|
Wired this up on the Testing it against the four formulae from Homebrew/homebrew-core#285534 turned up an OSV coverage gap worth noting. Most CVE records in OSV are auto-converted from NVD and have no That points at a possible third part to this thread: now that formulae carry structured |
|
Picking up the backfill that Homebrew/homebrew-core#285534 floats for the remaining ~935 patch blocks (scripted by URL heuristic): I pulled the API patch data to scope it and it gave me pause. I sampled 59 of the upstream-commit patches and zero reference a CVE. Core patches are mostly build/portability fixes, not security backports, so a URL/filename heuristic finds very little beyond the cases already covered (the CVE-named patchsets like unzip that inference catches, plus the four you annotated by hand). And of the ~10 formulae that mention a CVE in source, most are outstanding/unfixed CVEs or version rationale (avahi, openslp, sylpheed, opentsdb), so a heuristic that greps for CVE strings risks injecting false "patched" signals. So rather than scripting blind, I'd make it scanner-driven: run I can drop a per-patch inventory into a tracking issue as the working set and open the first batch from the scanner output once #92 / #93 land. Sound right, or do you still want the URL-heuristic sweep as a first pass and treat the scanner run as validation on top? |
|
Status update on the three parts. Part 1/2 (patches in JSON, Backfill (Homebrew/homebrew-brew-vulns#95): ran the scanner-driven pass over the 484 patched formulae that are currently queryable. 9 had OSV hits; every shipped patch turned out to be a build/portability fix, so zero new Part 3 (Homebrew OSV feed): prototyped. Homebrew/homebrew-brew-vulns#99 adds Plan is to transfer that repo into the Homebrew org once it's settled, then open the osv.dev new-data-source request and the ossf/osv-schema registration PR from there. |
|
Quick update since the last one, mostly on part 3.
Backfill: #97 (homepage fallback) merged, which made 20 of the previously-skipped 314 patched formulae queryable. Re-scan found zero OSV hits for any of them, so still one net annotation ( Next: transfer |
|
Two updates. Part 3: ossf/osv-schema#576 merged this morning, so brew-vulns → brew: opened Homebrew/brew#23080 to move the scanner into brew itself as a built-in |
|
Homebrew/brew#23080 merged this morning, so The advisory database has been transferred into the org as Homebrew/homebrew-advisory-database. Both upstream registrations are done: Two follow-up PRs to brew are open: Homebrew/brew#23103 restores the non-forge head-URL fallback so formulae like Current advisory count is 32 records across 5 formulae ( |
|
The advisory repo is now Homebrew/advisory-database (renamed to drop the osv.dev onboarding: ossf/osv-schema#580 fills the |
|
Hey all, I'm working on some related things. My current focus: Homebrew/brew#23152 Also tracking google/oss-fuzz-vulns#51 and google/osv.dev#2353 which reduce the quality of the Lastly, I am trying a local patch to have brew generate SBOMs that can be checked against https://github.com/Homebrew/advisory-database. commit dd71766e086df81825762a122a156b151a701b35
Author: Kyle Marek-Spartz <kyle.marek.spartz@gmail.com>
Date: Tue Jul 21 13:47:43 2026 -0500
sbom: add purl external references for sources
diff --git a/Library/Homebrew/sbom.rb b/Library/Homebrew/sbom.rb
index 1ca7d29245..b42c050e81 100644
--- a/Library/Homebrew/sbom.rb
+++ b/Library/Homebrew/sbom.rb
@@ -546,7 +546,13 @@ class SBOM
licenseConcluded: assert_value(license),
downloadLocation: source.url,
copyrightText: assert_value(nil),
- externalRefs: [],
+ externalRefs: [
+ {
+ referenceCategory: "PACKAGE-MANAGER",
+ referenceLocator: tap ? "pkg:brew/#{tap}/#{name}@#{spec_version}" : "pkg:brew/#{name}@#{spec_version}",
+ referenceType: "purl",
+ },
+ ].compact,
checksums: [
{
algorithm: "SHA256", |
|
Update since 14 July. Merged
Open
Once those four are merged the next site deploy shows the section for whatever's in advisory-database (44 records / 10 formulae today), and @kmarekspartz thanks for Homebrew/brew#23152 and the SBOM purl patch. osv.dev ingestion still waiting on google/osv.dev#5660 (needs a |
|
Adding patches to a formula based on the data in We may want to extend the cli filters to distinguish between new release available but formula hasn't been updated, and there's a patch available but no release. |
|
Likely need a flag for listing which "... packages skipped - no supported source URL" to make that actionable, too. |
|
Draft of incorporating my SBOM patch and third party purls as requested by @andrew: https://github.com/Homebrew/brew/pull/23459/changes It looks correct to me but intend to try this out locally a bit before marking it as ready for review. |
|
Looking across my installed but skipped formula, the two main clusters are:
Given the Python packages, I'm starting a branch to amend the scanner to look more closely at the upstream ecosystem(s) in the OSV data. There were a couple that are on GitLab/GitHub already that should be addressable with a formula change, but I have an existing formula change open, so would encourage someone else to take on getting these two formula updated:
|
Uh oh!
There was an error while loading. Please reload this page.
While working on
brew-vulnsI wanted to find every formula in homebrew-core that ships with a patch applied. There's currently no way to get this frombrew info --jsonor formulae.brew.sh;Formula#to_hashdoesn't serialisepatchlist, and formulae loaded from the API have an emptypatchlist. The only options today are grepping a homebrew-core checkout forpatch do/patch :DATA, or runningbrew rubywithHOMEBREW_NO_INSTALL_FROM_API=1and walkingFormula.all. Roughly 860 of the ~8400 core formulae currently carry at least one patch.1. Add a
patcheskey toFormula#to_hash. Something like:This would let
brew-vulnsand other downstream tooling (SBOM generators, OSV importers, distro-comparison tools) see which packages Homebrew has modified relative to the upstream tarball, without needing a full core checkout.2. Allow patches to declare which CVEs they address. Right now this lives in comments:
glibcapplies a Debian patch tarball withapply "patches/any/CVE-2024-2961.patch",libquicktimehas# Fix CVE-2016-2399above itspatch doblock. Only about eight formulae mention a CVE at all, and where the data exists it can't be read programmatically. A small DSL addition would cover it:which would surface in the JSON as
"fixes": ["CVE-2016-2399", "CVE-2017-9122"]on each patch entry. This is the same shape Fedora uses in spec changelogs and Alpine uses insecfixes:blocks, and it would let vulnerability scanners report "yes this version is affected upstream, but Homebrew's bottle is patched" instead of raising a false positive. Related: in #6826 @SMillerDev suggested handling CVEs at the audit layer; structured patch data would give that audit something to read.I'm happy to put together the PR for part 1 if there's appetite; part 2 is more of a policy question about whether maintainers want to track that data in formulae at all.
All reactions