开源CI/CD滥用检测工具cicd-abuse-detector介绍

admin 2026-05-01 06:16:53 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文介绍开源工具cicd-abuse-detector,用于检测CI/CD流水线中的恶意修改。工具通过正则表达式信号提取和LLM分析,识别凭证窃取、特权触发器滥用等攻击模式,支持GitHubActions等平台并提供告警功能。文章基于真实攻击案例说明CI/CD环境的安全风险及检测方案。 综合评分: 87 文章分类: 安全工具,供应链安全,漏洞分析,安全运营,云安全


cover_image

开源CI/CD滥用检测工具cicd-abuse-detector介绍

Dubito Dubito

云原生安全指北

2026年4月30日 08:35 江苏

在小说阅读器读本章

去阅读

注:本文翻译自 Elastic Security Lab 的文章《CI/CD pipeline abuse: the problem no one is watching》[1],可点击文末“阅读原文”按钮查看英文原文。

全文如下:

一、序言

在 2025 年和 2026 年,我们观察到一种模式在整个行业内反复出现。攻击者不再直接攻击生产服务器,而是将目标转向了用于部署生产环境的自动化系统。攻击者利用被盗的开发者凭证、一个被修改的工作流文件,就能突然将 CI/CD 环境中的每一个 secret 都流式传输到攻击者控制的端点。我们在涉及主流开源项目[2](译文详见:GhostAction攻击事件:恶意工作流致3275个密钥从GitHub仓库泄露)、财富 500 强公司[3](译文详见:GitHub Actions 风险:不当工作流致RCE 与供应链攻击(上))以及关键基础设施工具[4]的安全事件中都看到了这种情况。

攻击链出奇地简单:

被盗的开发者凭证 → 修改后的工作流文件 → 被窃取的 CI 环境 secrets → 横向移动至云环境和生产环境

今天,我们正式开源了 cicd-abuse-detector[5]。这是一个即插即用的 CI 模板,它使用基于正则表达式的信号提取和 LLM(大语言模型)分析来检测 CI/CD 流水线中的可疑变更。该工具支持 GitHub Actions、GitLab CI 和 Azure DevOps,基于公开安全研究中记载的真实世界攻击技术设计。

译版:CI/CD Abuse Detector 执行流程

原版:CI/CD Abuse Detector 执行流程

二、核心要点

  • • CI/CD 环境是高价值目标,因为仅需一个被攻陷的工作流,就可能导致云凭证、包仓库令牌(package registry token)、代码签名密钥、部署密钥和 OIDC 令牌同时被窃取
  • • 该工具从代码差异(diff)中提取 50 多个基于正则表达式和元数据的信号,然后将这些信号连同完整的代码差异一起传递给 Claude 进行结构化的威胁分析。无需 Python,除了 bash 和 Claude Code CLI 之外没有其他依赖
  • • 检测模式已针对 Nord Stream[6] 和 Gato-X[7] 等攻击性工具包,以及包括 ArtiPACKED[8] 和 HackerBot-Claw[9] 在内的真实安全事件进行了测试
  • • 该项目附带了 19 个恶意的和 4 个良性的示例代码差异,这些示例均针对具体安全事件建模,同时还附带了一个自动化的测试套件,用于验证每一个信号

三、为什么 CI/CD 流水线是首要攻击目标

如果你花点时间审阅 GitHub Actions 或 GitLab CI 的配置,可能会注意到这些文件中集中了多少权限。一个典型的部署工作流可能同时拥有访问 AWS 凭证、npm 发布令牌、Docker Hub 密码以及具有写入权限的 GitHub 令牌的权限。这里的攻击面并不是一个存在 CVE 漏洞的服务器,而是一个 YAML 文件。

3.1 大规模凭证窃取

攻击者利用窃取到的开发者凭证,修改一个工作流,从而窃取 CI 环境中可用的 secrets。2025 年 9 月的 GhostAction 攻击活动[2](译文详见:GhostAction攻击事件:恶意工作流致3275个密钥从GitHub仓库泄露)就展示了这种规模化的攻击,该活动导致 817 个代码仓库中的 327 个 GitHub 用户被入侵。攻击者通过注入的工作流文件将凭证 POST 到攻击者控制的端点,共窃取了 3,325 个 secrets。

