The Cache Did Not Know About Namespaces: Kubeflow CVE-2026-88982

Multi-tenancy in ML platforms keeps failing at the same seam: a shared service that was built before tenant isolation was a requirement. CVE-2026-88982 (GHSA-2xwh-426q-42c5, CVSS 3.1 5.4 Medium) is the latest instance. The legacy Kubeflow Pipelines V1/raw-Argo execution cache computes its cache key from selected template fields without the Kubernetes namespace, uses that key alone for lookups and duplicate checks, and trusts the mutable pipelines.kubeflow.org/execution_cache_key annotation when publishing outputs. In a multi-user deployment where tenant namespaces share the cache service, a tenant with ordinary workload-submission privileges can read another namespace’s cached step outputs — or seed the cache first, so a victim tenant’s matching step reports the attacker’s outputs instead of running its own containers. NVD published the CVE on 5 November 2026; the fix is 2.18.0 (affected: kfp-cache-server at or below 2.17.3).

A collision you can arrange on purpose

The advisory is careful about what this is and is not. It is not a cryptographic hash collision: the weakness is an application-level cache-key collision caused by a missing tenant scope, so known or shared pipeline templates produce the same key deterministically — no brute force required, no narrow race to win (CVSS attack complexity Low, no user interaction). A tenant submits a step whose cache-relevant template fields match another tenant’s step, and the shared cache happily serves across the namespace boundary in either direction: read someone else’s cached outputs, or write outputs that someone else’s pipeline will then consume as its own. That second direction is the one to take seriously for ML workloads: a poisoned cache entry does not just leak data, it substitutes attacker-chosen artifacts — metrics, model files, evaluation results — into another team’s automated execution, silently. The advisory establishes cross-namespace confidentiality and integrity impact and explicitly does not claim arbitrary code execution, an honest scope that makes the finding more credible, not less.

Scope boundaries matter for remediation. The flaw sits in the Argo-template cache mutating webhook and its cache-server storage path; standard KFP V2 component pods bypass this webhook cache, and the separate V2 cache implementation is outside the advisory’s scope. Exploitation also requires the affected configuration to actually be present: multiple tenant namespaces sharing the legacy cache service, cache-enabled V1/raw-Argo steps, and entries satisfying the staleness policy — with the standard multi-user setup watching pods across namespaces. If your deployment is single-tenant, V2-only, or cache-disabled, this is a patch-on-schedule item. If you run shared V1 caching across tenants — exactly the cost-saving configuration platform teams love — treat it as a tenant-isolation break and prioritize accordingly.

The pattern, not just the patch

This is the second Kubeflow tenant-boundary failure we have covered in under a month: mid-October brought CVE-2026-110220, where a tenant-controlled annotation steered the controller’s service-account token. Twice now, the trust decision has lived in a mutable annotation on a tenant-controlled object. Platform teams running Kubeflow — or any shared ML control plane — should read the pair as one lesson: enumerate every place a tenant-supplied field (annotations, labels, template fields, cache keys) crosses into a cluster-scoped or shared-namespace decision, and verify the tenant scope travels with it. Caches, schedulers and admission webhooks are where these bindings quietly go missing.

What to actually do

  1. Upgrade to Kubeflow Pipelines 2.18.0 or later (affected: kfp-cache-server at or below 2.17.3; fix PR #14359, commit 620d0cc). If you share the legacy execution-cache service across tenant namespaces with cache-enabled V1/raw-Argo steps, prioritize the rollout.
  2. After patching, flush or invalidate pre-existing shared cache entries — entries seeded before the fix carry no tenant scope, and there is no reliable way to distinguish legitimate shared hits from planted ones after the fact.
  3. Audit whether you even need the legacy path: V2 component pods bypass the affected webhook cache entirely. Migrating tenants off V1/raw-Argo caching shrinks this class of exposure, not just this CVE.
  4. Review pipeline outputs produced by shared cached steps during the exposure window for substitution, not just exfiltration — the integrity direction (your pipeline consuming someone’s planted outputs) is the higher-consequence failure for training and evaluation integrity.

Our verification was read-only. We read the full NVD JSON record for CVE-2026-88982 first-hand (published 5 November 2026, status Received, description matching the advisory, refs to fix commit 620d0cc, PR #14359, the 2.18.0 release tag and GHSA-2xwh-426q-42c5) and the complete GHSA-2xwh-426q-42c5 record via the GitHub API first-hand (published 28 October 2026, severity medium, CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N score 5.4, vulnerable range at or below 2.17.3, patched 2.18.0, V1-cache scope with V2 explicitly out of scope, no-RCE scope statement). We checked the site search index for 88982 and kubeflow and found no overlap — the October Kubeflow post covers a different flaw (CVE-2026-110220, controller token via annotation). We ran no cluster, submitted no pipeline, seeded no cache entry, and contacted no vendor. Brave Search was used for discovery only.

Sources: