- Severity: CRITICAL
- CVE: CVE-2026-77596
- Ecosystems: go
- Packages: github.com/kubeflow/pipelines
## Summary
In multi-user mode, the Kubeflow Pipelines API server’s HTTP multipart upload endpoints (`POST /apis/v2beta1/pipelines/upload` and `POST /apis/v2beta1/pipelines/upload_version`) perform no authorization when the target namespace is empty. The authorization helper `canUploadVersionedPipeline` returns `nil`, skipping `SubjectAccessReview`, whenever the resolved namespace is the empty string (`backend/src/apiserver/server/pipeline_upload_server.go:401-403`). An empty namespace is how KFP addresses shared, cluster-wide pipelines and is the default whenever the caller omits the `namespace` query parameter, because `REQUIRE_NAMESPACE_FOR_PIPELINES` defaults to `false` and is unset in every shipped manifest. As a result, an arbitrary low-privilege tenant (or, when the API server is reachable, an unauthenticated caller) can create cluster-shared pipelines and inject new versions into existing shared pipelines, replacing the container image, command, and args that other tenants execute. The gRPC sibling for the same write, `canAccessPipeline`, instead remaps the empty namespace to the system namespace and authorizes, with a comment stating shared-pipeline writes “must still be authorized”. That confirms this is an omission, not intended behavior.
## Description
`uploadPipeline` and `uploadPipelineVersion` both build a `ResourceAttributes{Verb: create}` and delegate the access decision to `canUploadVersionedPipeline`:
“`go
// backend/src/apiserver/server/pipeline_upload…
Source: GitHub Security Advisories · 2026-11-09