Skip to main content

Kubernetes Quietly Corrected Three 'Fixed' CVEs That Were Never Patched — What That Means for Your Cluster's Threat Model

9 min readDora NodaDora Noda
Share
On this page

On May 26, 2026, the Kubernetes Security Response Committee published a blog post with an unusually blunt title: "Reconciling the Past: Correcting Records for Unfixed Kubernetes CVEs." The admission underneath it is simple and uncomfortable — three CVE records, some disclosed as far back as 2020, had carried a "fixed version" field telling every vulnerability scanner on the planet that upgrading past a certain release closed the hole. That field was wrong. There was no fix. On June 1, 2026, the Committee removed it, and every scanner that had been reporting a clean bill of health on these three issues started reporting them again — not because anything in the cluster changed, but because the record scanners had been trusting for years finally caught up with reality.

That's the headline. The more useful question for anyone running a self-hosted fleet is what "no fix available" actually means when it's sitting in your threat model instead of a changelog, and what a Cluster-API-managed pipeline needs to check that a version-number comparison alone won't catch.

The Correction, Concretely

The Security Response Committee's audit, done while generating machine-readable OSV files for the official Kubernetes CVE feed, found that three long-standing "unfixed" CVEs had incorrectly kept a fixed-version field from an earlier point in their history. A fourth, already correctly marked as unfixed, had its version format standardized in the same pass — evidence the Committee audited its entire no-fix set, not just the three it got wrong:

CVESeverityWhat the record said beforeWhat it says now (June 1, 2026)
CVE-2020-8561Medium (4.1)Carried a "fixed version" fieldField removed — affects all versions
CVE-2020-8562Low (3.1)Carried a "fixed version" fieldField removed — affects all versions
CVE-2021-25740Low (3.1)Carried a "fixed version" fieldField removed — affects all versions
CVE-2020-8554Medium (6.0)Already marked unfixed, non-standard version formatVersion format standardized only

None of these are new vulnerabilities. All three corrected CVEs were disclosed years ago, sat in scanner databases with an implicit "upgrade and you're clear" message, and are only now surfacing as live findings on clusters that were never actually patched.

Why These Three Have No Fix

Each one is a design trade-off rather than a bug, which is exactly why a code fix never shipped.

CVE-2020-8561 lets an actor who controls a MutatingWebhookConfiguration or ValidatingWebhookConfiguration redirect kube-apiserver's outbound requests toward internal networks, because the API server follows HTTP redirects the same way any standard HTTP client does. Restricting that behavior would break legitimate webhook integrations that rely on redirect-following. The documented mitigation is operational, not a patch: set the API server's log level below 10 so response bodies aren't logged, and run with --profiling=false.

CVE-2020-8562 is a time-of-check-to-time-of-use race in the API server's proxy. Kubernetes validates a webhook or aggregated API server's DNS name once, then resolves it again for the actual connection — and a non-standard DNS server can return a different answer the second time, bypassing the proxy's link-local and localhost restrictions. Fixing it structurally would mean pinning resolved IPs in ways that break split-horizon DNS and dynamic-IP environments many clusters depend on. The mitigation: run a local DNS caching resolver in front of the API server (dnsmasq or similar) with min-cache-ttl set high enough that the check and the connection see the same answer.

CVE-2021-25740 is a confused-deputy issue in Endpoints and EndpointSlice objects: because those APIs let a user specify arbitrary IP addresses, a tenant with write access to Endpoints in one namespace can redirect Service traffic to an IP in a completely different namespace or network segment. Closing it outright would mean changing how Endpoints has worked since early Kubernetes — architecturally disruptive for anything that depends on manually-managed endpoints (external service registration is a common legitimate use). The mitigation is RBAC: restrict who can write to Endpoints/EndpointSlice objects to the same trust boundary as the Services they back.

None of these get an upgrade path. All three get a permanent line in your cluster's threat model instead.

Why This Isn't Just a Kubernetes Problem

The uncomfortable part is that Kubernetes' own records were the accurate exception, not the rule, for how strained CVE data quality already was in 2026. NIST's National Vulnerability Database — the source most scanners lean on for enrichment — hit a backlog it publicly admitted it can't clear: CVE submissions grew 263% between 2020 and 2025, and in April 2026 NIST moved every unscheduled CVE published before March 1, 2026 into a permanent "Not Scheduled" enrichment category, expected to cover only 15–20% of ongoing volume with prioritized handling. Separately, NVD's CPE coverage — the structured data scanners need to match a CVE to a specific product and version — reached only about 41% of CVEs published in 2024, meaning roughly 60% of that year's disclosures lack the metadata a version-matching scanner needs to place them correctly in the first place.

