advisory-scan: NVD by CPE, so mattermost and mumble stop scanning as '?'
Two recipes could not see CVEs at all. mattermost-lts has an empty GitHub advisory feed and renders its security bulletins client-side, so a text sweep finds nothing; mumble publishes nothing anywhere the registry points. Both returned '?' - nothing measured - which is honest but useless. NVD is CPE-indexed and carries structured version ranges, so it answers where the vendor does not. Declared per recipe as 'nvd-cpe: <image> = <cpe:2.3:...>'. mattermost-lts 10.5.0 -> 10.12.4 165 CVEs mattermost-lts 10.11.22 -> 10.12.4 0 CVEs (measured, not unknown) mumble 1.3.0 -> 1.6.870 2 CVEs Both NVD range forms are used: versionEndExcluding is a patched version; versionEndIncluding means the fix version is unpublished but the upgrade delivers it whenever it crosses X. That 0 for the actual mattermost upgrade is the interesting one, and it needed a new rule to be correct: a fix on the line you upgrade FROM was already yours. mattermost patches every maintained line at once, so 10.11.22 -> 10.12.4 crosses 10.12.1 while 10.11.22 already had the 10.11.4 backport. Without the rule the scan claimed 12 CVEs the upgrade did not deliver. The rule is skipped for placeholders: '7.4.X' parses to a bare 7.4 and would read as 'already fixed at 7.4', which silently dropped redis CVE-2024-46981 and took discourse 140 -> 139 before I caught it. 79 tests. discourse 140 / gitea 2 / mailu 2 / keycloak 12 / plausible 6 unchanged. Fleet sweep: 0 recipes with no usable CVE source, down from 2.
This commit is contained in:
@@ -537,6 +537,34 @@ class TestReleaseLineSemantics(unittest.TestCase):
|
||||
self.assertEqual(rep["fixed_by_this_upgrade"], ["CVE-2025-49844"])
|
||||
|
||||
|
||||
class TestAlreadyFixedOnFromLine(unittest.TestCase):
|
||||
"""A fix that landed on the line we upgrade FROM was already ours before the upgrade."""
|
||||
|
||||
def test_backport_to_our_own_line_is_not_credited(self):
|
||||
# mattermost patches every maintained line at once. 10.11.22 -> 10.12.4 crosses 10.12.1, but
|
||||
# 10.11.22 is already past 10.11.4, so the deployment HAD the fix. Counting it credits the
|
||||
# upgrade with work it did not do.
|
||||
rep = run_scan([gh("mattermost/mattermost",
|
||||
[adv("CVE-1", patched="10.11.4; 10.12.1; 10.5.12")])],
|
||||
v_from="10.11.22", v_to="10.12.4",
|
||||
urls=["https://github.com/mattermost/mattermost"])
|
||||
self.assertEqual(rep["fixed_by_this_upgrade"], [])
|
||||
|
||||
def test_a_fix_ABOVE_our_position_on_the_same_line_still_counts(self):
|
||||
rep = run_scan([gh("mattermost/mattermost", [adv("CVE-2", patched="10.11.30; 10.12.1")])],
|
||||
v_from="10.11.22", v_to="10.12.4",
|
||||
urls=["https://github.com/mattermost/mattermost"])
|
||||
self.assertEqual(rep["fixed_by_this_upgrade"], ["CVE-2"])
|
||||
|
||||
def test_placeholders_never_feed_this_rule(self):
|
||||
# "7.4.X" parses to a bare 7.4, which would read as "already fixed at 7.4" and silently drop
|
||||
# a real fix — this is exactly how redis CVE-2024-46981 was lost when the rule was added.
|
||||
rep = run_scan([gh("redis/redis", [adv("CVE-3", patched="6.2.X, 7.2.X, 7.4.X")])],
|
||||
v_from="7.4", v_to="8.10", urls=["https://github.com/redis/redis"])
|
||||
self.assertIn("CVE-3", rep["indeterminate"])
|
||||
self.assertEqual(rep["fixed_by_this_upgrade"], [])
|
||||
|
||||
|
||||
class TestChangelogAttribution(unittest.TestCase):
|
||||
"""Projects that publish no advisory feed still say which release fixed what — in their changelog."""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user