你的代码正在 “裸奔” 吗?

在当今的软件开发流程中,GitHub Actions 作为一款强大的自动化工具,被广大开发者广泛应用。它能帮助我们自动完成诸如代码构建、测试、部署等一系列繁琐的任务,极大地提高了开发效率。然而,看似便捷的背后,却隐藏着不容忽视的安全隐患。你有没有想过,在使用 GitHub Actions 时,你运行的究竟是谁的代码?

恶意代码入侵事件敲响警钟

就在不久前,有人在 tj-actions/changed-files 这款 GitHub Action 中植入了恶意代码。这可不是一件小事!一旦你使用了被篡改的这个 Action,你的机密信息就可能会泄露到构建日志中。而对于公共仓库来说,这些构建日志是公开可见的,这意味着任何人都有可能看到你的机密信息,简直细思极恐!

为什么会出现这样的情况呢?这背后涉及到一个关于引用方式的问题。在 GitHub Actions 工作流中,大家常常会使用标签来引用 Action,就像这样:

jobs:
  changed_files:
    ...
    steps:
      - name: Get changed files
        id: changed-files
        uses: tj-actions/changed-files@v2
      ...

乍一看,这似乎是指向已经发布的 “v2 版本” Action 的固定引用,但实际上,这里的v2标签是可变的。如果有人在tj-actions/changed-files仓库中修改了v2标签,让它指向了不同的提交,那么下次运行这个 Action 时,执行的就会是不同的代码,恶意代码也就有了可乘之机。

相比之下,如果你指定的是一个 Git 提交 ID(例如a5b3abf),那就是一个不可变的引用,每次运行都会执行相同的代码,安全性就会高很多。不过,使用标签和提交 ID 各有利弊。指定具体的提交 ID 虽然能确保代码不会意外改变,但标签更便于阅读和比较。这就像是在便捷性和安全性之间做了一场艰难的抉择。

自查:你的项目是否存在风险?

这件事发生后,我虽然不使用tj-actions,但也开始对自己项目中使用的其他 GitHub Actions 感到好奇,想知道是否也存在类似的风险。于是,我在本地克隆了所有仓库的文件夹中运行了一段简短的 Shell 脚本:

find . -path '*/.github/workflows/*' -type f -name '*.yml' -print0 \
  | xargs -0 grep --no-filename "uses:" \
  | sed 's/\- uses:/uses:/g' \
  | tr '"' ' ' \
  | awk '{print $2}' \
  | sed 's/\r//g' \
  | sort \
  | uniq --count \
  | sort --numeric-sort

这段脚本的作用是统计我在项目中使用的所有 GitHub Actions。让我们来详细拆解一下它的工作原理:

  1. find . -path '*/.github/workflows/*' -type f -name '*.yml' -print0:这个命令用于查找所有的 GitHub Actions 工作流文件。它会在当前目录及其子目录下,寻找路径中包含.github/workflows/且文件名以.yml结尾的文件。找到后,它会以空字节(\0)作为分隔符输出这些文件名。这是因为相比于默认的换行符,空字节更安全,能避免文件名中包含换行符时出现的问题。如果你的工作流文件扩展名有时是.yaml,可以把-name '*.yml'替换为$ -name '*.yml' -o -name '*.yaml' $ 。另外,我还添加了一些-path规则,比如-not -path './cpython/*',用来排除那些我克隆的开源项目仓库,因为我不太关心它们使用的 GitHub Actions。
  2. xargs -0 grep --no-filename "uses:"xargs命令会根据前面find命令输出的文件名,逐个进行处理。-0标志告诉它以空字节作为分隔符。然后,grep命令会在每个文件中查找包含"uses:"的行,这是在工作流文件中使用 Action 的标识。--no-filename选项表示只输出匹配的行,而不输出文件名。由于我的文件格式和缩进不太一致,所以输出的内容有点杂乱。
  3. sed 's/\- uses:/uses:/g':在工作流文件中,uses:前面有时会有一个连字符,有时没有,这取决于它在 YAML 字典中的位置。这个sed命令会把"- uses:"替换为"uses:",对数据进行初步整理。我知道sed是一个非常强大的文本处理工具,但我常用的也就像这种替换文本的简单命令:sed 's/old/new/g' 。
  4. tr '"' ' ':Action 的名称有时会被引号括起来,有时不会。这个命令的作用就是去除输出中的双引号。写这篇文章的时候我突然想到,其实也可以用sed来完成这个替换操作。不过我选择tr是因为我用它的时间更久,而且对于单个字符的替换,它的语法更简单:tr '<oldchar>' '<newchar>'
  5. awk '{print $2}'awk命令会把字符串按空格进行分割,然后输出第二个部分,也就是 Action 的名称。虽然awk有很多强大的模式匹配功能,但我目前也就掌握了打印字符串中第 n 个单词的用法。
  6. sed 's/\r//g':我的一些工作流文件中存在回车符(\r),它们会出现在awk的输出中。这个命令就是用来去除这些回车符,让数据在最后一步处理时更加统一。
  7. sort | uniq --count | sort --numeric-sort:首先,sort命令会对前面的输出进行排序,让相同的行相邻;然后,uniq --count会对相邻的相同行进行分组并统计数量;最后,再用sort --numeric-sort按数量进行排序,把使用次数最多的 Action 排在最下面。我把这个脚本设置成了一个名为tally的 Shell 别名。

