
类型:代码托管平台
简介:只支持Git作为唯一的版本库格式进行托管,故名GitHub。
GitHub Actions 经常需要访问云平台、包管理器、服务器或第三方 API,这些凭证不能直接写进仓库。GitHub Secrets 提供了保存敏感值的方式,但“放进 Secrets”并不等于绝对安全。Token 权限过大、日志里误打印、环境不隔离、长时间不轮换,都可能让项目面临风险。
一、哪些内容应该放进Secrets
API Token、SSH 私钥、部署密钥、Webhook 密钥、数据库连接字符串、第三方服务访问凭证,都应该放入 Secrets。普通配置项如果不敏感,例如构建模式、公开 API 地址,可以放在 Variables 或 workflow 里,不必混进 Secrets。
区分敏感和非敏感很重要。所有配置都塞进 Secrets,会让维护者看不清哪些值真正需要保护;真正的密钥又如果写在 README、YAML 或脚本里,一旦提交到公开仓库,就很难彻底收回。
二、Token权限要尽量小
创建 Token 时,不要为了省事直接给最高权限。部署静态站可能只需要写某个存储桶,发布包可能只需要 package 写权限,调用 API 可能只需要某个项目范围。权限越大,泄露后的损失越大。
如果服务支持细粒度 Token,优先使用细粒度权限和过期时间。长期有效、全账号权限的 Token 最危险。对生产环境凭证,最好只放在 production environment 下,而不是仓库全局 Secrets。
三、在workflow中正确引用
Secrets 在 workflow 中通常通过 `${{ secrets.NAME }}` 引用,再传给环境变量:
env:
API_TOKEN: ${{ secrets.API_TOKEN }}
脚本里读取环境变量即可。不要把密钥拼进命令输出,也不要为了调试打印完整变量。GitHub 会对已识别的 Secrets 做脱敏,但这不是万能保护。经过编码、截断、拼接后的密钥,可能不会被完整遮蔽。
四、日志泄露往往来自调试
很多泄露不是 GitHub 保存方式有问题,而是调试时手滑。比如运行 env 打印所有变量,curl 命令带着 Token 输出到日志,脚本异常时把请求头完整打印。公开仓库的 Actions 日志可被更多人看到,风险更高。
调试时可以打印“变量是否存在”或“字符串长度”,不要打印值本身。需要查看请求失败原因时,隐藏 Authorization 头,或在本地安全环境中复现。
五、Secrets和Variables要分开
GitHub 还有 Variables,适合保存非敏感配置,例如区域、构建目标、公开站点地址。把非敏感值放 Variables,能让 workflow 更易读;把敏感值放 Secrets,能减少误暴露。
不要因为 Variables 使用方便,就把 Token 放进去。Variables 不是为密钥保护设计的。团队协作中,应明确哪些配置可以公开,哪些必须按密钥管理。
六、环境隔离降低误用风险
测试环境和生产环境应使用不同 Secrets。测试部署即使失败,也不应该接触生产 Token。结合 GitHub Environments,可以把 STAGING_TOKEN 放 staging,把 PRODUCTION_TOKEN 放 production,并给 production 加审批。
这样做还有一个好处:当测试 Token 泄露或失效时,不影响生产凭证;生产 Token 轮换时,也不会破坏测试流程。
七、定期轮换和撤销
Secrets 不是设置一次就永久安全。成员变动、服务迁移、疑似泄露、权限调整后,都应轮换 Token。对关键凭证,建议记录创建时间、用途和负责人。无法确认用途的旧 Token,应先评估再撤销。
如果密钥已经提交到仓库历史,不要只删除当前文件。应立即撤销旧密钥,生成新密钥,并视情况清理历史记录。公开仓库尤其要谨慎,因为爬虫可能已经抓取了泄露内容。
八、适合站长项目的安全习惯
站长常用 GitHub Actions 做部署、备份、链接检查和数据同步。每个用途最好使用独立 Token,不要一个 Token 管所有事情。部署站点用部署 Token,调用统计 API 用统计 Token,上传文件用上传 Token。某个任务出问题时,影响范围更小。
GitHub Secrets 的核心是减少凭证裸露,但真正的安全来自最小权限、环境隔离、日志克制和及时轮换。只要把这几件事做好,Actions 自动化就能在便利和安全之间取得平衡。
九、Pull Request中的Secrets要特别小心
公开仓库收到外部贡献者 PR 时,Secrets 的可用范围会受到限制,这是为了防止恶意 PR 读取密钥。维护者不应为了让外部 PR 完整跑部署流程,就放宽 Secrets 暴露范围。更稳妥的方式是让外部 PR 只跑不需要密钥的测试,合并后再由受信任分支触发部署。
如果确实需要测试外部服务,可以使用权限很低的测试 Token,并且只允许访问测试资源。不要让生产 Token 出现在处理外部 PR 的 workflow 中。开源仓库尤其要理解这一点,否则一次看似普通的贡献就可能变成密钥泄露入口。
十、脚本错误也可能泄露密钥上下文
即使没有直接打印 Token,错误日志也可能暴露敏感上下文。例如 curl 失败时输出完整请求头,部署工具 debug 模式打印配置文件,Node 或 Python 异常把环境变量快照写入日志。GitHub 会遮蔽已登记的 Secret 值,但无法理解所有派生形式。
因此,脚本层面也要控制日志。生产部署命令默认不要开启 verbose;异常处理不要 dump 全部环境;请求失败时只输出状态码、错误摘要和可公开的请求地址。日志越克制,密钥管理越安全。
十一、个人Token和机器Token要分开
很多小项目直接使用维护者个人 Token 做自动部署。这样配置快,但当个人离开团队、账号权限变化或 Token 过期时,部署会受影响。更合理的做法是使用专门的机器账号、部署密钥或服务端 Token,并把权限限制在项目需要的范围。
如果只能使用个人 Token,也要记录用途和过期时间,并避免绑定过多仓库。不要把同一个高权限 Token 同时用于部署、包发布、数据同步和后台管理。用途越分散,轮换时越痛苦,泄露后影响也越大。
十二、发现泄露后的第一反应
一旦怀疑密钥泄露,第一步不是删日志或改提交,而是立即撤销旧密钥。公开仓库中的泄露内容可能已经被缓存或抓取,删除文件不能让旧密钥重新安全。撤销后再生成新密钥,检查调用记录,确认是否有异常访问。
随后再清理仓库历史、更新 Secrets、通知相关人员。处理顺序很重要:先止损,再清理痕迹,最后复盘流程。把 GitHub Secrets 当成保险箱之前,也要准备好密钥失效时的应急步骤。
十三、把密钥管理写进项目交接
项目交接时,除了代码和部署文档,还应交接密钥用途。哪些 Secrets 用于部署,哪些用于通知,哪些用于第三方 API,谁有权限轮换,过期后会影响什么流程,这些信息如果没人知道,后续维护会很被动。
可以用不含密钥值的清单记录名称、用途、负责人和轮换周期。清单只描述元信息,不保存真实 Token。这样既不增加泄露风险,又能让新维护者理解自动化流程依赖哪些凭证。

