Repository navigation
security(trivy): declare the trusted registries so KSV-0125 gates instead of noises - #3216
Conversation
…tead of noises
KSV-0125 ("Restrict container images to trusted registries") ships a default
trusted list of Azure ACR, AWS ECR and GCR only — read from the check's own
rego, not inferred. This repository uses none of those three, so the check
flagged every container it declares: 27 findings, the single largest family on
this tree, none of which said anything about supply-chain risk.
Declare the four registries actually in use (derived from the tree: quay.io,
docker.io, registry.k8s.io, ghcr.io) via --config-data. The check reads
data.ksv0125.trusted_registries and uses it instead of its defaults, which turns
a permanently-failing check into one that can catch an unexpected registry.
The check proved it still discriminates by surviving on one container:
vault-config's store-keys ran `alpine/k8s`, whose first path segment is a Docker
Hub namespace rather than a registry host, so the check read the registry as
"alpine". Fixed at the manifest by writing it fully-qualified with the same
pinned digest, matching the 11 docker.io images already written that way.
Measured with scripts/megalinter-scan-counts.sh: trivy 93 -> 66 across 29 -> 16
targets; checkov unchanged at 0. Ablation: deleting the single quay.io entry
returns exactly 11 findings, all quay.io-hosted, so the list is load-bearing.
Part of #2787
✅
|
Verified in CI, not just locallyA green CI ran the argument — from the mega-linter log at CI reproduces the number: That is the same 93 → 66 across 29 → 16 measured with Also checked
|
@coderabbitai review |
|
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository YAML (base), Organization UI (inherited) Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
Included review availability: Your plan includes up to 1 review per rolling hour; 0 remain after this review. 📜 Recent review details🧰 Additional context used📓 Path-based instructions (1)**/*.{yaml,yml}📄 CodeRabbit inference engine (AGENTS.md)
Files:
🧠 Learnings (7)📚 Learning: 2026-07-01T21:13:36.950ZApplied to files:
📚 Learning: 2026-07-02T06:32:09.574ZApplied to files:
📚 Learning: 2026-08-08T15:10:00.349ZApplied to files:
📚 Learning: 2026-08-08T15:10:00.350ZApplied to files:
📚 Learning: 2026-08-08T21:23:32.529ZApplied to files:
📚 Learning: 2026-08-11T12:41:28.242ZApplied to files:
📚 Learning: 2026-08-10T13:01:12.782ZApplied to files:
🔇 Additional comments (6)
📝 WalkthroughWalkthroughThe change adds KSV-0125 trusted-registry configuration for four registries. Trivy scans now load data from 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
@codex review |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Requesting Cursor Bugbot at this head. CodeRabbit refused (review limit, 41-minute window) and Codex refused (account usage limit for code reviews), both at |
|
@cursor review |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_0adf3280-9705-4540-94aa-01cc5c8335c0) |
Review-lane state at
|
| Lane | Outcome | Evidence |
|---|---|---|
| CodeRabbit | refused | "Review limit reached — next review available in 41 minutes"; head status Review rate limited |
| Codex | refused | "You have reached your Codex usage limits for code reviews" |
| Cursor Bugbot | never ran | check-run conclusion: neutral + output.title: Error, with "Bugbot couldn't run - usage limit reached" |
Bugbot's neutral/Error pair is the did-not-run shape, not a findings result — no inline comments and no review object accompany it. Only a team admin can lift the Cursor and Codex ceilings.
Not securing a review at this head yet, deliberately. This PR carries a second blocker that requires a new commit to clear: GitHub's managed CodeQL run failed in Initialize CodeQL with a runner-side API rate limit exceeded, and it cannot be re-run — POST .../rerun-failed-jobs returns 403 This workflow run cannot be retried, which is expected for an event: dynamic run with no workflow file in the repository. The Require code scanning results ruleset requires CodeQL results, so that has to resolve before merge. Any push to fix it would stale a review secured now, so the review is sequenced after it rather than spent twice.
CodeRabbit's window reopens at roughly 15:13Z; it is the free lane and therefore the one to spend first.
… path-scoped ignores The reproduction script exists to produce numbers comparable to CI's, and every other deliberate deviation from the CI command is documented in its header. The scan root was not, and getting it wrong inflates the count silently. Measured on this tree with trivy v0.74.0, subcommand and flags held identical and the scan root the only variable: a root-scoped run reports 66 findings across 16 targets, a k8s/-scoped run reports 133 across 62. Every check ID appearing only in the narrowed arm is one .trivyignore.yaml already dispositions, because those globs are written repository-root-relative and stop matching once the root moves. The failure direction is what makes it worth a warning: it reads as more backlog rather than as a broken measurement.
@coderabbitai review |
|
✅ Action performedReview finished.
|
Resolution record — CodeRabbit ancillary "Merge Risk" note at
|
| Location | Text | Status |
|---|---|---|
.mega-linter.yml:100 |
trivy 66 in the local v0.74.0 reproduction | current |
.mega-linter.yml:124 |
went 109 → 93 (KubeVirt/CDI RBAC breadth) | historical |
.mega-linter.yml:140 |
went 93 → 66 across 29 → 16 targets | historical |
scripts/megalinter-scan-counts.sh:35 |
66/16 at root, 133/62 at k8s/ |
current |
The current figure was independently re-measured on this head with trivy v0.74.0 using the CI
invocation from the repository root: 66 findings across 16 targets, matching the documented value
exactly. No text asserts a superseded current count.
Readiness
Programmatically tested. All required checks green at e3734f62, including Analyze (actions)
and CodeQL — the failure that blocked the previous head was a runner-side rate limit in
Initialize CodeQL on a GitHub-managed run that returns 403 cannot be retried, so it needed a new
commit rather than a re-run. 🧹 Lint - mega-linter passes on the changed script; bash -n parses it.
Reviewed. CodeRabbit green at this exact head (above).
Tried and evaluated as a user. The registry list was ablation-verified when it landed: removing
the single quay.io entry returns exactly 11 findings, all 11 quay.io-hosted. This head's added
documentation was verified by running the thing it documents — both scan roots, same subcommand and
flags, root as the only variable: . → 66 findings/16 targets, k8s/ → 133/62. Every check ID
appearing only in the narrowed arm (KSV-0022, KSV-0037, KSV-0053, KSV-0109, KSV-0114, KSV-0117) is
one .trivyignore.yaml already dispositions, and KSV-0037 alone accounts for 47 of the 67 extra —
which is the mechanism the warning describes, observed rather than reasoned about.

Why
Our container-image security check was switched on but effectively blind. Trivy ships trusting only Amazon, Google and Microsoft registries — and we use none of them — so it reported every single container we run as coming from an untrusted registry. That is 27 findings that told us nothing except "this is not an AWS shop", and it is a large part of why this scanner is still parked as non-blocking.
A check that always fails is a check nobody can act on. If someone added a workload pulling from a registry we do not trust, today it would look exactly like the 27 findings already there.
What
Declares the four registries we actually pull from, so the check compares against our real supply chain instead of a cloud vendor default. It now passes on what we legitimately use and stands out on anything else.
One image was also written ambiguously enough that the check misread where it came from; it is now written in full, pointing at the same pinned image as before.
It also records a way of measuring this backlog that quietly gives the wrong answer: checking only the Kubernetes folder rather than the whole repository doubles the reported number, because the exemptions we have already agreed stop applying. That reads as more work to do rather than as a broken measurement, so the warning now sits next to the instructions.
Security floor gained: an image from an unexpected registry is now a visible finding rather than being lost in permanent noise.
Everyday cost: none — no new step for anyone. Adding a registry later is one reviewed line in a documented file. The scanner backlog on this tree drops by roughly a third (93 → 66 findings, 29 → 16 affected files), which makes the remaining work easier to see.
This is one slice of a larger backlog, not the whole of it — the scanner stays non-blocking until the rest is worked off.
Part of #2787