GitHub reviewed GHSA-rjr3-43j3-4q8g (CVE-2026-77596) on November 9, 2026: Kubeflow Pipelines multi-user HTTP upload endpoints can skip authorization when the target namespace is empty, which is how cluster-wide shared pipelines are addressed by default. A low-privilege tenant — or an unauthenticated caller when the API server lacks an authenticating front door — can upload shared pipelines or new versions that replace container images, commands, and arguments other users execute. Upgrade to Kubeflow Pipelines 2.18.0 (fix commit 62516d8c525f) and set REQUIRE_NAMESPACE_FOR_PIPELINES=true until every cluster component is patched.
Kubeflow Pipelines (KFP) is the workflow engine behind many internal ML platforms, experiment trackers, and agent toolchains that spawn training or batch jobs from CI. The bug is not model poisoning in the abstract; it is supply-chain control over what code runs when someone clicks Run on a shared template.
TL;DR
| Question | Answer |
|---|---|
| Am I affected? | Multi-user KFP before 2.18.0, especially with shared pipelines and default namespace settings |
| Is there a fix? | 2.18.0 / commit 62516d8c525f (PR #14352) |
| Severity? | Critical, CVSS v3.1 9.6 (AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N) in advisory |
| Default config risk? | REQUIRE_NAMESPACE_FOR_PIPELINES defaults false; empty namespace allowed |
| Does data leave my machine? | Not from the CVE itself; poisoned runs can exfiltrate from inside jobs |
| Agent angle? | Agents that upload or version pipelines over HTTP inherit this auth gap |
Mechanism: HTTP upload vs gRPC authorization
The advisory contrasts two code paths in the API server:
HTTP multipart uploads (POST /apis/v2beta1/pipelines/upload and POST /apis/v2beta1/pipelines/upload_version) call canUploadVersionedPipeline in pipeline_upload_server.go. When resourceAttributes.Namespace is still empty after pipeline ID resolution — the case for shared/cluster-wide pipelines, or simply omitting the namespace query parameter — the function returns nil at lines 401–403 and never calls IsAuthorized / SubjectAccessReview.
gRPC pipeline APIs use canAccessPipeline in pipeline_server.go, which intentionally skips authorization only for read verbs on shared pipelines. For writes, comments state shared pipeline mutations must still be authorized against the KFP system namespace. The HTTP upload path contradicts that design.
Namespace validation reinforces the gap: ValidateNamespaceRequired rejects empty namespaces only when IsNamespaceRequiredForPipelines() is true, and REQUIRE_NAMESPACE_FOR_PIPELINES defaults to false and is not set in shipped manifests.
Net effect: shared pipeline writes over HTTP are reachable without the authorization checks gRPC writes require.
What "omit the namespace parameter" means in practice
The advisory walks through ValidateNamespaceRequired and IsNamespaceRequiredForPipelines(). In plain terms:
- Upload URLs accept a namespace query parameter naming where a pipeline version should live.
- When operators omit it — or tools default to cluster-wide templates — the resolved namespace becomes the empty string, which KFP treats as shared.
- With
REQUIRE_NAMESPACE_FOR_PIPELINESunset, that omission is valid, not an error. canUploadVersionedPipelinethen hits the early return forNamespace == ""and never calls SubjectAccessReview.
SDKs and notebooks that wrap upload_pipeline and do not pass a namespace therefore inherit this behavior silently. Agents that generate SDK snippets from documentation examples are especially likely to copy the minimal curl or Python sample without namespace scoping.
Platform engineers should treat "namespace omitted" as equivalent to cluster-wide write in threat models until every API server runs the patched build and the namespace requirement flag is on.
Proof points from the advisory
Researchers reproduced the issue against a real API server image (ghcr.io/kubeflow/kfp-api-server@sha256:621fdae9bfcc93405eca299c24f715bc7f17dbb76f1b53e8b2b35852e4d7d423) with MULTIUSER=true and unset REQUIRE_NAMESPACE_FOR_PIPELINES.
Documented results include:
- Shared pipeline create with only
kubeflow-userid: [email protected]and HTTP 200 - Attacker identity with no RBAC bindings anywhere in the cluster
- Victim namespace present without grants to the attacker
Example upload shape from the advisory:
curl -F [email protected] \
-H "kubeflow-userid: [email protected]" \
"http://APISERVER:8888/apis/v2beta1/pipelines/upload?name=shared-pwn"
When the API server is exposed without an authenticating proxy, the advisory notes the bypass may also be reachable without credentials, though the published CVSS vector assumes an authenticated low-privilege tenant scenario.
Attack chain for a poisoned shared pipeline
- Attacker obtains any valid tenant identity (or hits an exposed API server).
- Uploads a new shared pipeline or version with malicious
image,command, andargsin the pipeline YAML. - Victims run the shared template from the UI, SDK, or an automated agent workflow that references the cluster-wide name.
- Attacker code executes in victim namespaces with whatever service account the pipeline step inherits — often broader than the attacker's own RBAC.
This is classic cross-tenant supply chain: the artifact looks official because it lives in the shared catalog.
Timeline
| Date | Event |
|---|---|
| 2026-09-09 | Fix merged to master in kubeflow/pipelines#14352 (62516d8c525f) |
| 2.18.0 | Release carrying the fix per advisory |
| 2026-10-28 | GHSA first published |
| 2026-11-09 | GitHub Advisory Database reviewed/updated |
Who is affected
In scope:
- Multi-user Kubeflow deployments with shared pipelines enabled
- Clusters where the KFP API server is reachable from tenant networks, CI, or the public internet without an auth gateway
- Organizations where data scientists or agents upload pipelines through HTTP rather than gated CI
Mitigations while patching:
- Upgrade to KFP 2.18.0+
- Set
REQUIRE_NAMESPACE_FOR_PIPELINES=trueso empty namespaces fail validation - Block unauthenticated access to
/apis/v2beta1/pipelines/upload* - Audit shared pipeline versions for unexpected container images
Lower risk:
- Single-user mode installs (authorization helper short-circuits differently)
- Clusters that already require namespaces on every pipeline operation and enforce OAuth at the ingress
What this means if you run AI coding agents
Agents increasingly generate Kubeflow components or call the Pipelines SDK when a user says "train this and schedule it." That convenience reuses the same HTTP upload surface humans use.
Concrete checks:
- Inventory automation that calls
POST .../pipelines/uploadorupload_version— including notebook helpers and MCP wrappers. - Pin SDK and server versions together; an upgraded client against a vulnerable server still leaves you exposed.
- Treat shared pipelines like shared GitHub Actions workflows — review version history after the patch window.
- If agents store KFP endpoint URLs and tokens in repo
.envfiles, rotate them after any suspected unauthorized upload; see API keys in logs and environment variables.
For parallel control-plane bugs on ML infrastructure, see GPUStack CVE-2026-102895, the follow-on GPUStack SAML bypass CVE-2026-102894, and fastapi-code-generator RCE chain when agents scaffold APIs adjacent to training jobs.
Hunting unauthorized uploads after you patch
The advisory does not publish universal IoCs, but defenders on shared KFP clusters can prioritize:
- Pipeline version audit: Export shared pipeline metadata and diff
created_atagainst your change window. Look for container images from registries your team does not use. - Ingress logs: Search reverse-proxy access logs for
POST /apis/v2beta1/pipelines/uploadandupload_versionwith missing namespace query parameters. - Identity headers: Correlating
kubeflow-useridvalues on upload requests with HR identity is painful but worthwhile after incident; unexpected corporate emails on shared writes are a red flag. - Downstream run failures: Victim jobs that suddenly pull a new digest without a ticket often surface first in Argo / KFP UI run history rather than in API server logs.
If you use GitOps for manifests, confirm the live deployment actually sets REQUIRE_NAMESPACE_FOR_PIPELINES after you think you toggled it — drift between Terraform and the running ConfigMap has burned teams on similar flags.
Why empty namespace is the default footgun
Kubeflow treats empty namespace as "this pipeline is visible cluster-wide." That ergonomics choice helps platform teams publish golden paths for scientists. It also means any authorization bug on empty namespace becomes a cluster-wide write primitive.
The gRPC server's comments explicitly acknowledge the asymmetry: reads may skip auth for shared pipelines to keep the UI snappy; writes must map to the system namespace. HTTP uploads only ever perform writes, yet inherited the read shortcut. From a design-review perspective, this is the kind of dual transport inconsistency red teams hunt for — HTTP and gRPC should share one authorization matrix.
EPSS for this CVE was about 0.25% (16th percentile) when GitHub reviewed the entry on November 9, 2026 — low predicted exploitation probability in FIRST's model, but critical impact if your cluster exposes the API.
What Beam can and cannot do here
Beam does not sit in front of Kubeflow's API server and does not authorize Kubernetes pipeline uploads. Its relevance is indirect:
- If an agent on a developer laptop proposes shell or SDK commands that hit KFP upload endpoints, Claude Code or Codex PreToolUse hooks can deny matching curl patterns when workspace policy is in enforce mode — heuristic, hook-based, fail-open without cached policy.
- Beam's local collector keeps redacted records of those tool calls for review after you upgrade KFP.
That observability helps you learn that someone automated uploads; it does not stop a direct HTTP client bypassing the agent.
Related reading
- GPUStack loopback admin bypass (CVE-2026-102895)
- Symantec Skynet Mode and hijacked LLM endpoints
- x402 SDK flaws and agent wallet spending
- November 2026 attacks timeline
- GitHub advisory GHSA-rjr3-43j3-4q8g
- NVD CVE-2026-77596
Frequently asked questions
What is CVE-2026-77596?
It is a critical missing authorization flaw in Kubeflow Pipelines before the September 9, 2026 fix (2.18.0, commit 62516d8c525f). HTTP upload endpoints skip SubjectAccessReview when the pipeline namespace is empty, which is the default for shared cluster-wide pipelines when REQUIRE_NAMESPACE_FOR_PIPELINES is false.
What can an attacker do?
Create or version shared pipelines with attacker-chosen container images, commands, and arguments that other tenants later run. The advisory reproduced shared pipeline creation as an unprivileged kubeflow-userid header and notes unauthenticated access when the API server is reachable without an authenticating proxy.
Which versions fix it?
Kubeflow Pipelines 2.18.0 includes the fix merged in kubeflow/pipelines#14352. Patched pseudo-version is 0.0.0-20260909234119-62516d8c525f in the GitHub advisory database.
Is there a configuration workaround?
Set REQUIRE_NAMESPACE_FOR_PIPELINES true so empty namespaces fail validation, and ensure the API server is not reachable without authentication. The advisory notes the flag defaults false and is unset in shipped manifests.
Does this affect single-user Kubeflow?
The vulnerable branch is gated on multi-user mode. Single-user deployments do not take the same authorization path, but shared clusters used by data science and agent automation teams are in scope.
What should coding agent users do?
Audit any agent or notebook that calls KFP upload APIs or wraps kubeflow pipelines SDK uploads, upgrade the cluster, and review shared pipeline versions created after your last known-good backup for unexpected images or commands.
Comparison to other November 2026 pipeline and control-plane CVEs
November 9 brought several critical authorization issues on infrastructure coding agents touch:
| Issue | Product | Primary failure |
|---|---|---|
| CVE-2026-77596 | Kubeflow Pipelines | HTTP upload skips SAR on empty namespace |
| CVE-2026-102895 | GPUStack | Loopback requests promoted to admin |
| CVE-2026-63470 family | fastapi-code-generator | Untrusted OpenAPI text becomes Python |
KFP's bug is tenant isolation, not arbitrary RCE on the API process itself. The blast radius is whatever Kubernetes service accounts pipeline steps inherit — often cluster-admin is not required for meaningful damage if steps can reach object storage, metadata services, or internal APIs.
Teams running Notebook → Agent → KFP chains should treat pipeline YAML with the same suspicion as Dockerfiles agents commit: diff images on every merge, and run training jobs in namespaces without access to production secrets. Schedule a quarterly review of shared pipeline catalogs even when no CVE is active — authorization bugs are easier to find when you already know what "normal" images look like.
explainx.ai has background on agent harness evolution for readers tracking how automation surfaces keep shifting; Beam focuses here on the KFP authorization omission and patch path.
Advisory text, CVSS vector, and version numbers reflect GitHub and Kubeflow as of 2026-11-09.

