Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Contributing

Advisories in this repository come from two places: records generated from `resolves` annotations on `homebrew/core` formula patches, and records contributed directly by pull request. Both live under `advisories/` as [OSV-schema](https://ossf.github.io/osv-schema/) JSON and are validated against that schema on every push.
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](https://ossf.github.io/osv-schema/) JSON and are validated against that schema on every push.

## Reporting a fixed vulnerability

Expand Down Expand Up @@ -31,6 +31,33 @@ Name the file `BREW-0000-0000.json`; a maintainer assigns the final id on merge.

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`.

## Reviewing matched candidates

Records with `"database_specific": {"source": "matched", ...}` are produced by `brew advisory-match` (in [Homebrew/brew](https://github.com/Homebrew/brew)), which queries OSV.dev's GIT, language-registry and distro ecosystems plus [CPANSA](https://github.com/briandfoy/cpan-security-advisory) 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:

- `strategy` is the highest-precision path that reached the CVE: `git` (the formula's forge repo), `registry` (a PyPI/npm/crates/... package derived from `stable.url` or a `resource`), `cpansa` (a CPAN distribution), or `distro` (a Debian/Ubuntu/... source package name mapped via [Repology](https://repology.org)).
- `confidence` follows from strategy and whether a comparable version range was found: `high` for `git`/`registry` with a range, `medium` when no comparable range was found (typically GIT commit-SHA events), `low` for `distro`.
- `upstream_evidence` lists 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_state` is `affected` (the shipped version is inside an upstream affected range), `fixed` (past one), or absent (no comparable range; the reviewer sets the boundary).
- `upstream_fixed_in` is the upstream version the matched range says fixes it.
- `resource` and `resource_purl` are set when the affected subject is a vendored `resource` block rather than the formula's primary source.
- `"fix": "bump"` and a `fixed` event in `ranges` are only present when `range_state` is `"fixed"`.

Before merging, check:

- The `upstream_evidence` keys point at this formula's actual upstream. A `distro`-only hit can reach a CVE for an unrelated package that shares a Repology project (for example a `wget2` CVE surfaced against `wget`); 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_state` is `"fixed"`, the `fixed` boundary in `ranges` is the `pkg_version` at which Homebrew first shipped the fix. `brew advisory-match` derives this by walking `homebrew-core` history; spot-check it against `git log -p -- Formula/<letter>/<name>.rb` in a `homebrew-core` checkout and correct it in the PR if wrong. The corrected value is preserved on subsequent regenerations.
- If `range_state` is `"affected"` with a `resource`, `brew info <formula> --json=v2 | jq '.formulae[0].resources[] | select(.name == "<resource>") | .version'` confirms the pinned resource version is below `upstream_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_state` is absent and `confidence` is `medium` or `low`, the record is a lead rather than a determination: either set the `ranges` boundary yourself from the upstream advisory and `homebrew-core` history, 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.

## Scope

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.
Expand Down