Kubeflow Pipelines 跨租户代码执行(CVE-2026-77596)
Kubeflow Pipelines 2.18.0 之前对共享管道上传跳过授权,低权限租户可在其他命名空间执行代码。2.18.0 已修复。
TL;DR
- 低权限租户可以在没有 Kubernetes SubjectAccessReview 的情况下上传共享管道,或为现有共享管道添加新版本。该公告于 2026 年 10 月 28 日发布。
- Kubeflow Pipelines 2.18.0 之前在多用户模式下受影响,此时
REQUIRE_NAMESPACE_FOR_PIPELINES为 false,这是默认值。跟随最新版本且未固定版本的定期运行会在另一个租户的命名空间中执行注入的管道。 - CVE 记录评分为 CVSS v3.1 9.6 Critical。没有公开概念验证,也没有在野利用报告,截至 2026 年 11 月 6 日该 CVE 不在 CISA KEV 目录中。
- 升级到 Kubeflow Pipelines 2.18.0 或更高版本。如果无法升级,请在管道操作中要求命名空间,并在 API 服务器前放置认证代理;参见“如何修复?”。
我受影响吗?
只有在以下条件全部成立时才受影响:
- 集群运行 Kubeflow Pipelines 2.18.0 之前的版本。公告将 2.17.3 及以下版本列为受影响。
- API 服务器以多用户模式运行。单用户安装完全跳过授权路径,不受此缺陷影响。
REQUIRE_NAMESPACE_FOR_PIPELINES为 false。默认值为 false,随附清单中也没有设置,因此默认的多用户安装会暴露。- 攻击者能访问 API 服务器。如果可以直接访问而没有认证代理,未认证调用者也能利用该绕过。在认证代理后面,调用者需要有效的低权限租户身份。
- 在代码执行阶段,目标命名空间中存在跟随最新管道版本且未固定版本的定期运行。固定版本或内嵌规范的运行不会被替换。
API 服务器是 kubeflow 命名空间中的 ml-pipeline 部署。HTTP 上传端点是 POST /apis/v2beta1/pipelines/upload 和 POST /apis/v2beta1/pipelines/upload_version,同一服务器也提供较早的 v1beta1 路径。
| 分支 | 受影响版本 | 修复版本 |
|---|---|---|
| Kubeflow Pipelines | 2.18.0 之前的所有版本(公告:至 2.17.3) | 2.18.0(2026 年 10 月 28 日发布) |
检查镜像标签和命名空间设置:
kubectl -n kubeflow get deploy ml-pipeline -o jsonpath='{range .spec.template.spec.containers[*]}{.name}{" "}{.image}{"\n"}{end}'
kubectl -n kubeflow get deploy ml-pipeline -o yaml | grep -i REQUIRE_NAMESPACE_FOR_PIPELINES
镜像标签低于 2.18.0,且没有 REQUIRE_NAMESPACE_FOR_PIPELINES 条目或值为 false,就符合暴露的默认配置。变量缺失时,服务器使用 false。
如何修复?
- 升级到 Kubeflow Pipelines 2.18.0 或更高版本。2.18.0 版本是第一个包含授权修复的版本;请应用与安装方式匹配的清单。
- 如果现在无法升级,请在 API 服务器上设置
REQUIRE_NAMESPACE_FOR_PIPELINES=true。验证会在上传到达未保护分支前拒绝空命名空间。这是缓解措施而非修复:调用者仍可指定不属于自己的命名空间,而后续检查才是补丁修复的部分。 - 在 API 服务器前放置认证代理,不要直接暴露它。公告指出,可直接访问的服务器会让未认证调用者利用该绕过。对每个请求进行认证的代理会消除该路径。
- 审计共享管道及其版本中的容器镜像、命令和参数,查找无法识别的项,并检查跟随最新版本的定期运行。
厂商公告没有代码级缓解措施。升级是唯一完整的修复。
根本原因是什么?
HTTP 上传路径在目标命名空间为空时由授权助手直接返回成功,因此共享管道上传永远到不了 SubjectAccessReview。2.17.3 中 backend/src/apiserver/server/pipeline_upload_server.go 的助手如下:
func (s *PipelineUploadServer) canUploadVersionedPipeline(r *http.Request, pipelineID string, resourceAttributes *authorizationv1.ResourceAttributes) error {
if !common.IsMultiUserMode() {
// Skip authorization if not multi-user mode.
return nil
}
if len(pipelineID) > 0 {
namespace, err := s.resourceManager.FetchNamespaceFromPipelineId(pipelineID)
if err != nil {
return util.Wrap(err, "Failed to authorize with the Pipeline ID")
}
if len(resourceAttributes.Namespace) == 0 {
resourceAttributes.Namespace = namespace
}
}
if resourceAttributes.Namespace == "" {
return nil
}
resourceAttributes.Group = common.RbacPipelinesGroup
// ... IsAuthorized() runs only after this point
}
空命名空间是 Kubeflow Pipelines 表示集群级共享管道的方式。它也是调用者省略 namespace 查询参数时的默认值。能够拒绝它的验证只在 IsNamespaceRequiredForPipelines() 为 true 时运行:
func ValidateNamespaceRequired(namespace string) error {
if common.IsMultiUserMode() &&
common.IsNamespaceRequiredForPipelines() &&
namespace == "" {
return util.NewInvalidInputError("Namespace is required for pipeline operations")
}
return nil
}
IsNamespaceRequiredForPipelines() 读取 REQUIRE_NAMESPACE_FOR_PIPELINES,默认值为 false,manifests/ 下没有清单设置它。同一写入的 gRPC 路径,即 pipeline_server.go 中的 canAccessPipeline(),行为相反:它在 create、update 和 delete 时把空命名空间重新映射到系统命名空间,并注释说共享管道的写入仍必须经过授权。因此 HTTP 助手是遗漏,而不是有意的例外。
如何被利用?
- 攻击者访问 API 服务器。没有认证代理时不需要账户。在代理后面,低权限租户账户即可。
- 攻击者向
/apis/v2beta1/pipelines/upload发送不带namespace参数的多部分 POST,或向/apis/v2beta1/pipelines/upload_version发送带现有共享管道 ID 的请求。 canUploadVersionedPipeline()看到空命名空间并返回nil。不会发送 SubjectAccessReview。- 上传创建新的共享管道,或向现有共享管道附加新版本。版本携带攻击者的容器镜像、命令和参数。
- 在另一个租户的命名空间中,跟随最新版本且未固定版本的定期运行会取得注入的规范。
- 运行在受害命名空间中用该运行的服务账户启动攻击者的容器。该账户的 Kubernetes 权限随即作用于攻击者的代码。
请求形式是标准的 KFP 多部分上传。没有公开概念验证代码;公告描述了端点和缺失的检查。
攻击如何展开?
空命名空间跳过授权调用,共享管道版本把攻击者的容器带入另一个租户的定期运行。
攻击者能做什么?
攻击者可以在另一个租户的命名空间中,以该租户定期运行的服务账户执行任意容器。这里完整列出所有条件:
- Kubeflow Pipelines 低于 2.18.0。
- 多用户模式,且
REQUIRE_NAMESPACE_FOR_PIPELINES为 false 或未设置。 - 攻击者能访问 API 服务器,直接访问或通过允许低权限账户的认证代理。
- 版本注入路径需要现有共享管道;创建路径需要创建新共享管道的权限。
- 受害命名空间中存在跟随最新版本且未固定版本的定期运行。
影响包括读取该运行服务账户可读的命名空间密钥、修改其资源以及利用其网络位置。具体影响取决于服务账户的 role binding。固定版本或内嵌自身规范的运行不会被该路径替换。公告没有展示认证代理保护服务器时的未认证路径。
为什么修复有效?
修复把空命名空间映射到 KFP 系统命名空间,并让现有的 SubjectAccessReview 做决定,因此共享管道写入像其他写入一样被授权。pipeline_upload_server.go 中的补丁如下:
if len(pipelineID) > 0 {
namespace, err := s.resourceManager.FetchNamespaceFromPipelineId(pipelineID)
if err != nil {
return util.Wrap(err, "Failed to authorize with the Pipeline ID")
}
if len(resourceAttributes.Namespace) == 0 {
resourceAttributes.Namespace = namespace
}
}
- if resourceAttributes.Namespace == "" {
- return nil
+ if s.resourceManager.IsEmptyNamespace(resourceAttributes.Namespace) {
+ // Shared-pipeline writes require authorization in the KFP system namespace.
+ resourceAttributes.Namespace = common.GetPodNamespace()
}
resourceAttributes.Group = common.RbacPipelinesGroup
代码现在对共享写入调用 IsAuthorized(),使用 API 服务器运行所在的命名空间。无法在该命名空间创建管道的调用者会被拒绝。修复还增加了 recordingSubjectAccessReviewClient 测试矩阵,覆盖共享和带命名空间的上传、版本上传、允许和拒绝的情况以及单用户模式,因此空命名空间分支会在 CI 中执行。
修复对公告提到的两个 HTTP 端点来说是完整的。它不改变 RBAC 设计:已经拥有共享管道写入权限的租户保留该权限,授权决定由集群做出。
如何检查是否已遭入侵?
厂商没有发布入侵指标。请检查 API 服务器日志和共享管道清单:
# Pipeline upload requests and authorization failures in the API server log.
kubectl -n kubeflow logs deploy/ml-pipeline --since=720h | grep -Ei 'upload|SubjectAccessReview|Authorization Failure'
# Shared pipelines visible through the API.
kubectl -n kubeflow port-forward deploy/ml-pipeline 8888:8888 &
curl -s http://localhost:8888/apis/v2beta1/pipelines | head -c 2000
在多用户安装中,没有命名空间的管道就是共享管道。检查每个共享管道及其版本,把每个版本的容器镜像、命令和参数与团队预期进行比较。然后列出跟随最新版本的定期运行,检查其最近运行历史中是否有您未部署的镜像。当审计策略包含 SubjectAccessReview 调用时,Kubernetes 审计日志会记录这些调用。在 Request 或更高的审计级别,审查正文包含调用者身份。如果启用了请求日志,请在 ml-pipeline 或代理的访问日志中查找上传请求本身。SubjectAccessReview 的缺失本身不会被记录。
上传成功除新的管道或版本外,在 KFP 界面中没有其他提示。把意外的共享管道,或您未发布的共享管道新版本,视为需要调查的线索。
时间线
- 2026-09-09:修复通过拉取请求 #14352 合并。
- 2026-10-28:Kubeflow Pipelines 2.18.0 发布,公告 GHSA-rjr3-43j3-4q8g 发布。
- 2026-11-05:CVE-2026-77596 发布,CVSS v3.1 9.6。
- 2026-11-06:没有在野利用报告,该 CVE 不在 CISA KEV 目录中。
常见问题
单用户 Kubeflow Pipelines 安装受影响吗?
不受影响。多用户模式关闭时助手会立即返回,因此授权路径和空命名空间分支不会被使用。该缺陷适用于多用户安装。
攻击者需要 Kubernetes 账户吗?
如果 API 服务器可以直接访问且没有认证代理,则不需要;公告指出此时未认证调用者可以利用该绕过。在认证代理后面,攻击者需要有效的低权限租户账户。
攻击者的代码总会在另一个租户的命名空间中运行吗?
不会。只有当目标命名空间存在跟随最新版本且未固定版本的定期运行时才会运行。固定版本或内嵌自身规范的运行不会被该路径替换。
设置 REQUIRE_NAMESPACE_FOR_PIPELINES=true 就够了吗?
它会阻止空命名空间路径,也就是此 CVE 描述的绕过。这是缓解措施而非修复,不能替代补丁添加的授权检查。请尽快升级。
是否有在野利用?
截至 2026 年 11 月 6 日没有在野利用报告,该 CVE 不在 CISA KEV 目录中。公告于 2026 年 10 月 28 日发布,因此没有报告的时间还很短。
如何知道运行的是哪个版本?
检查 ml-pipeline 部署的镜像标签。清单为每个版本固定镜像标签,2.18.0 是第一个修复版本。如果平台厂商捆绑了 Kubeflow Pipelines,请询问捆绑包包含哪个上游版本。
参考文献
- Kubeflow Pipelines 安全公告 GHSA-rjr3-43j3-4q8g,2026 年 10 月 28 日发布,包含受影响版本、易受攻击代码、修复和影响:https://github.com/kubeflow/pipelines/security/advisories/GHSA-rjr3-43j3-4q8g(2026 年 11 月 6 日检查)
- CVE-2026-77596 记录,2026 年 11 月 5 日发布,CVSS v3.1 9.6 和受影响范围:https://www.cve.org/CVERecord?id=CVE-2026-77596(2026 年 11 月 6 日检查)
- Kubeflow Pipelines 拉取请求 #14352,修复:https://github.com/kubeflow/pipelines/pull/14352(2026 年 11 月 6 日检查)
- Kubeflow Pipelines 提交 62516d8c525f146b754cb515cf441dd0290ad841,“fix(backend): authorize shared pipeline uploads (#14352)”,2026 年 9 月 9 日:https://github.com/kubeflow/pipelines/commit/62516d8c525f146b754cb515cf441dd0290ad841(2026 年 11 月 6 日检查)
- Kubeflow Pipelines 2.18.0 版本,2026 年 10 月 28 日:https://github.com/kubeflow/pipelines/releases/tag/2.18.0(2026 年 11 月 6 日检查)
- Kubeflow Pipelines
backend/src/apiserver/server/pipeline_upload_server.go2.17.3,易受攻击的助手:https://github.com/kubeflow/pipelines/blob/2.17.3/backend/src/apiserver/server/pipeline_upload_server.go(2026 年 11 月 6 日检查) - Kubeflow Pipelines
backend/src/apiserver/server/pipeline_server.go2.17.3,授权共享写入的 gRPCcanAccessPipeline():https://github.com/kubeflow/pipelines/blob/2.17.3/backend/src/apiserver/server/pipeline_server.go(2026 年 11 月 6 日检查) - Kubeflow Pipelines
backend/src/apiserver/validation/namespace.go2.17.3,ValidateNamespaceRequired():https://github.com/kubeflow/pipelines/blob/2.17.3/backend/src/apiserver/validation/namespace.go(2026 年 11 月 6 日检查) - Kubeflow Pipelines
manifests/kustomize/base/pipeline/ml-pipeline-apiserver-deployment.yaml2.18.0,ml-pipeline部署:https://github.com/kubeflow/pipelines/blob/2.18.0/manifests/kustomize/base/pipeline/ml-pipeline-apiserver-deployment.yaml(2026 年 11 月 6 日检查) - CISA 已知被利用漏洞目录 JSON 源,2026 年 11 月 6 日检查 CVE-2026-77596(未列出):https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json(2026 年 11 月 6 日检查)
- GitHub,
kubeflow/pipelines,4,262 个星标和 2,185 个复刻:https://github.com/kubeflow/pipelines(2026 年 11 月 6 日检查)