Skip to content

CVE Scanning

Container image CVE scanning is integrated into every custom image CI pipeline using Syft (SBOM generation) and Grype (vulnerability matching).

Pipeline Integration

flowchart LR
    code["Source / upstream bump"] --> build["build\ndocker buildx\nmulti-arch"] --> scan["scan\nSyft → SBOM\nGrype → CVE match"] --> notify["notify\nPushover priority 1\n(HIGH/CRITICAL only)"]
    build --> push["push :latest\nregistry.mdapi.ch/mdapi/"]
    scan --> artifact["SBOM artifact\nSPDX JSON\n7-day retention"]

The scan stage runs after the image is built but the result never blocks the pipeline (allow_failure: true). A CVE finding sends a notification for human review — the deployment still proceeds because production systems cannot be held hostage by upstream vulnerabilities that may have no fix yet.

Covered Images

9 custom images are scanned on every CI run (triggered on push, and every 4 hours via schedule):

Image Base Registry
gitlab-webservice-ee GitLab EE registry.mdapi.ch/mdapi/
gitlab-sidekiq-ee GitLab EE registry.mdapi.ch/mdapi/
keycloak quay.io/keycloak/keycloak:26.x registry.mdapi.ch/mdapi/
chrony debian:stable-slim registry.mdapi.ch/mdapi/
certspotter golang registry.mdapi.ch/mdapi/
autoconfig nginx:alpine registry.mdapi.ch/mdapi/
opennic-tier2 debian:stable-slim registry.mdapi.ch/mdapi/
threadfin debian:stable-slim registry.mdapi.ch/mdapi/
joplin-mcp python:slim registry.mdapi.ch/mdapi/
znc debian:stable-slim registry.mdapi.ch/mdapi/

SBOM Artifacts

Syft generates an SPDX JSON SBOM for each image build. This provides:

  • A point-in-time snapshot of every package installed in the image
  • A queryable artifact for retroactive CVE analysis when new vulnerabilities are published
  • Compliance evidence for software supply chain auditing

SBOM artifacts are stored in GitLab CI for 7 days per build.

Runtime CVE Scanning

A Windmill flow (f/security/pod_image_cve_scan) runs daily and scans the images of all currently running pods against the Grype database. This catches:

  • Third-party images (from docker.io, ghcr.io) that are not built from source
  • Newly published CVEs affecting images that passed scan when built

Results are sent via Pushover with the affected image and CVE IDs.