Integrate metrics from metrics.json into the report pdf.

This commit is contained in:
Florian Frank committed 2026-09-21 21:47:29 +02:00
1 parent 9d7df77923
commit 9247608a9f
5 files changed
+155 -18

No files matched your search

+57 -10
View File
@@ -123,7 +123,9 @@ def _dependency_metrics(readings: list[dict[str, Any]]) -> dict[str, Any]:
"impact": _impact(scored),
"exploitability": _exploitability(scored, readings),
"remediation": _remediation(readings),
"age": _age(readings),
"temporal": _temporal(readings),
"taxonomy": _taxonomy(readings),
"affected_surface": _affected_surface(readings),
}
@@ -255,7 +257,7 @@ def _remediation(readings: list[dict[str, Any]]) -> dict[str, Any]:
}
def _age(readings: list[dict[str, Any]]) -> dict[str, Any]:
def _temporal(readings: list[dict[str, Any]]) -> dict[str, Any]:
dated = []
for one in readings:
stated = one["finding"].get("published")
@@ -265,13 +267,58 @@ def _age(readings: list[dict[str, Any]]) -> dict[str, Any]:
except ValueError:
continue
if not dated:
return {"newest": None, "oldest": None, "mean_days": None, "median_days": None, "coverage": 0}
dated.sort()
days = [(datetime.now(UTC) - date.astimezone(UTC)).days for date, _ in dated]
age = {"newest": None, "oldest": None, "mean_days": None, "median_days": None, "coverage": 0}
else:
dated.sort()
days = [(datetime.now(UTC) - date.astimezone(UTC)).days for date, _ in dated]
age = {
"newest": {"cve": dated[-1][1], "published": dated[-1][0].isoformat(), "days": days[-1]},
"oldest": {"cve": dated[0][1], "published": dated[0][0].isoformat(), "days": days[0]},
"mean_days": round(statistics.fmean(days)),
"median_days": round(statistics.median(days)),
"coverage": len(dated),
}
return {"published": age, "time_to_exploit_days": None, "cve_volume_trends": None}
def _taxonomy(readings: list[dict[str, Any]]) -> dict[str, Any]:
cwes: Counter[str] = Counter()
for one in readings:
vulnerability = one["finding"]
values = vulnerability.get("cwes") or []
if not values and vulnerability.get("cweId") is not None:
values = [vulnerability["cweId"]]
for value in values:
if isinstance(value, dict):
value = value.get("cweId")
if value is not None:
cwes[str(value) if str(value).startswith("CWE-") else f"CWE-{value}"] += 1
return {
"newest": {"cve": dated[-1][1], "published": dated[-1][0].isoformat(), "days": days[-1]},
"oldest": {"cve": dated[0][1], "published": dated[0][0].isoformat(), "days": days[0]},
"mean_days": round(statistics.fmean(days)),
"median_days": round(statistics.median(days)),
"coverage": len(dated),
"cwe_counts": dict(cwes.most_common()),
"coverage": sum(cwes.values()),
"abstraction_level": None,
"relationships": None,
}
def _affected_surface(readings: list[dict[str, Any]]) -> dict[str, Any]:
components = [one["component"] for one in readings]
names = {str(component.get("name")) for component in components if component.get("name")}
versions = {str(component.get("version")) for component in components if component.get("version")}
vendors = set()
for component in components:
purl = component.get("purl")
if isinstance(purl, str) and purl.startswith("pkg:"):
coordinate = purl[4:].split("@", 1)[0]
parts = coordinate.split("/")
if len(parts) > 2 and parts[1]:
vendors.add(parts[1])
return {
"products": len(names),
"versions": len(versions),
"version_ranges": None,
"vendors": sorted(vendors),
}