Advisories in this repository come from three places: records generated from resolves annotations on homebrew/core formula patches, candidate records matched against external OSV feeds by brew advisory-match, and records contributed directly by pull request. All live under advisories/ as OSV-schema JSON and are validated against that schema on every push.
If a homebrew/core formula already ships a patch that fixes a CVE, the simplest route is to annotate the patch. Open a pull request against Homebrew/homebrew-core adding resolves "CVE-YYYY-NNNNN" to the relevant patch do block; see libquicktime.rb for an example. CVE identifiers appearing in the patch URL or applied file paths are picked up automatically without an explicit resolves. The daily Regenerate workflow will pick it up and write a BREW-<formula>-<CVE> record here automatically. Generated records carry "database_specific": {"source": "generated"}. The workflow refreshes their upstream-derived fields (summary, severity, references, ecosystem_specific.patches) on each run but preserves published and affected[].ranges from whatever is on disk, so a hand-corrected fixed boundary will not be overwritten.
Open a pull request adding a file under advisories/ when you want to record something the generated path cannot express, most commonly that a formula version is affected and Homebrew has not yet applied a fix.
Before opening the PR, report the issue upstream according to the project's security policy and wait for it to be acknowledged. If you believe the vulnerability is being actively exploited against Homebrew users, or the upstream project is unresponsive after a reasonable disclosure window, open a private security advisory on this repository instead of a public PR.
Name the file BREW-0000-0000.json; a maintainer assigns the final id on merge. The record must validate against the OSV schema and use the Homebrew ecosystem with a pkg:brew/<formula> purl. A minimal example:
{
"schema_version": "1.7.3",
"id": "BREW-0000-0000",
"modified": "2026-01-01T00:00:00Z",
"upstream": ["CVE-YYYY-NNNNN"],
"summary": "One-line description",
"affected": [{
"package": {"ecosystem": "Homebrew", "name": "example", "purl": "pkg:brew/example"},
"ranges": [{"type": "ECOSYSTEM", "events": [{"introduced": "0"}, {"fixed": "1.2.3"}]}]
}],
"references": [{"type": "ADVISORY", "url": "https://..."}]
}Use {"introduced": "0"} if every shipped version is affected. Omit the fixed event if there is no fixed version yet; add it in a follow-up PR once one exists. Versions are the formula version as brew info reports it, with an _N suffix when the revision is nonzero. Link the upstream CVE, GHSA or advisory in upstream and references.
Records with "database_specific": {"source": "matched", ...} are produced by brew advisory-match (in Homebrew/brew), which queries OSV.dev's GIT, language-registry and distro ecosystems plus CPANSA for a formula and emits one candidate per CVE reached. These arrive as automated PRs and need a human to confirm the match before merge.
database_specific tells you how the match was made:
strategyis the highest-precision path that reached the CVE:git(the formula's forge repo),registry(a PyPI/npm/crates/... package derived fromstable.urlor aresource),cpansa(a CPAN distribution), ordistro(a Debian/Ubuntu/... source package name mapped via Repology).confidencefollows from strategy and whether a comparable version range was found:highforgit/registrywith a range,mediumwhen no comparable range was found (typically GIT commit-SHA events),lowfordistro.upstream_evidencelists every path that reached the CVE, each with the{ecosystem, name, subject_version}that was queried.
affected[0].ecosystem_specific tells you what the range check concluded:
range_stateisaffected(the shipped version is inside an upstream affected range),fixed(past one), or absent (no comparable range; the reviewer sets the boundary).upstream_fixed_inis the upstream version the matched range says fixes it.resourceandresource_purlare set when the affected subject is a vendoredresourceblock rather than the formula's primary source."fix": "bump"and afixedevent inrangesare only present whenrange_stateis"fixed".
Before merging, check:
- The
upstream_evidencekeys point at this formula's actual upstream. Adistro-only hit can reach a CVE for an unrelated package that shares a Repology project (for example awget2CVE surfaced againstwget); close those. - The CVE is not a distro-specific patch. Open https://osv.dev/vulnerability/CVE-YYYY-NNNNN and confirm the affected package and description match the upstream project, not a distribution's packaging of it.
- If
range_stateis"fixed", thefixedboundary inrangesis thepkg_versionat which Homebrew first shipped the fix.brew advisory-matchderives this by walkinghomebrew-corehistory; spot-check it againstgit log -p -- Formula/<letter>/<name>.rbin ahomebrew-corecheckout and correct it in the PR if wrong. The corrected value is preserved on subsequent regenerations. - If
range_stateis"affected"with aresource,brew info <formula> --json=v2 | jq '.formulae[0].resources[] | select(.name == "<resource>") | .version'confirms the pinned resource version is belowupstream_fixed_in. Known false-positive sources are stale CPANSA ranges and OSV records where one alias (often a PYSEC id) has an open-ended range while another has a bounded one. - If
range_stateis absent andconfidenceismediumorlow, the record is a lead rather than a determination: either set therangesboundary yourself from the upstream advisory andhomebrew-corehistory, or close if the CVE does not apply.
Do not merge a matched record over an existing source: "generated" record for the same (formula, CVE); the generated record already states Homebrew ships a patch and takes precedence. brew advisory-match --output skips these automatically.
Records here describe vulnerabilities in software Homebrew distributes, scoped to the Homebrew formula name and version. They are not a substitute for the upstream project's own advisory; the purpose is to let tools that read pkg:brew purls or Homebrew OSV queries answer "is this installed formula affected". Casks are out of scope for now.
This project follows the Homebrew Code of Conduct.