feat: include short description with each critical CVE in summary

summary now lists only CRITICAL vulnerabilities, formatted as
"CVE-ID: description" pairs joined by "; ". Description comes from
trivy's Title field, falling back to the first sentence of Description.
This commit is contained in:
ychangkim
2026-07-21 13:39:26 +09:00
parent f6eaf3c664
commit d2e804b482
+15 -4
View File
@@ -2,7 +2,10 @@ name: helm-catalog-cve-edge-post
# manifests/helm 카탈로그의 컨테이너 이미지 취약점을 스캔해 단일 JSON 요약으로 출력한다. # manifests/helm 카탈로그의 컨테이너 이미지 취약점을 스캔해 단일 JSON 요약으로 출력한다.
# [{"image": "...", "low": 0, "high": 0, "medium": 0, "critical": 0, # [{"image": "...", "low": 0, "high": 0, "medium": 0, "critical": 0,
# "scanned_at": "2026-07-13T06:19:44Z", "summary": "CVE-xxxx-xxxxx, ..."}, ...] # "scanned_at": "2026-07-13T06:19:44Z",
# "summary": "CVE-xxxx-xxxxx: short description; CVE-yyyy-yyyyy: ..."}, ...]
# summary 는 CRITICAL 취약점만 대상이며, CVE ID 별로 trivy 가 제공하는 Title(또는
# Description 첫 문장)을 짧은 설명으로 붙인다.
# 생성된 JSON 은 POST https://edge.gke.paasup.io/api/v1/cve-scans 로 전송한다. # 생성된 JSON 은 POST https://edge.gke.paasup.io/api/v1/cve-scans 로 전송한다.
# (X-CVE-API-Key 헤더 필요 — Repo Secret CVE_API_KEY, SSL 검증은 --insecure 로 스킵) # (X-CVE-API-Key 헤더 필요 — Repo Secret CVE_API_KEY, SSL 검증은 --insecure 로 스킵)
# #
@@ -131,14 +134,22 @@ jobs:
data = json.load(f) data = json.load(f)
image = data.get("ArtifactName", os.path.basename(path)) image = data.get("ArtifactName", os.path.basename(path))
counts = {"LOW": 0, "HIGH": 0, "MEDIUM": 0, "CRITICAL": 0} counts = {"LOW": 0, "HIGH": 0, "MEDIUM": 0, "CRITICAL": 0}
critical_ids = set() critical_desc = {}
for result in data.get("Results") or []: for result in data.get("Results") or []:
for vuln in result.get("Vulnerabilities") or []: for vuln in result.get("Vulnerabilities") or []:
sev = vuln.get("Severity") sev = vuln.get("Severity")
if sev in counts: if sev in counts:
counts[sev] += 1 counts[sev] += 1
if sev == "CRITICAL": if sev == "CRITICAL":
critical_ids.add(vuln["VulnerabilityID"]) vid = vuln["VulnerabilityID"]
if vid not in critical_desc:
desc = vuln.get("Title") or (vuln.get("Description") or "").split(". ")[0]
critical_desc[vid] = desc.strip()
summary = "; ".join(
f"{vid}: {desc}" if desc else vid
for vid, desc in sorted(critical_desc.items())
)
results.append({ results.append({
"image": image, "image": image,
"low": counts["LOW"], "low": counts["LOW"],
@@ -146,7 +157,7 @@ jobs:
"medium": counts["MEDIUM"], "medium": counts["MEDIUM"],
"critical": counts["CRITICAL"], "critical": counts["CRITICAL"],
"scanned_at": scanned_at, "scanned_at": scanned_at,
"summary": ", ".join(sorted(critical_ids)), "summary": summary,
}) })
with open(out_path, "w") as f: with open(out_path, "w") as f: