"""Container-CVE source: Trivy-scan the images of running containers (HIGH/CRITICAL).""" import json import subprocess from soc import finding from . import _docker SEV = {"CRITICAL": "crit", "HIGH": "high", "MEDIUM": "med", "LOW": "low"} def _running_images(): conts = _docker.get("/containers/json") or [] seen = [] for c in conts: img = c.get("Image", "") if img and img not in seen: seen.append(img) return seen def run(): if not _docker.available(): return None # socket not mounted -> skip images = _running_images() if not images: return None findings = [] for img in images: try: proc = subprocess.run( ["trivy", "image", "--quiet", "--scanners", "vuln", "--severity", "HIGH,CRITICAL", "--format", "json", img], capture_output=True, text=True, timeout=900) rep = json.loads(proc.stdout or "{}") except Exception: continue vulns = [v for res in (rep.get("Results") or []) for v in (res.get("Vulnerabilities") or [])] if not vulns: continue worst = "crit" if any(v.get("Severity") == "CRITICAL" for v in vulns) else "high" ids = sorted({v.get("VulnerabilityID", "") for v in vulns if v.get("VulnerabilityID")}) findings.append(finding( f"cve-{img}", worst, f"{len(vulns)} HIGH/CRITICAL CVEs in {img}", host=img, evidence=", ".join(ids[:10]) + (" …" if len(ids) > 10 else ""), impact=["known-exploitable vulnerabilities in a running image"], fix=[f"pull/rebuild a patched {img.split(':')[0]} image"])) return { "scope": f"{len(images)} running image(s)", "findings": findings, "good": [] if findings else ["No HIGH/CRITICAL CVEs in running images"], }