Office, SharePoint and Exchange take their release from the year in the
inventory NAME, so every companion package that happens to carry a year
claimed that release was installed: "Microsoft Office 2007 Primary Interop
Assemblies", "Microsoft Exchange Server 2010 MAPI Client and CDO",
"Microsoft SharePoint 2013 Client Components SDK". Each produced a CRITICAL
EOL finding for a product the host does not run — the tester's Exchange SE
host, fully supported, carried an EOL-MSEXCHANGE-2007.
Naming the add-ons one at a time is a race nobody wins; there is always
another rollup. What separates the product from its companions is what
FOLLOWS the year: the product name ends there, or continues with an edition
or update qualifier ("2016 Cumulative Update 23", "Professional Plus 2016 -
de-de"). Any other word after the year belongs to a different product that
merely names this one. Both resolvers consult the same rule, so a companion
is refused whichever source would have matched it.
Second half of the same report: the status loop. These slugs are
single-release, so each companion superseded the others' finding once per
sweep — 2007 closes 2016, 2016 reopens and closes 2007, every run, with
nothing changing on the host. Supersede now leaves alone any finding the
same sweep already confirmed: the sweep saw both products in one inventory,
so neither replaced the other. Dropping the companions removes the cause;
this removes the mechanism.
The real entries are untouched — "Microsoft Exchange Server 2016 Cumulative
Update 23" and the plain "Microsoft Exchange Server" both still resolve to
release 2016 (EOL 2025-10-14), so the host's genuine finding stands.
80 lines
3.0 KiB
Python
80 lines
3.0 KiB
Python
"""EOL supersede must not fire on side-by-side products.
|
|
|
|
The tester's host has Visual C++ 2008, 2010, 2012, 2013, 2015 and 2022
|
|
redistributables installed at once — normal on Windows, and several of them
|
|
genuinely EOL. Supersede assumed one release per product, so within a single
|
|
scan the 2008 entry closed the 2013 finding as "superseded", the 2013 entry
|
|
reopened it and closed 2008, and so on: 50 alternating change-history rows and
|
|
hundreds of audit entries a night, with nothing on the host changing.
|
|
"""
|
|
import os
|
|
import sys
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
from app.services.eol_service import ( # noqa: E402
|
|
_SINGLE_RELEASE_SLUGS, _pseudo_cve_id, _supersede_old_eol,
|
|
resolve_product_slug)
|
|
from app.models.vulnerability import VulnerabilityStatus # noqa: E402
|
|
|
|
|
|
class _Vuln:
|
|
def __init__(self, vid, cve_id):
|
|
self.id, self.cve_id = vid, cve_id
|
|
self.status = VulnerabilityStatus.open
|
|
self.patched_at = None
|
|
|
|
|
|
class _Query:
|
|
def __init__(self, rows): self.rows = rows
|
|
def filter(self, *a, **k): return self
|
|
def all(self): return self.rows
|
|
|
|
|
|
class _DB:
|
|
def __init__(self, rows): self.rows = rows
|
|
def query(self, *a, **k): return _Query(self.rows)
|
|
|
|
|
|
def protect_check():
|
|
"""A finding this same sweep confirmed must never be superseded — that
|
|
mutual close/reopen is the open→patched→open loop."""
|
|
other = _Vuln(7, "EOL-MSEXCHANGE-2019")
|
|
db = _DB([other])
|
|
_supersede_old_eol(db, 1, "msexchange", "EOL-MSEXCHANGE-2016",
|
|
protect_ids={7})
|
|
assert other.status == VulnerabilityStatus.open
|
|
|
|
# Unprotected (not seen this run) → still closed, as before.
|
|
_supersede_old_eol(db, 1, "msexchange", "EOL-MSEXCHANGE-2016")
|
|
assert other.status == VulnerabilityStatus.patched
|
|
|
|
|
|
def demo():
|
|
protect_check()
|
|
# Side by side → never superseded.
|
|
for name in ("Microsoft Visual C++ 2013 Redistributable (x86) - 12.0.21005",
|
|
"Microsoft Visual C++ 2008 Redistributable - x64 9.0.30729"):
|
|
assert resolve_product_slug(name) not in _SINGLE_RELEASE_SLUGS, name
|
|
for slug in ("mssqlserver", "oracle-jdk", "dotnetfx", "nodejs", "python"):
|
|
assert slug not in _SINGLE_RELEASE_SLUGS, slug
|
|
|
|
# One per device → supersede is what keeps the old release from lingering.
|
|
for slug in ("chrome", "firefox", "windows", "windows-server", "msexchange"):
|
|
assert slug in _SINGLE_RELEASE_SLUGS, slug
|
|
assert resolve_product_slug("Google Chrome") in _SINGLE_RELEASE_SLUGS
|
|
|
|
# The reported case: the two ids are distinct, so the old code saw each as
|
|
# the other's stale duplicate.
|
|
a = _pseudo_cve_id("ms-lifecycle", "Visual C++ 2013 Redistributable")
|
|
b = _pseudo_cve_id("ms-lifecycle", "Visual C++ 2008 Redistributable")
|
|
assert a != b
|
|
assert "ms-lifecycle" not in _SINGLE_RELEASE_SLUGS, (
|
|
"the Microsoft lifecycle export covers many co-installed products")
|
|
|
|
print("ok supersede fires only where a device runs one release")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
demo()
|