more changes
This commit is contained in:
1 parent
a8241fa648
commit
8a5c712ef0
3 files changed
+26
-21
No files matched your search
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
|
||||
Reference in new issue
Block a user