Comments across the codebase credited one individual by role and, in places, described that person's own machines: which SQL Server versions a host ran, which devices were enrolled, what a particular dashboard showed, how many findings sat open on which server. In a public repository that reads as a profile of someone's unpatched estate. The observations are why the code looks the way it does, so they stay. Every CVE id, version, build number, count and date is preserved, as are the verbatim quotes that motivated specific sort and filter rules — only the attribution changes, to "field report", "observed", "a host". A local variable in tests/test_autodesk_year.py was renamed for the same reason; its value and every assertion around it are byte-identical. PROJECT_OVERVIEW.md additionally loses a subtitle naming the kind of organisation this was built for, and a support section pointing at an internal team, both replaced with neutral wording. Comments, docstrings and markdown prose only: 74 files, 200 lines, one-for-one swaps. detect_changes reports 104 touched symbols and zero affected execution flows, and all 55 test scripts pass. Nothing here needs re-testing.
57 lines
2.4 KiB
Python
57 lines
2.4 KiB
Python
"""Firefox/Chrome "EOL" means the next version shipped, not a dead product.
|
|
|
|
They release every four weeks and the previous version stops receiving patches
|
|
the day the next one lands, so every install except the newest is end-of-life
|
|
by that definition. One host moved Firefox 150 -> 152 and the finding
|
|
came straight back as EOL-FIREFOX-152 at CVSS 9.0, escalating toward critical
|
|
as the days counted up — outranking genuinely abandoned software like Exchange
|
|
Server 2016.
|
|
|
|
The finding stays (an unpatched browser matters) but is capped at medium, and
|
|
the day counter no longer escalates it: on a four-week cycle that measures
|
|
release cadence, not growing risk.
|
|
"""
|
|
import os
|
|
import sys
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
from app.services.eol_service import _RAPID_RELEASE_SLUGS, _build_eol_status # noqa: E402
|
|
|
|
|
|
def demo():
|
|
assert _RAPID_RELEASE_SLUGS == {"chrome", "firefox"}
|
|
# Everything that ships on a real support lifecycle must NOT be in here.
|
|
for slug in ("windows", "windows-server", "msexchange", "office",
|
|
"sharepoint", "mssqlserver", "nodejs", "oracle-jdk"):
|
|
assert slug not in _RAPID_RELEASE_SLUGS, slug
|
|
|
|
# The reported release: Firefox 152, security support ended 2026-07-21.
|
|
rel = {"name": "152", "label": "152", "eolFrom": "2026-07-21",
|
|
"isMaintained": False, "latest": {"name": "152.0.6"}}
|
|
st = _build_eol_status(rel, "firefox")
|
|
assert st.is_eol, "still end-of-life — the finding is correct and stays"
|
|
assert st.product_slug == "firefox"
|
|
assert st.latest_version == "152.0.6"
|
|
|
|
# And the release that is current must produce no finding at all.
|
|
cur = {"name": "153", "label": "153", "eolFrom": None,
|
|
"isMaintained": True, "latest": {"name": "153.0.3"}}
|
|
st_cur = _build_eol_status(cur, "firefox")
|
|
assert not st_cur.is_eol
|
|
assert not st_cur.is_eol_soon
|
|
|
|
# A genuinely abandoned product keeps the full weight — this is the
|
|
# comparison that was broken: Exchange 2016 must outrank a stale browser.
|
|
ex = {"name": "2016", "label": "2016 CU23 SU22", "eolFrom": "2025-10-14",
|
|
"isMaintained": False, "latest": {"name": "15.1.2507.69"}}
|
|
st_ex = _build_eol_status(ex, "msexchange")
|
|
assert st_ex.is_eol
|
|
assert st_ex.product_slug not in _RAPID_RELEASE_SLUGS
|
|
|
|
print("ok rapid-release EOL is capped; real end-of-life is not")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
demo()
|