Shai-Hulud npm 蠕虫[10]则更进一步。这种自我传播的攻击通过 gh auth token 窃取 GitHub 个人访问令牌(GitHub Personal Access Token),运行 TruffleHog[11] 进行秘密侦察,并使用窃取到的令牌将恶意代码静默注入同一开发者拥有的其他包中。仅在第一波攻击中,就有超过 46,000 个恶意包被发布。

3.2 特权触发器利用

pull_request_target 触发器是 GitHub Actions 中最危险的功能之一。与普通的 pull_request 触发器不同,它在基础仓库(base repository)的上下文中运行工作流,可以访问 secrets,但同时它会执行来自不可信分支(fork)的代码。Orca 公司关于 “Pull Request Nightmare”[3](译文详见:GitHub Actions 风险:不当工作流致RCE 与供应链攻击(上))的研究展示了针对 Google、Microsoft 和 NVIDIA 所维护仓库的这种攻击。

2026 年 2 月,一个名为 HackerBot-Claw[12](译文详见:当AI攻击CI/CD:hackerbot-claw如何实现Github仓库接管)的自动化攻击活动系统性地扫描了公共仓库,寻找这类确切的安全配置错误。它使用了五种不同的利用技术,包括恶意的 Go init() 函数、分支名称命令注入、基于文件名的注入、直接脚本注入,以及针对基于 Claude 的代码评审者的 AI 提示词注入。在最严重的事件中,Aqua Security 的 Trivy 仓库被完全攻陷,导致了一次下游供应链攻击,暴露了分布在近 7,000 台机器上的 33,000 个 secrets。正如相关文档[13]所记载的,这次供应链攻击之所以成为可能,是因为被窃取的令牌在被盗后很长一段时间内仍然有效。

3.3 其他威胁类别

除了凭证窃取和触发器利用之外,威胁模型还涵盖了另外四类在公开研究中频繁出现的攻击方式:

  • • 权限提升:通过添加 permissions: write-all 或 id-token: write 等权限,扩大任何安全入侵事件的影响范围
  • • Runner 定向攻击:将作业重定向到自托管的 runner(这些 runner 通常具有访问内部基础设施的网络权限),或者指定由攻击者控制的容器镜像
  • • 供应链操纵:通过可变 action 引用(使用 @main 而非 SHA 固定版本)、远程脚本执行(curl 配合 bash)、lockfile 仓库源替换以及依赖投毒等方式实现
  • • 防御规避:通过修改提交时间戳,使恶意文件看起来像是旧文件且值得信任。KL4R10N 曾记录[14]这种技术被用于与朝鲜有关的攻击活动中,其中通过回溯提交日期引用的基础设施在所述日期实际并不存在

以上每一种攻击方式都对应到 MITRE ATT&CK[15] 中的具体技术:T1552[16](不安全的凭证,Unsecured Credentials)、T1195[17](供应链入侵,Supply Chain Compromise)、T1070.006[18](时间戳抹除,Timestomp)以及 T1059[19](命令与脚本解释器,Command and Scripting Interpreter)。

CI/CD Abuse Detector 攻击分类与检测路径

四、检测器的工作原理

我们希望这些模板能够在不需要 Python、自定义运行时或复杂依赖的情况下工作。所有操作都在默认的 ubuntu-latest 运行器上,使用标准的 shell 工具执行,唯一需要安装的工具是通过 npm 安装的 Claude Code CLI[20],该工具负责处理认证、重试和模型路由。

4.1 第一阶段:过滤与Diff提取

当一个 PR 被打开(或向受保护分支推送代码)时,工作流会识别三层与 CI/CD 相关的路径中被更改的文件。第一层涵盖核心 CI 文件,如 workflow 定义、流水线配置和 Makefile。第二层涵盖构建与发布产物(artifact),如 Dockerfile、包清单(package manifests)、lockfile 以及签名或部署脚本。第三层涵盖开发者环境配置,如 .vscode/tasks.json 和 .devcontainer 文件。