运行这个脚本后,我得到了类似这样的输出:

 1 hashicorp/setup-terraform@v3
 2 dtolnay/rust-toolchain@v1
 2 taiki-e/create-gh-release-action@v1
 2 taiki-e/upload-rust-binary-action@v1
 4 actions/setup-python@v4
 6 actions/cache@v4
 9 ruby/setup-ruby@v1
31 actions/setup-python@v5
58 actions/checkout@v4

看着这份清单,我开始思考对每个 Action 及其作者的信任程度。像actionsruby这样的大组织提供的 Action,虽然不能说绝对完美,但它们通常会有比较完善的安全措施,能有效防范恶意修改。而对于那些来自个人开发者或小组织的 Action,我就会更加谨慎,尤其是在我不认识作者的情况下。这并不是说个人开发者的安全意识一定不好,只是在互联网上,个人开发者的安全设置差异比大组织要大得多。另外,我还会考虑是否真的需要使用别人的 Action,还是可以自己编写脚本来替代。如果我只是用到某个 Action 的一小部分功能,我通常更倾向于自己写脚本。虽然前期会多花点功夫,但这样我能清楚地知道代码在做什么,也能减少上游变更带来的影响和风险。

总体来说,我对自己项目中使用的这些 Action 还算比较放心。大部分 Action 都来自大组织,剩下的一些是针对我自己的 Rust 命令行工具的,这些工具属于非关键的小项目,就算 GitHub 仓库被入侵,影响也相对较小。

安全使用 GitHub Actions 的建议

通过这次事件和自查,我们可以总结出一些安全使用 GitHub Actions 的建议。首先,尽量使用不可变的引用,也就是指定具体的 Git 提交 ID 来引用 Action,这样能最大程度地避免因标签被篡改而导致的安全问题。虽然使用标签更方便,但在安全问题上,还是谨慎为好。

其次,要对使用的 Action 进行严格审查。在引入一个新的 Action 之前,仔细查看它的仓库、作者信息,了解其更新频率和社区反馈。如果是来自不太知名的作者或小组织,更要格外小心。可以查看代码的历史记录、提交信息,看看是否有异常情况。

另外,定期检查项目中使用的 Actions 也是个好习惯。就像我用脚本统计自己使用的 Actions 一样,你也可以定期运行类似的脚本,看看是否有新的风险出现。如果发现某个 Action 存在安全隐患,及时进行替换或更新。

最后,对于一些简单的功能,如果自己有能力编写脚本实现,尽量不要依赖外部的 Action。这样不仅能提高安全性,还能让你更加了解项目的具体实现,在遇到问题时也能更快速地进行调试和修复。

GitHub Actions 为我们的开发工作带来了极大的便利,但我们不能忽视其中的安全问题。通过了解这些潜在风险,并采取相应的防范措施,我们就能在享受其便利的同时,保障项目的安全。希望大家都能重视起来,让自己的代码在 GitHub Actions 的运行中更加安全可靠。你在使用 GitHub Actions 时遇到过哪些安全问题呢?欢迎在评论区分享你的经验和看法。

关于Allthinker 敖行客:

公司专注于通过先进的理念与技术,为开发者打造开放、自由、高效且安全的研发空间,期待与你一起创造一个更美好的研发新世界。

关于AT Work:

AT Work是敖行客打造的下一代研发智能体,基于自主研发的"思链"认知引擎构建,实现云原生研发场景的全面智能化革新。作为业内首个搭载多模态AI中台的云端研发平台,通过深度学习模型重构需求分析、代码生成、质量管控、知识管理四大核心模块,深度融合云IDE、敏捷看板、共享云盘、云文档、云端知识库等数字工具链,形成"需求-设计-开发-测试-交付"的智能闭环。

科技脉搏,每日跳动。

与敖行客 Allthinker一起,创造属于开发者的多彩世界。

图片

- 智慧链接 思想协作 -

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值