more changes

This commit is contained in:
David Duran Rosich committed 2026-10-24 23:55:11 +02:00
1 parent a8241fa648
commit 8a5c712ef0
3 files changed
+26 -21

No files matched your search

+7 -6
View File
@@ -25,12 +25,13 @@ host only needs Docker. JSON reports are kept on disk for auditing.
alert.
- `FAIL_ON` (default `HIGH`) – when the script should exit with code `1`
(useful for CI).
3. If any CVE reaches `NOTIFY_MIN_SEVERITY`, notifications are sent. When
`IMPORTANT_CONTAINERS` is set, each named container gets its own complete
CVE list (split into fixable and unfixable), missing important containers
are reported, and every other container is summarised in one notification.
Without `IMPORTANT_CONTAINERS`, a single aggregated notification lists each
CVE with the affected packages, containers, and images.
3. Notifications are sent. When `IMPORTANT_CONTAINERS` is set, each named
container gets its own complete CVE list (showing `C X/Y ...` where X is
fixable and Y is total per severity, plus `Total: fixable/total`), missing
important containers are reported, and every other container is summarised as
`fixable/total`. Without `IMPORTANT_CONTAINERS`, a single aggregated
notification lists each CVE with the affected packages, containers, and
images.
## Quick start
+12 -10
View File
@@ -854,7 +854,7 @@ def build_body(
MAX_NOTIFICATION_CHARS = 2500
DISCORD_MAX_NOTIFICATION_CHARS = 1800
DISCORD_MAX_NOTIFICATION_CHARS = 1500
def uses_discord(settings: Settings) -> bool:
@@ -973,12 +973,19 @@ def build_important_body(
entries = cve_entries(result, severity_rank(min_severity))
total, fixable, unfixable = split_counts(entries)
counts = severity_counts(entries)
fixable_counts = {severity: 0 for severity in REPORTED_SEVERITIES}
for entry in entries:
if entry.fixable:
fixable_counts[entry.severity] += 1
lines = [
f"Image: {target.image}",
f"Container: {container}",
" | ".join(f"{name.title()}: {counts[name]}" for name in REPORTED_SEVERITIES),
f"Total: {total} (fixable: {fixable}, unfixable: {unfixable})",
" | ".join(
f"{name[0]} {fixable_counts[name]}/{counts[name]}"
for name in REPORTED_SEVERITIES
),
f"Total: {fixable}/{total} (fixable/total)",
"",
"CVEs:",
]
@@ -1000,15 +1007,10 @@ def build_other_containers_body(
Each row is ``(image, container, total, fixable, unfixable)``.
"""
lines = ["Other containers with findings:", ""]
total_all = 0
for image, container, total, fixable, unfixable in rows:
total_all += total
label = f"{image} [{container}]" if container else image
lines.append(
f"* {label}: {total} total "
f"({fixable} fixable, {unfixable} unfixable)"
)
lines += ["", f"Total: {total_all} CVE(s) in {len(rows)} container(s)"]
lines.append(f"* {label}: {fixable}/{total} (fixable/total)")
lines += ["", f"Total: {sum(row[2] for row in rows)} CVE(s) in {len(rows)} container(s)"]
return "\n".join(lines)
+7 -5
View File
@@ -475,7 +475,8 @@ class ReportTests(unittest.TestCase):
)
self.assertIn("Image: nginx:1.27", body)
self.assertIn("Container: web", body)
self.assertIn("Total: 3 (fixable: 2, unfixable: 1)", body)
self.assertIn("C 1/1 | H 1/2 | M 0/0 | L 0/0", body)
self.assertIn("Total: 2/3 (fixable/total)", body)
self.assertIn("CVE-1", body)
self.assertIn("CVE-2", body)
self.assertIn("CVE-5", body)
@@ -491,7 +492,8 @@ class ReportTests(unittest.TestCase):
self.assertIn("CVE-1", body)
self.assertNotIn("CVE-2", body)
self.assertNotIn("CVE-5", body)
self.assertIn("Total: 1 (fixable: 1, unfixable: 0)", body)
self.assertIn("C 1/1 | H 0/0 | M 0/0 | L 0/0", body)
self.assertIn("Total: 1/1 (fixable/total)", body)
def test_build_other_containers_body_has_counts_per_container(self) -> None:
body = scan.build_other_containers_body(
@@ -500,8 +502,8 @@ class ReportTests(unittest.TestCase):
("redis:7", "cache", 4, 0, 4),
]
)
self.assertIn("* nginx:1.27 [web-worker]: 3 total (2 fixable, 1 unfixable)", body)
self.assertIn("* redis:7 [cache]: 4 total (0 fixable, 4 unfixable)", body)
self.assertIn("* nginx:1.27 [web-worker]: 2/3 (fixable/total)", body)
self.assertIn("* redis:7 [cache]: 0/4 (fixable/total)", body)
self.assertIn("Total: 7 CVE(s) in 2 container(s)", body)
def test_build_missing_body_separates_missing_and_unscanned(self) -> None:
@@ -667,7 +669,7 @@ printf '%s\\n' "$*" >> "$APPRISE_LOG"
self.assertIn("CVE-2026-0001", notification)
self.assertIn("Vulnerability scan: other containers", notification)
self.assertIn("redis:7 [cache]", notification)
self.assertIn("(1 fixable, 0 unfixable)", notification)
self.assertIn("1/1 (fixable/total)", notification)
# The important container must not also appear in the summary.
self.assertNotIn("testphp-php [web]", notification)