GHSA-rjr3-43j3-4q8g: Kubeflow Pipelines API server lacks authorization for shared pipeline uploads

  • 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