vulns/advisory_database: skip :not_applicable records in status_for

A record whose ECOSYSTEM range starts above pkg_version returns
state :not_applicable from range_status; that was falling through to
patched (if fix: patch) or fixed_count. Drop it instead so a version the
advisory never applied to is not counted either way. Also distinguish a
missing advisories key from a wrong-type value in the load error.
This commit is contained in:
Andrew Nesbitt committed 2026-07-28 17:26:03 +01:00
1 parent e36ace0ef4
commit e7eec14b51
2 files changed
+32 -8

No files matched your search

@@ -31,7 +31,12 @@ RSpec.describe Homebrew::Vulns::AdvisoryDatabase do
it "raises Error when the advisories key is missing" do
expect { described_class.new({ "meta" => {} }) }
.to raise_error(Homebrew::Vulns::CachedFeed::Error, /missing 'advisories' key/)
.to raise_error(Homebrew::Vulns::CachedFeed::Error, /no 'advisories' key/)
end
it "distinguishes a wrong-type advisories value from a missing key" do
expect { described_class.new({ "advisories" => [] }) }
.to raise_error(Homebrew::Vulns::CachedFeed::Error, /'advisories' is not a JSON object/)
end
end
@@ -89,6 +94,19 @@ RSpec.describe Homebrew::Vulns::AdvisoryDatabase do
expect(corpus.status_for("nope", "1.0")).to be_nil
end
it "ignores :not_applicable records rather than counting them as fixed or patched" do
d = db({ "foo" => [
record("BREW-foo-CVE-1", "foo",
events: [{ "introduced" => "2.0" }, { "fixed" => "3.0" }], fix: "bump"),
record("BREW-foo-CVE-2", "foo",
events: [{ "introduced" => "2.0" }, { "fixed" => "3.0" }], fix: "patch"),
] })
status = d.status_for("foo", "1.0")
expect(status["open"]).to eq []
expect(status["patched"]).to eq []
expect(status["fixed_count"]).to eq 0
end
it "compacts nil fields out of each entry hash" do
status = corpus.status_for("unzip", "6.0_29")
expect(status["open"].first.keys).to eq %w[id upstream]
+13 -7
View File
@@ -27,7 +27,10 @@ module Homebrew
def initialize(data)
super
raise Error, "advisory index is not a JSON object" unless (top = as_hash(data))
raise Error, "advisory index missing 'advisories' key" unless (advisories = as_hash(top["advisories"]))
raise Error, "advisory index has no 'advisories' key" unless top.key?("advisories")
unless (advisories = as_hash(top["advisories"]))
raise Error, "advisory index 'advisories' is not a JSON object"
end
@advisories = T.let(advisories, T::Hash[String, T.untyped])
@meta = T.let(as_hash(top["meta"]) || {}, T::Hash[String, T.untyped])
@@ -89,12 +92,15 @@ module Homebrew
fix: eco["fix"],
fixed_in: status&.fixed_in,
).freeze
if status.nil? || status.affected?
open << entry
elsif eco["fix"] == "patch"
patched << entry
else
fixed_count += 1
case status&.state
when nil, :affected then open << entry
when :fixed
if eco["fix"] == "patch"
patched << entry
else
fixed_count += 1
end
when :not_applicable then next
end
end