CI/CD 流水线滥用:一个无人真正关注的问题
作者来自 Elastic Mika Ayenson, PhD我们如何构建一个开源、可直接使用的 CI 模板该模板通过信号提取和 LLM 推理来检测 GitHub Actions、GitLab CI 以及 Azure DevOps 流水线中的 CI/CD 滥用行为。前言在 2025 和 2026 年我们观察到一个在整个行业反复出现的模式。攻击者不再直接针对生产服务器而是转而攻击用于部署这些服务器的自动化系统。一旦开发者凭证被入侵、工作流文件被篡改CI/CD 环境中的所有 secret 就可能开始流向攻击者控制的端点。我们在涉及大型开源项目、Fortune 500 公司以及关键基础设施工具的事件中都看到了这一攻击方式的真实发生。攻击链看起来非常简单却极具欺骗性开发者凭证被盗 → 工作流文件被修改 → CI/CD secrets 被窃取 → 横向移动至云环境与生产系统今天我们正式开源 cicd-abuse-detector这是一个可直接使用的 CI 模板它通过基于正则表达式的信号提取以及 LLM 分析来检测 CI/CD 流水线中的可疑变更。它可以在 GitHub Actions、GitLab CI 和 Azure DevOps 中运行并且基于公开安全研究中记录的真实攻击技术设计。CI/CD 滥用检测器 CI/CD Abuse Detector 执行流程关键要点CI/CD 环境是高价值攻击目标因为一旦某个 workflow 被入侵就可能同时泄露云凭证、package registry token、代码签名密钥、部署密钥以及 OIDC token该工具从 diff 中提取 50 条基于正则表达式与元数据的信号然后将这些信号连同完整 diff 一起交给 Claude 进行结构化威胁分析。无需 Python仅依赖 bash 和 Claude Code CLI检测模式已经在 Nord Stream 和 Gato-X 等攻击性工具以及 ArtiPACKED 和 HackerBot-Claw 等真实事件中进行了验证该项目包含 19 个恶意 diff 和 4 个良性示例这些示例基于真实事件建模并提供一个自动化测试套件用于验证每一条信号为什么 CI/CD 流水线是高优先级攻击目标如果你花时间审查 GitHub Actions 或 GitLab CI 配置你会注意到这些文件中集中了承担了多少“信任”。一个典型的部署 workflow 通常同时拥有 AWS 凭证、npm 发布 token、Docker Hub 密码以及一个具有写权限的 GitHub token。攻击面并不是某个存在 CVE 的服务器而是一个 YAML 文件。大规模凭证窃取攻击者一旦获取开发者凭证就可以修改 workflow从 CI 环境中窃取 secrets。GhostAction campaign 在 2025 年 9 月展示了这种规模化攻击攻击者入侵 327 个 GitHub 用户、817 个仓库并通过注入的 workflow 文件窃取 3,325 个 secrets这些 workflow 会将凭证 POST 到攻击者控制的端点。Shai-Hulud npm worm 进一步升级了攻击方式。该自传播攻击通过 gh auth token 获取 GitHub Personal Access Token运行 TruffleHog 进行 secret 侦测并使用被盗 token 在同一开发者名下的其他 package 中悄悄注入恶意代码。仅第一波攻击就发布了超过 46,000 个恶意包。高权限触发器滥用pull_request_target 是 GitHub Actions 中最危险的功能之一。与普通 pull_request 不同它会在 base repository 的上下文中运行 workflow并访问 secrets但同时又可能执行来自不可信 fork 的代码。Pull Request Nightmare 的研究展示了这一点并影响了 Google、Microsoft 和 NVIDIA 维护的仓库。在 2026 年 2 月一个名为 HackerBot-Claw 的自动化攻击活动系统性扫描公共仓库专门寻找这种错误配置。它使用了五种利用方式包括被污染的 Go 函数、branch name 命令注入、基于文件名的注入、直接 script 注入以及针对 Claude-based code reviewer 的 AI prompt injection。在最严重案例中Aqua Security 的 Trivy 仓库被完全攻破进一步导致供应链攻击影响近 7,000 台机器并泄露 33,000 个 secrets。正如Microsoft 安全博客所记录这些攻击之所以成立是因为被盗 token 在数周后仍然有效。其余攻击分类除了凭证窃取和触发器滥用之外该威胁模型还覆盖了四类在公开研究中反复出现的攻击权限提升 permission escalation 例如添加 permissions: write-all 或 id-token: write从而扩大任何一次入侵的影响范围runner 攻击 runner targeting 将 job 重定向到自托管 runner通常可访问内部网络或指定攻击者控制的 container image供应链篡改 supply chain manipulation 包括使用 mutable action 引用main 而非 SHA 固定版本、远程 script 执行|、lockfile registry 替换以及依赖投毒防御规避 defense evasion 通过修改 commit timestamp 让恶意文件看起来“更旧且可信”。KL4R10N 博客记录了这一技术在与朝鲜相关的攻击活动中的使用这些攻击分别对应 MITRE ATTCK 的具体技术T1552未安全存储的凭证、T1195供应链攻击、T1070.006时间戳伪造、T1059命令与脚本解释器。CI/CD 滥用检测器攻击分类法与检测路径检测器是如何工作的我们希望这些模板在运行时不需要 Python、自定义运行环境或复杂依赖。所有逻辑都运行在标准 shell 工具上并且使用默认的 ubuntu-latest runner。唯一额外安装的工具是通过 npm 安装的 Claude Code CLI它负责处理认证、重试以及模型路由。阶段 1过滤与 diff当 pull request 被创建或 push 到受保护分支时workflow 会识别所有变更文件并按三个与 CI/CD 相关的层级进行分类。第一层是核心 CI 文件例如 workflow 定义、pipeline 配置以及 Makefile。第二层是构建与发布相关的工件例如 Dockerfile、package manifest、lockfile以及签名或部署脚本。第三层则覆盖开发环境配置例如 .vscode/tasks.json 和 .devcontainer 文件。每个文件都会单独进行 diff并限制在 10,000 字符以内。之所以按文件拆分而不是全局限制是因为统一截断可能被绕过。攻击者可以通过在恶意 workflow 修改旁加入大量无害的 Dockerfile 修改把 payload 推过字符限制。阶段 2信号提取在 LLM 看到任何内容之前50 条正则表达式模式会对每个 diff 进行扫描以识别已知的危险模式。这些 signals 是“提示性”的不会直接决定分析结果但会为 LLM 提供一个预筛选的威胁摘要。下面是一些示例信号Signal模式Pattern检测内容What it catchessecrets_context${{.*secrets.在 workflow 中直接进行 secret 插值direct secret interpolationpull_request_targetpull_request_target会让 PR 代码获取 secrets 的危险触发器checkout_refref:.*github.event.pull_request.head.(sha|ref)在特权上下文中检出不可信的 PR 代码double_base64base64.*|.*base64双重编码用于绕过日志脱敏Nord Stream 技术ld_preloadLD_PRELOAD通过环境变量注入实现任意代码执行vscode_auto_taskrunOn.*folderOpenVS Code task在打开文件夹时自动执行Contagious Interview该信号列表基于真实的对抗性工具包括 Nord Stream 和 Gato-X并在 19 个基于特定真实事件建模的恶意示例 diff 上进行了测试。该检测器在 GitHub Actions、GitLab CI 和 Azure DevOps 上运行方式完全一致。下面是它在各个平台上的检测触发示例Azure DevOps CI/CD 滥用检测器告警阶段 3LLM 分析信号摘要、完整 diff、作者画像以及 commit 元数据会被打包并通过 Claude Code CLI 发送给 Claude。分析 prompt 会引导模型完成以下几个方面的分析对 diff 的理解与逐文件风险评估信号解释结合上下文判断单个 signal 不构成结论针对回溯时间戳backdated commits的时间分析作者信任度评估账号年龄、贡献历史、组织成员关系等基于 60 条信号组合表进行严重性校准误报识别例如curl 下载已知工具不等同于数据外泄给出具体、可执行的修复建议例如“将 actions/setup-nodemain 固定到具体 SHA”而不是“请谨慎审查”最终输出是一个结构化 JSON verdict包含 severity、confidence、reasoning、evidence 和 recommendations并通过 JSON Schema 验证 进行校验。阶段 4告警与拦截Alert and gate根据 verdict 的严重级别workflow 会执行不同动作输出 step summary、创建 issue、发送 Slack 通知并在达到配置阈值时直接让 PR 检查失败fail the PR check。来自 CI/CD 滥用检测器的 Slack 通知标记出一个“严重critical级别”的发现将判定结果verdict发送到 ElasticsearchSlack 和 GitHub Issues 只能解决即时通知问题但无法提供可查询的历史记录。检测器生成的每一个 verdict例如 benign、suspicious 或 malicious都可以选择性地作为结构化文档发送到 Elasticsearch并写入 logs-cicd.abuse-default data stream。该 workflow 会将 verdict 连同 CI/CD 元数据platform、repository、actor、event type、run URL一起写入一个统一索引从而覆盖所有三种支持的平台。这一步使跨平台关联变得真正可行来自 GitHub Actions 的告警和来自 GitLab CI 的告警如果属于同一个 actor会进入同一个 data stream并且可以通过一条 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 流水线的跨平台判定结果该 schema 包含 cicd.platform、cicd.repository、cicd.actor以及完整的 verdict 对象verdict、severity、confidence、summary、reasons、evidence使构建检测规则变得非常直接。例如一个在一小时内影响多个仓库的协同攻击活动、一个在多个平台上被反复标记的“惯犯repeat offender”或者一个需要触发 incident response 的 critical 级别告警激增都可以被轻松关联起来。与真实攻击进行验证为了验证覆盖范围我们将检测信号与真实的攻击工具源码、公开研究以及事件复盘报告进行了对照。Nord Stream逐字节 payload 匹配Nord Stream 是 Synacktiv 开源的 CI/CD secret 提取工具支持 GitHub、GitLab 和 Azure DevOps。我们提取了 YAML 生成器源码并将其输出模板与我们的示例 diff 进行对比。GitHub payload 模板使用了 env -0 | awk -v RS0 /^secret_/ {print $0} | base64 -w0 | base64 -w0。我们的nord-stream-pipeline-exfil.diff 中包含这一行的逐字匹配内容并且我们的 double_base64、env_null_dump 和 env_secret_grep 信号全部被触发。OIDC Azure 模板使用了 azure/loginv1并配合id-token: write 权限随后执行az accountget-access-token | base64 -w0 | base64 -w0。我们的 diff 捕获了这一完整流程并触发了cloud_auth_action 和 id_token_write。Azure DevOps pipeline 技术 addSpnToEnvironment用于 SPN 凭证泄露、DownloadSecureFile 用于安全文件窃取、通过 ssh.js修改 SSH task 源代码全部出现在nord-stream-azure-devops.diff 中并被平台特定信号识别。ArtiPACKEDartifact 竞争条件ArtiPACKED 研究表明当将整个 checkout 目录作为 artifact 上传时会泄露包含 GITHUB_TOKEN的.git/config 文件。由于 v4 artifact API 允许在 job 执行过程中下载 artifact攻击者可以在任务结束前提取并使用该 token。我们的 artifact-token-leak.diff模型复现了这一攻击模式使用upload-artifact 并将 path: .设置为整个工作区。信号可以捕捉该行为而 LLM 会进一步评估上传范围是否包含.git 目录。GITHUB_ENV 注入LD_PRELOAD 到 RCELegit Security 研究 显示在 Google Firebase 和 Apache 的案例中将不可信输入写入 $GITHUB_ENV可能允许攻击者设置任意环境变量例如LD_PRELOAD 和 NODE_OPTIONS从而在特权 workflow 中实现代码执行。我们的 github-env-injection.diff复现了这一技术包含LD_PRELOAD三种 payload指向恶意共享对象的、带有强制注入的以及对$GITHUB_PATH的篡改。 github_env_write、ld_preload 和 github_path_write 信号均如预期触发。Contagious InterviewIDE 配置作为初始入口点Contagious Interview campaign归因于 DPRK 的攻击活动通过 “虚假面试” 针对开发者分发包含 .vscode/tasks.json文件的仓库这些文件会在打开文件夹时自动执行。其展示内容被隐藏reveal: never,echo: false并使用 curl|node实现静默执行。我们的 ide-config-poisoning.diff捕获了完整攻击链包括自动执行触发器runOn: folderOpen、隐藏展示层、curl | nodepayload、用于隐藏files.exclude 目录的 .vscode条目以及包含 base64 编码 URL 和执行链的木马化 postinstall hook。六种 signal 同时命中该攻击。防御建议除了部署检测器之外我们还从这些攻击模式中总结出了一些关键加固措施将所有 action 固定到 SHA而不是 tag 或 branch。SHA 固定引用可以防止类似 tj-actionsCVE-2025-30066这类标签回滚攻击将 secrets 限制在单个 step而不是使用 job 级环境变量。每个 step 只能访问其真正需要的 secrets尽量使用短生命周期的临时 token以降低攻击面避免使用 pull_request_target除非绝对必要。如果必须使用也不要在同一个workflow_run-triggered workflow中 checkout PR head 代码。应使用独立来分离“需要 secrets”和“需要 PR context”的操作为每个 workflow 设置显式权限因为默认 token 权限过于宽泛。在 workflow 级别设置 permissions: {}并为每个 job 添加细粒度权限启用 persist-credentials: falsecheckout因为 actions/checkout 默认行为会将GITHUB_TOKEN 保存在 .git 目录中。如果上传 artifact这个 token 也可能被一并带走总结CI/CD 流水线已经成为供应链攻击的主要攻击面。支撑现代软件交付的自动化系统正是攻击者用来窃取凭证、投毒包以及横向进入云基础设施的关键入口。传统的代码审查很难发现这些模式因为它们往往非常隐蔽、强依赖平台特性并且刻意伪装成正常的 DevOps 改动。通过结合基于正则的信号提取与 LLM 推理我们可以在 pull request 阶段就识别这些模式在它们进入生产环境之前进行拦截。该仓库提供了完整的威胁模型、测试套件以及示例 diff如果你想深入理解细节或将其适配到自己的环境中都可以参考。要开始使用请查看 cicd-abuse-detector 仓库获取安装说明、完整威胁模型和示例 diff。我们也欢迎大家分享新的攻击模式和检测思路可以在社区 Slack 中交流或在 Discuss 论坛提问。CI/CD 滥用与 MITRE ATTCK 映射我们使用 MITRE ATTCK 框架来映射攻击者针对 CI/CD 流水线的战术、技术与流程TTP。战术Tactics战术CI/CD 相关性Credential Access (TA0006)从 CI 环境中窃取 secretsExecution (TA0002)在 pipeline runner 中执行命令Persistence (TA0003)定时触发器、cron workflowDefense Evasion (TA0005)commit 时间戳篡改、日志规避Initial Access (TA0001)开发者凭证泄露、PAT 钓鱼Lateral Movement (TA0008)使用云凭证横向移动技术Techniques技术CI/CD 应用T1552: Unsecured CredentialsCI 环境变量、artifact、runner 内存中的 secrets 泄露T1195.002: Compromise Software Supply Chain被投毒的 actions、依赖与 lockfileT1059: Command and Scripting Interpretercurl 等命令执行T1070.006: Timestomp通过回溯 commit 时间绕过审查T1098: Account Manipulation通过 write-all、id-token: write 进行权限提升T1078: Valid Accounts使用被盗 PAT 修改 workflow参考资料以下资源在上述研究中被引用cicd-abuse-detectorNord StreamGato-XArtiPACKEDGhostAction campaignShai-Hulud npm wormPull Request NightmareHackerBot-ClawStepSecurity HackerBot-ClawLegit Security GitHub env injectionContagious InterviewCodecov postmortemGit history liesSynacktiv CI/CD exploitationClaude Code关于 Elastic Security LabsElastic Security Labs 是 Elastic Security 的威胁情报研究团队致力于推动威胁环境的积极变化。团队公开发布关于新兴威胁的研究并从战略、战术与操作层面对攻击者目标进行分析同时将这些研究整合进 Elastic Security 的内置检测与响应能力中。关注 Elastic Security LabsTwitter elasticseclabs或访问 Elastic Security Labs 获取最新研究成果。原文CI/CD pipeline abuse: the problem no one is watching — Elastic Security Labs