CVE-2026-58443:Gitea 公共作用域令牌可写入私有仓库并触发 Actions,CVSS 9.6 PoC 已公开

CVE-2026-58443(GHSA-xxjv-752h-3vp2)是 Gitea 自托管代码平台一处严重授权绕过漏洞,CVSS 3.1 评分 9.6。仅持有 public-only 作用域令牌的调用方可借助 PR 更新端点将公共基础仓库的提交推送到私有 head 仓库,并进一步触发该私有仓库上的 Actions 工作流,完全绕过令牌作用域隔离。官方已在 Gitea v1.27.0 修复,完整 PoC 已公开。

事件概述

Gitea 是被广泛使用的轻量自托管 Git 服务之一,被众多团队用作内网代码托管与 CI 触发入口。漏洞根源在于 PR 更新接口 POST /api/v1/repos/{owner}/{repo}/pulls/{index}/update:Gitea 的 public-only 检查仅施加在路由/base 仓库,而 UpdatePullRequest() 在对私有 head 仓库进行 IsUserAllowedToUpdate() 普通 RBAC 校验时,未重新施加令牌作用域限制。当 head 仓库启用 Actions 时,注入的 push 事件会作为合法 push 触发对应 ActionRunActionRunJob,使攻击者用公共作用域凭据撬动私有 CI/CD

技术细节

官方代码片段(routers/api/v1/api.go:1358-1394)显示 PR 路由挂在 checkTokenPublicOnly() 检查之下,但内部 /update 端点未对 head 仓库再做相同检查:

m.Group("/pulls", func() {
    ...
    m.Group("/{index}", func() {
        ...
        m.Post("/update", reqToken(), repo.UpdatePullRequest)
        ...
    })
}, mustAllowPulls, reqRepoReader(unit.TypeCode), ...
}, repoAssignment(), checkTokenPublicOnly())

利用前置条件:

  • 攻击者持有合法的 public-only + write:repository 令牌
  • 该令牌所属用户对目标私有 head 分支具备正常写权限
  • 存在一个 PR 关系,公共 base 仓库可被合并/重定基到私有 head 仓库

分类上属于 CWE-863 Incorrect Authorization,影响 Integrity 与 Availability,Scope 标记为 Changed(C)。PoC 验证显示:直接对私有仓库的写入会被 404 拒绝,而通过 PR 更新端点可以成功合并公共提交到私有分支并触发 Actions 工作流。

影响评估

所有 Gitea v1.26.4 及更早版本均受影响,CVSS 向量 AV:N/AC:L/PR:L/UI:N/S:C/C:N/I:H/A:H。在自托管部署中,攻击者可借此向私有代码、私有构建流水线注入代码,无需具备私有仓库的直接写权限。EPSS 评分较高,研究员已发布完整 PoC。目前尚未确认野外利用,但鉴于 PoC 已公开,多支研究团队过去 6 个月内已多次发现 Gitea 类似作用域边界失败(反代认证绕过、webhook SSRF),规模化利用门槛极低。

修复建议

  1. 立即升级:自托管实例升级至 Gitea v1.27.0 及以上版本(修复 PR #38406)。升级完成后重新打开 Actions 验证是否仍按预期触发。
  2. 令牌审计:在升级前,列出同时具有 public-onlywrite:repository 作用域的令牌,对组合非必要的进行撤销并重新签发最小权限令牌。
  3. Actions 行为审计:检查私有仓库近期 ActionRun 记录,关注 event=pushtrigger_user_id 与提交者不匹配、来源为 PR-update 触发的可疑 run。
  4. RBAC 与 MFA 加固:对所有用户强制 MFA;对私有仓库设置 PushPush to protected branchRun workflows 三项最小权限复核;将 Token only public 开关作为强制安全基线。
  5. 端点约束:反向代理层对 /api/v1/repos/*/pulls/*/update 增加可信 IP、UA、速率限制;WAF 日志应记录全部调用以便回溯。

参考来源