Why registry.gitlab.com Went First: Eight Images, No Exclusions, the Largest CVE Block
Queue order for routing registries through Harbor was chosen by value, not size: gitlabcom carries 8 images, zero excluded namespaces, and roughly 1,195 fixable Critical+High findings — the single largest CVE block in the estate.
When nine registries wait to be routed through Harbor, the queue order is a prioritization exercise. The instinct is size: route the biggest registry first. The estate data said otherwise.
The table that decided it
| Order | Registry | Project | Images | Why |
| 1 | registry.gitlab.com | gitlabcom | 8 | enabled first — largest CVE block, ~1,195 C+H |
| 2 | ghcr.io | ghcr | 11 | second-largest routable block |
| 3 | quay.io | quay | 9 | touches OpenBao — needs practice first |
| 4 | registry.k8s.io | k8s | 3 | ingress-nginx DaemonSet + external-dns |
| 5 | mirror.gcr.io | gcrmirror | 2 | your own scanner — safest learning ground |
| 6–9 | ecr, dragonflydb, redhat, fluentbit | — | 1 each | completeness only |
registry.gitlab.com wins on three axes at once: eight images, no excluded namespaces (nothing in it runs anywhere that must keep pulling direct), and roughly 1,195 fixable Critical+High findings — the largest single block in the estate. One MR, the highest concentration of risk retired.
Eight images, zero exclusions, ~1,195 fixable Critical+High. The last four registries buy four images between them — do them for completeness, not for impact.
The measured-candidates counterpoint
The per-registry blast-radius table exists for a second reason: the queue is not just value-ordered, it is caution-ordered within the value tiers. quay has nine images but touches OpenBao's StatefulSet — the instance that holds every secret in the cluster and needs unsealing after a restart. The runbook puts it after you have done the procedure a few times, and says to do it alone. dragonflydb touches GitLab's Redis and carries an explicit note that skipping it entirely is a reasonable choice — it buys one image.
Prioritization is not a ranking of registries; it is a ranking of registry × blast radius, and both columns are measured.
Where the 1,195 came from
The "~1,195 fixable Critical+High" figure is not a guess; it is the estate aggregation that made the decision obvious. The deduplicated image/CVE data — the same data vuln-exporter publishes with its fixable dimension — showed the GitLab component images (gitaly, gitlab-shell, the webservice chain and their dependencies) as by far the largest concentrated block of fixable Critical+High in the cluster. The top CVE contributors overall were already known: gitaly at 393, gitlab-shell at 302, the CNPG postgres image at 251, argocd at 228. The registry.gitlab.com images carry most of the first two.
That concentration is what made eight images the highest-value move. Routing gitlabcom did not reduce the CVEs by itself — the fix is still the version bump — but it made every one of those images scan-on-push, SBOM-generated, and Copacetic-discoverable, which turns the eventual fix into a one-click promotion path instead of a rebuild pipeline nobody had built.
The exclusions column, read carefully
For most registries the "must stay direct" column is where the hard thinking lives. For registry.gitlab.com it is empty — no GitLab-registry image runs in an excluded namespace — which is why it could go first despite carrying the biggest CVE block. Value ordering and safety ordering agreed, and when the two agree, move.
The contrast is quay.io: 16 images total, 9 routable, and the 9 include images running in openbao — the StatefulSet that holds every secret in the cluster and needs unsealing after a restart. Same value tier, different blast radius entirely. The runbook's resolution is procedural rather than analytical: do quay after the procedure is muscle memory, do it alone, and verify bao status unsealed before moving to the next thing.
Renovate is still the primary remediation path
One clarification the docs insist on: routing an image does not fix it. For chart-supplied images — and all 36 workloads in this cluster are Helm releases — the image tag comes from the chart, and the remediation is the Renovate MR that bumps the chart. Routing makes the fix land better: scan-on-push re-evaluates on every upstream update, the SBOM is current, and a Copacetic candidate is possible. The version bump remains the fix. The two systems compose: routing feeds discovery, Renovate feeds the fix, and the promotion pipeline (later in this series) feeds the result back into the cluster safely.
Next: the pull test — how to read a pod's failure modes so a pass never looks like a fail.