The disagreement isn't limited to missing metadata, either. Academic analysis of CVEs scored by more than one database has found divergence rates above 50% for most of the past decade, peaking near 70% in 2023, with gaps large enough to move a vulnerability across an entire severity tier — a "Low" in one source and a "High" in another for the same identifier. A severity mismatch is a different failure mode than a wrong fixed-version field, but it's the same root cause: the CVE ecosystem's records are maintained by people and pipelines with their own backlogs, and "published" has never meant "verified."

Kubernetes catching and correcting its own three wrong records is the system working as intended — a project actively maintaining its own feed found and fixed a stale field, then published a blog post naming exactly which records changed and why, rather than quietly editing the database. The lesson for anyone downstream is the opposite of reassuring: if a security-conscious CNCF project with a dedicated response committee carried an inaccurate "fixed" field for years before catching it, a "fixed" field from a less actively maintained corner of the CVE ecosystem deserves the same default skepticism, not more trust.

What a Self-Hosted Cluster-API Fleet Should Actually Do

A Cluster-API fleet doesn't run "Kubernetes" in the abstract — it runs a specific node image, baked once per version by kubernetes-sigs/image-builder (or a provider-specific equivalent like CAPH's own image pipeline on Hetzner), then referenced by the version: field on every KubeadmControlPlane and MachineDeployment. That's exactly where CVE-ID matching and version-pinned scanning diverge in practice.

For most CVEs, a version-range check is legitimate. An OSV record typically looks like this:

json
{
  "type": "ECOSYSTEM",
  "events": [
    { "introduced": "0" },
    { "fixed": "1.31.9" }
  ]
}

A node image pinned to v1.31.10 clears that check correctly — there's a real fixed boundary, and the pinned version is past it. Before June 1, 2026, CVE-2020-8561's record had a comparable shape: a version boundary a scanner could resolve as "you're past the fix, no finding." After the correction, the entry instead has no fixed event at all — an open-ended range that OSV tooling reads as affecting every published version, including whatever a fleet is pinned to right now. The matching step a scanner runs — is this ID present, is my version past its fixed boundary — didn't change. The data underneath it did, silently, and the finding came back on unchanged infrastructure.

That's the discipline a Cluster-API pipeline needs layered on top of plain ID matching: run osv-scanner (or the Trivy Operator's equivalent, running in-cluster) against each node image's SBOM using the Kubernetes project's own OSV feed rather than trusting only a generic aggregator — and treat any Kubernetes finding whose OSV entry has no fixed event as a standing, version-independent finding. That finding doesn't belong in the same triage queue as an ordinary "upgrade available" alert; it needs the documented operational mitigation (restricted log level, DNS caching, tightened Endpoints RBAC) applied once, recorded as a waiver in the pipeline, and left there — not re-triaged and hopefully cleared on every node image rebuild, because it structurally never will clear.

The practical difference shows up at the exact moment a pipeline decides whether a node image is safe to promote. A gate that only checks "does osv-scanner report zero findings" will pass a freshly rebuilt image today and then start failing it tomorrow if the upstream feed changes underneath it — precisely what happened to every scanner pointed at CVE-2020-8561 on June 1, 2026, with no corresponding change to any cluster's actual configuration. A gate that instead separates findings into "has a fixed boundary, block until resolved" and "no fixed boundary, confirm the documented mitigation is applied and pass" survives that kind of record correction without a false alarm, because it was never trusting the absence of a finding as proof of safety in the first place — it was checking a specific, falsifiable claim about the record and a specific, verifiable mitigation on the running config.

Building that verify-don't-trust step into the image-build-to-admission pipeline is exactly the kind of platform plumbing bex.co is built around — an open-source, AI-native alternative to Render that reconciles a Cluster-API-managed fleet on hardware you own, rather than hiding that fleet behind someone else's managed control plane. Star the repo on GitHub if you're wiring your own patch-and-scan pipeline on top of CAPI.

Sources

All figures and technical details cited above are drawn directly from the linked sources.

Related articles

Run this on infrastructure you own

bex is the open-source, AI-native Render alternative — push a git repo and get a running HTTPS service on your own machines.

Get started with bex