每个文件都会被单独进行差异比较,并且每个差异内容上限为 10,000 字符。我们选择按文件而非全局进行限制,因为如果只对合并后的总差异设置一个字符上限,攻击者可以通过在一个大型的、无害的 Dockerfile 修改中夹带恶意的 workflow 变更,从而突破字符限制。

4.2 第二阶段:信号提取

在大语言模型看到任何内容之前,系统会先用 50 多个正则表达式模式扫描每个差异内容(diff),寻找已知的危险模式。这些信号起辅助作用,它们永远不会直接决定分析结果,而是为大语言模型提供一份预先筛选过的威胁摘要。以下是一些示例:

| 信号 | 正则表达式模式 | 捕获内容 | | — | — | — | | secrets_context | ${{.*secrets. | 工作流中直接进行 secret 插值 | | pull_request_target | pull_request_target | 会向 PR 代码授予 secrets 的危险触发器 | | checkout_ref | ref:.*github.event.pull_request.head.(sha|ref) | 在特权上下文中检出的不可信 PR 代码 | | double_base64 | base64.*|.*base64 | 双重编码以绕过日志脱敏(Nord Stream 技术) | | ld_preload | LD_PRELOAD | 通过环境变量注入实现任意代码执行 | | vscode_auto_task | runOn.*folderOpen | 在打开文件夹时执行的 VS Code 任务(Contagious Interview) |

该信号列表基于真实的攻击工具,包括 Nord Stream[6] 和 Gato-X[7],并且已针对 19 个根据具体安全事件建模的恶意示例差异文件进行了测试。

该检测器在 GitHub Actions、GitLab CI 和 Azure DevOps 上的运行方式完全相同。以下是各平台上的检测告警示例:

GitHub CI/CD Abuse Detector 告警

GitLab CI/CD Abuse Detector 告警

Azure DevOps CI/CD Abuse Detector 告警

4.3 第三阶段:大语言模型分析

信号摘要、完整的差异内容、作者profile以及提交元数据会被打包在一起,通过 Claude Code CLI 发送给 Claude。分析提示词[21]会引导模型从以下几个方面进行分析:

  1. 1. Diff 理解与每个文件的风险评估
  2. 2. 结合上下文的信号解读(单个信号本身不等同于定论)
  3. 3. 针对回溯提交的时间分析
  4. 4. 基于账号年龄、贡献历史和组织成员身份的作者可信度评估
  5. 5. 对照包含 60 多个条目的信号组合表进行严重程度校准
  6. 6. 误报识别(例如,使用 cURL 下载已知工具不属于数据外泄)
  7. 7. 给出具体、可操作的建议(例如:“将 actions/setup-node@main 固定到具体的 SHA”,而不是“请仔细检查”)

输出结果是一个结构化的 JSON 格式判定结果(verdict),其中包含严重程度、置信度、推理过程、证据和建议,所有这些内容都会根据 JSON Schema[22] 进行验证。

4.4 第四阶段:告警与拦截

根据判定结果的严重程度,工作流会发布步骤摘要、创建一个 Issue、发送 Slack 通知,并且可以选择在严重程度达到设定阈值时,让 PR 检查失败。

CI/CD Abuse Detector 发出的 Slack 通知,标记了一个严重级别为“严重”的发现

译版:将判定结果发送至 Elastic

原版:将判定结果发送至 Elastic

在 Slack 和 GitHub Issues 中收到告警解决了即时通知的问题,但这并不能提供一个可查询的历史记录。检测器产生的每一个判定结果(例如 benign(良性)、suspicious(可疑)或 malicious(恶意))都可以选择作为结构化文档发送到 Elasticsearch 的 logs-cicd.abuse-default 数据流中。工作流会将判定结果连同 CI/CD 元数据(平台、代码仓库、操作者、事件类型、运行 URL)一起放入一个索引中,该索引涵盖了所有三个受支持的平台。

跨平台的关联分析在此处变得切实可行。来自同一个操作者的一个 GitHub Actions 告警和一个 GitLab CI 告警会落入同一个数据流,通过一句 ES|QL 语句即可查询:

FROM logs-cicd.abuse-*
WHERE verdict.verdict IN ("malicious", "suspicious") AND @timestamp > NOW() - 7 days
EVAL platform = cicd.platform, repo = cicd.repository, actor = cicd.actor, severity = verdict.severity
KEEP @timestamp, platform, repo, actor, severity
SORT @timestamp DESC

来自 GitHub Actions、GitLab CI、Azure DevOps Pipelines 的跨平台判定结果

该数据结构(schema)包含 cicd.platformcicd.repositorycicd.actor 以及完整的判定结果对象(包含 verdict、severity、confidence、summary、reasons、evidence),这使得构建检测规则变得非常简单。例如,一个在多个仓库间协同攻击的活动、一个跨平台被标记的惯犯,或者某个严重发现激增(需要启动应急响应流程)的情况,都可以方便地进行关联分析。

五、针对真实攻击的验证

为了验证检测覆盖范围,我们将自己的检测模式与攻击工具的源代码、已发表的研究成果以及公开的事后分析报告进行了对比。

5.1 Nord Stream:逐字匹配攻击载荷

Nord Stream 是 Synacktiv 开发的开源 CI/CD 凭证提取工具,支持 GitHub、GitLab 和 Azure DevOps。我们提取了该工具的 YAML 生成器源代码(nordstream/yaml/github.py),并将其输出的模板与我们的示例差异文件进行了对比。

  • • GitHub 的攻击载荷模板使用了 env -0 | awk -v RS='0' '/^secret_/ {print $0}' | base64 -w0 | base64 -w0。我们的 nord-stream-pipeline-exfil.diff 示例文件中就逐字包含了这行命令,并且我们的 double_base64env_null_dump 和 env_secret_grep 信号均会触发。
  • • OIDC Azure 模板使用了 azure/login@v1 并配置了 id-token: write 权限,随后执行了 az account get-access-token | base64 -w0 | base64 -w0。我们的差异文件捕获了这一精确流程,并触发了 cloud_auth_action 和 id_token_write 信号。
  • • 针对 Azure DevOps 流水线的技术(通过 addSpnToEnvironment 暴露服务主体名称凭证、通过 DownloadSecureFile 窃取安全文件、通过修改 ssh.js 进行 SSH 任务源补丁劫持)均存在于 nord-stream-azure-devops.diff 文件中,并被平台特定的信号所检测到。

5.2 ArtiPACKED:产物竞争条件利用

Palo Alto Unit 42 的 ArtiPACKED[8] 研究表明,将整个检出目录上传为 workflow 产物(artifact)会泄露包含 GITHUB_TOKEN 的 .git/config 文件。由于 v4 版本的产物 API 允许在作业执行过程中下载产物,攻击者可以在作业完成之前就提取并使用该令牌。

我们的 artifact-token-leak.diff 示例文件精确模拟了这种模式,即使用 upload-artifact 并配置 path: .(即整个工作空间)。upload_artifact 信号会捕获该行为,随后大语言模型会评估上传范围是否包含 .git 目录。

5.3 GITHUB_ENV 注入:从 LD_PRELOAD 到远程代码执行

Legit Security 的研究[23] (涉及 Google Firebase 和 Apache) 表明,向 $GITHUB_ENV 写入不可信输入,允许攻击者设置任意环境变量,例如 LD_PRELOAD 和 NODE_OPTIONS,从而在特权工作流中实现代码执行。

我们的 github-env-injection.diff 示例文件重现了这种技术,使用了三种不同的攻击载荷,包括指向恶意共享对象的 LD_PRELOAD、带有必需注入代码的 NODE_OPTIONS,以及对 $GITHUB_PATH 的篡改。github_env_writeld_preload 和 github_path_write 信号均能按预期触发。

5.4 Contagious Interview:IDE 配置作为初始入侵途径

Contagious Interview 攻击活动[24]被认为与朝鲜有关,该活动通过虚假的工作面试机会来攻击开发者,分发的代码仓库中包含 .vscode/tasks.json 文件,该文件会在打开文件夹时自动执行。其显示设置为隐藏(reveal: neverecho: false),攻击载荷使用 curl | node 进行静默执行。

我们的 ide-config-poisoning.diff 示例文件捕获了完整的攻击链,包括自动执行触发器(runOn: folderOpen)、隐藏的显示设置、curl | node 载荷、用于隐藏 .vscode 目录的 files.exclude 条目,以及一个被植入后门的 postinstall 钩子(包含 base64 编码的 URL 和用于执行代码的 eval())。共有六个信号会同时检测到该行为。

六、防御建议

除了部署检测器之外,以下加固措施直接来源于我们所研究的攻击模式:

  • • 将所有 action 固定到 SHA,不要使用 tag 或分支。使用 SHA 固定的引用可以防止像 tj-actions 那样的追溯性 tag 篡改攻击(CVE-2025-30066)。
  • • 将 secrets 的作用域限定到单个步骤,而不是使用作业级别的环境变量。每个步骤只应拥有其实际需要的 secrets。
  • • 尽可能使用短期的、一次性的令牌,以减少攻击面。
  • • 除非绝对必要,否则避免使用 pull_request_target。如果必须使用它,切勿在同一工作流中检出 PR 的 head 代码。对于既需要 secrets 又需要 PR 上下文的操作,应使用一个单独由 workflow_run 触发的工作流。
  • • 为每个工作流设置显式的权限,因为默认的令牌权限过于宽泛。在工作流级别设置 permissions: {},然后为每个作业添加具体的权限。
  • • 在检出代码时启用 persist-credentials: false,因为 actions/checkout 的默认行为会将 GITHUB_TOKEN 持久化存储在 .git 目录中。如果你上传产物(artifact),该令牌也会随之被上传。

七、总结

CI/CD 流水线已成为供应链攻击的主要攻击面。攻击者利用的正是那些使现代软件交付成为可能的自动化机制,来窃取凭证、投毒软件包并横向移动到云基础设施。传统的代码评审很难发现这些模式,因为它们隐蔽、与特定平台相关,并且被伪装成合法的 DevOps 变更。

将基于正则表达式的信号提取与大语言模型的推理能力相结合,使我们能够在这些模式到达生产环境之前,在 PR 阶段就将其暴露出来。该代码仓库包含完整的威胁模型、测试套件以及示例差异文件,方便你深入研究细节或将其适配到自己的环境中。

想要开始使用,请查看 cicd-abuse-detector 仓库[25]获取设置说明、完整的威胁模型以及示例差异文件。我们非常欢迎你分享新的攻击模式和检测思路。欢迎在我们的社区 Slack[26] 中与我们交流,并在我们的讨论论坛[27]中提问。

八、通过 MITRE ATT&CK 理解 CI/CD 滥用

我们使用 MITRE ATT&CK[15] 框架来映射攻击者针对 CI/CD 流水线所使用的战术、技术及程序。

8.1 战术

| 战术 | 与 CI/CD 的关联性 | | — | — | | 凭证访问(TA0006)[28] | 从 CI 环境中窃取 secrets(密钥) | | 执行(TA0002)[29] | 在流水线运行器(runner)中执行命令 | | 持久化(TA0003)[30] | 使用定时触发器、基于 cron 的工作流 | | 防御规避(TA0005)[31] | 篡改提交时间戳、绕过日志脱敏 | | 初始访问(TA0001)[32] | 窃取开发者凭证、通过网络钓鱼获取个人访问令牌(PAT) | | 横向移动(TA0008)[33] | 使用窃取到的云凭证进行横向跳转 |

8.2 技术

| 技术 | 在 CI/CD 中的具体应用 | | — | — | | T1552:不安全的凭证[16] | 暴露在 CI 环境变量、产物(artifact)及运行器内存中的 secrets | | T1195.002:入侵软件供应链[34] | 投毒后的 actions(操作)、依赖项及锁定文件(lockfile) | | T1059:命令与脚本解释器[19] | 使用 curl | bash 或 curl | node 等方式执行远程脚本 | | T1070.006:时间戳抹除[18] | 使用回溯的提交日期来规避评审 | | T1098:账户操纵[35] | 通过 write-allid-token: write 等方式进行权限提升 | | T1078:有效账户[36] | 使用窃取到的开发者个人访问令牌(PAT)来修改工作流 |

引用链接

[1] 《CI/CD pipeline abuse: the problem no one is watching》: https://www.elastic.co/security-labs/detecting-cicd-pipeline-abuse-with-llm-augmented-analysis [2] 主流开源项目: https://blog.gitguardian.com/ghostaction-campaign-3-325-secrets-stolen [3] 财富 500 强公司: https://orca.security/resources/blog/pull-request-nightmare-github-actions-rce/ [4] 关键基础设施工具: https://about.codecov.io/apr-2021-post-mortem/ [5] cicd-abuse-detector: https://github.com/elastic/cicd-abuse-detector [6] Nord Stream: https://github.com/synacktiv/nord-stream [7] Gato-X: https://github.com/AdnaneKhan/Gato-X [8] ArtiPACKED: https://unit42.paloaltonetworks.com/github-repo-artifacts-leak-tokens/ [9] HackerBot-Claw: https://orca.security/resources/blog/hackerbot-claw-github-actions-attack/ [10] Shai-Hulud npm 蠕虫: https://www.reversinglabs.com/blog/shai-hulud-worm-npm [11] TruffleHog: https://github.com/trufflesecurity/trufflehog [12] HackerBot-Claw: https://www.stepsecurity.io/blog/hackerbot-claw-github-actions-exploitation [13] 相关文档: https://www.microsoft.com/en-us/security/blog/2026/03/24/detecting-investigating-defending-against-trivy-supply-chain-compromise/ [14] KL4R10N 曾记录: https://kl4r10n.tech/blog/when-git-history-lies [15] MITRE ATT&CK: https://attack.mitre.org/ [16] T1552: https://attack.mitre.org/techniques/T1552/ [17] T1195: https://attack.mitre.org/techniques/T1195/ [18] T1070.006: https://attack.mitre.org/techniques/T1070/006/ [19] T1059: https://attack.mitre.org/techniques/T1059/ [20] Claude Code CLI: https://docs.anthropic.com/en/docs/claude-code [21] 分析提示词: https://github.com/elastic/cicd-abuse-detector/blob/main/prompts/analyze-cicd-change.md [22] JSON Schema: https://github.com/elastic/cicd-abuse-detector/blob/main/schemas/verdict.schema.json [23] Legit Security 的研究: https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability-0 [24] Contagious Interview 攻击活动: https://www.abstract.security/blog/contagious-interview-tracking-the-vs-code-tasks-infection-vector [25] cicd-abuse-detector 仓库: https://github.com/elastic/cicd-abuse-detector [26] 社区 Slack: http://ela.st/slack [27] 讨论论坛: https://discuss.elastic.co/c/security/endpoint-security/80 [28] 凭证访问(TA0006): https://attack.mitre.org/tactics/TA0006/ [29] 执行(TA0002): https://attack.mitre.org/tactics/TA0002/ [30] 持久化(TA0003): https://attack.mitre.org/tactics/TA0003/ [31] 防御规避(TA0005): https://attack.mitre.org/tactics/TA0005/ [32] 初始访问(TA0001): https://attack.mitre.org/tactics/TA0001/ [33] 横向移动(TA0008): https://attack.mitre.org/tactics/TA0008/ [34] T1195.002:入侵软件供应链: https://attack.mitre.org/techniques/T1195/002/ [35] T1098:账户操纵: https://attack.mitre.org/techniques/T1098/ [36] T1078:有效账户: https://attack.mitre.org/techniques/T1078/

交流群


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:云原生安全指北 Dubito Dubito《开源CI/CD滥用检测工具cicd-abuse-detector介绍》

评论:0   参与:  0