Skip to main content

Container CVE Triage: Local Scans, Three Buckets, and Explainable Policies

· 5 min read
MCPBundles

TL;DR

  • Vulnerability Intelligence runs Trivy on your Mac via Desktop, enriches with NVD + CISA KEV + EPSS, and buckets every CVE into exploit priority / patch today / defer — each row includes a plain-English reason.
  • On our own bases (June 2026 scans): python:3.13-slim has 46 unique CVEs and 0 patch-today rows under balanced ( 2 under permissive_patches ); node:20-slim has 97 unique CVEs and 29 patch-today rows — same scanner, different nightly workload.
  • Built for security and platform teams who already have Trivy output and need shared rules across client images, not another dashboard that dumps CVSS-sorted noise.

Picture Monday after a base-image rebuild. Trivy finished overnight. The spreadsheet has 103 rows before anyone's had coffee. That's the moment this post is about — not picking Wiz over Snyk, but agreeing what actually patches tonight.

In April we open-sourced an MCP server that combines NIST NVD, CISA KEV, and EPSS into a composite risk score. That solved ranking — why a CVSS 5.0 in active ransomware campaigns should beat a CVSS 9.8 nobody is exploiting.

The next bottleneck is operations: your scanner still dumps hundreds of rows, and every team reinvents spreadsheet triage. Paste-JSON workflows do not scale when you run ten client images a week.

We shipped a hosted path that closes the loop: Desktop runs Trivy on your machine, the cloud enriches findings, and scan_triage buckets every CVE with a bucket_reason you can tune via policy presets.

Try Vulnerability Intelligence on MCPBundles — or keep reading for the bucketing rules and real numbers from our own Dockerfiles.

The workflow (no paste step)

  1. Install MCPBundles Desktop and connect the tunnel.
  2. Bind Container Scan on the Vulnerability Intelligence bundle with Trivy installed locally.
  3. Ask your agent: "Scan node:20-slim with policy_preset balanced."

scan_triage shells out to Trivy through the Desktop proxy, then queries NVD + KEV + EPSS in parallel. You still can paste Trivy JSON when Desktop is offline — but the default path is target=, not copy-paste.

Three buckets, same rules every image

BucketDefault rule (balanced)
Exploit priorityIn CISA KEV, or EPSS ≥ 50%
Patch todayVendor fix reported and composite tier ≥ HIGH (and not already exploit priority)
DeferEverything else

Every row carries bucket_reason — e.g. "defer — EPSS 3.76% below exploit threshold 50%; no vendor fix flagged in scanner output."

High CVSS in defer is intentional. Scanner severity measures impact; EPSS measures likelihood. CVE-2005-2541 shows CRITICAL in Trivy with ~4% EPSS and no fix — paging on CVSS alone would burn your weekend.

Policy presets change the patch queue

Same scan, different policy:

PresetPatch-today barWhen to use
balancedFix exists + tier ≥ HIGHDefault nightly triage
permissive_patchesFix exists + tier ≥ MEDIUMSlim bases with pip/npm fixes
strictFix exists + tier ≥ CRITICALEmergency freeze — libc noise stays defer
on_callLower EPSS exploit thresholdIncident mode — watch more EPSS movement

Override any preset field: epss_exploit_threshold, patch_today_min_tier, patch_today_requires_fix.

Real numbers from our Dockerfiles

Trivy → NVD + KEV + EPSS → bucket (June 2026, local Desktop scans):

ImageRoleUnique CVEsExploit priorityPatch today (balanced)Defer
python:3.13-slimAPI backend base4600103 (98% deferrable)
node:20-slimFrontend/widgets base97029136 (82% deferrable)

Same toolchain, different ops pressure. The Python base is monitor-and-rebuild-on-cadence. The Node base has libc/dpkg rows worth scheduling this sprint.

Under permissive_patches, python:3.13-slim surfaces 2 patch-today pip CVEs (MEDIUM tier, fixes available) that balanced defers. Policy choice is not cosmetic — it changes what humans review.

What you see in Studio

The scan triage workspace shows policy summary, bucket counts, patch-today rows with reasons, and a CRITICAL in defer — why? section for the top deferred CRITICAL findings. The screenshot above is a real python:3.13-slim run under permissive_patches.

Example agent prompts:

  • "Scan node:20-slim with balanced policy and summarize patch_today."
  • "Scan python:3.13-slim with permissive_patches — why did CRITICAL CVEs defer?"
  • "Compare CVSS rank vs composite rank for the latest node:20-slim scan."

Scoring still matters

Bucketing sits on top of the composite score from the April post: CVSS base × EPSS multiplier + KEV bonus + ransomware bonus, clamped 0–10. Buckets answer what to do tonight; composite score answers how scary relative to exploitation reality.

Open source + hosted

Not a Wiz/Snyk replacement for coverage. The win is consistent prioritisation rules across environments when you already have scanner output and need humans to agree on what patches tonight.