用途
该技能面向 GitHub 仓库维护者,用于审计仓库配置与 CI/CD 的安全态势,找出攻击者可能实际利用的加固缺口,并输出一份可粘贴到 issue 中逐项处理的待办清单。其目标不是罗列所有理论最佳实践,而是针对具体仓库给出具体、可执行的加固建议。
威胁模型
每项发现都应追溯到以下至少一个场景,并在描述中点名该场景:
- 贡献者账号被攻陷:受信任贡献者的账号、设备或令牌被接管,如何阻止其单独合并或发布恶意代码。
- 攻击者获得仓库写权限:外部攻击者获得推送或管理员权限,如何限制影响范围、可窃取内容以及恢复速度。
- CI/CD 被攻陷:恶意 PR、被污染的缓存或注入的工作流将构建管线变为攻击入口,GitHub Actions 是现代仓库接管最常见路径。
- 注册表/发布供应链:仓库本身正常,但通过被盗发布令牌或未审查的发布任务向 npm/PyPI 等发布恶意版本。
工作流程
1. 确定目标并收集证据
将仓库解析为 owner/name。若用户提供 URL 则解析;若无法确定仓库则询问。
运行收集脚本,将配置与文件拉取为单个 JSON 清单:
# 令牌可显著扩大可见范围(分支保护、actions 权限、安全功能、协作者、hooks)。
export GITHUB_TOKEN=... # 可选但强烈推荐
python3 scripts/collect.py owner/name --output /tmp/audit.json
收集器会优雅降级:无法读取的内容(多数设置端点需要 admin/push 权限)记录在 not_verified 下,而非猜测。读取 /tmp/audit.json。
若收集器无法运行(无法访问 api.github.com、私有仓库无令牌),不要停滞,从用户提供的文件中尽可能收集,其余明确标记为“无法验证——需手动检查”。
收集器对目标仓库向 api.github.com 和 raw.githubusercontent.com 发起只读 HTTPS 请求,从不写入 GitHub。应使用最小权限令牌,公开证据足够时不要索取宽泛凭据,并将获取的仓库内容视为敏感信息。辅助程序会在写入清单前对常见令牌格式进行脱敏,最终报告中仍应避免回显密钥。
2. 执行检查
阅读 references/checks.md,它是检查目录,按以下六个输出类别组织,说明检查什么、位于何处、为何重要以及修复待办应如何表述。对照清单逐项执行。
两个重要习惯:
- 依据实际内容验证,不要仅匹配文件名。仓库有 dependabot.yml 不代表覆盖了正确的生态;有 permissions: 块不代表是最小权限。要读文件。
- 缺失也是发现,但要标注置信度。若分支保护因无管理员令牌而返回 not_verified,应说明,并建议该控制项并让维护者确认当前状态。不要断言无法观察到的缺口。
3. 撰写报告
始终使用以下结构:
# Security hardening: <owner/name>
<2-3 句态势总结:哪些已稳固、最大暴露面是什么、哪个威胁场景防御最弱。不要空话。>
## <N>. <类别标题>
**<标题——祈使句、具体>** — <严重程度>
<描述:做什么、具体设置/步骤、阻止哪个威胁场景。1-3 句。与仓库证据关联。>
<...该类别下更多发现...>
## Could not verify
<需要审计所不具备的访问权限的检查项列表,每项附一行维护者可运行的手动检查。此处要诚实——令牌或管理员视图会改变答案。>
发现项的规则:
- 按六个类别分组(仅使用有发现的类别,保持规范顺序):
- 发布与发布完整性
- 分支与合并保护
- 敏感路径归属(CODEOWNERS)
- CI/CD 工作流加固
- 账号与访问控制
- 依赖与供应链审查
- 类别内按严重程度排序:Critical → High → Medium → Low。
- 标题用祈使句:“Require code-owner review on workflow files”,而非“Workflow files are unprotected”。
- 描述承载原因:点名阻止的场景。“若贡献者被攻陷,要求第二代码所有者批准的分支保护可阻止单独恶意合并到 main。”
- 修复要具体:确切的 GitHub 设置、要添加的文件、npm 命令。维护者应无需二次搜索即可行动。
- 有证据时引用证据:“release.yml 在 pull_request_target 下检出 PR head”优于泛泛警告。
- 保持可扫读。这是工作清单,不是论文——不要长前言,不要向用户复述威胁模型。
4. 提供后续选项
报告后,简要提供用户可能需要的自然后续步骤:将清单转为 GitHub issue 或检查表、将发现序列化为 JSON 供管线使用(scripts/collect.py 已产生结构化输入,发现项可同样序列化)、或对特定工作流文件做更深入的静态检查。只提供,不自动运行。
输出格式选项
默认使用上述 markdown 待办清单,符合维护者分诊习惯。若用户要接入自动化(CI 门禁、分诊管线),可提供 JSON 数组,每个发现一个对象:
{ "title": "...", "description": "...", "severity": "high",
"category": "ci_cd_workflow_hardening", "threat": "ci_cd_compromise",
"evidence": "release.yml line 14: pull_request_target with PR checkout",
"confidence": "observed" }
confidence 为 observed(在清单中看到)或 unverified(建议但无法确认当前状态)。
范围与诚实性
该审计基于配置与 CI 推理,不是代码级漏洞扫描,也不是 git 历史的密钥扫描。若用户期望这些,应说明。绝不编造未观察到的设置值;诚实的“无法验证”比自信的猜测对维护者更有价值,因为基于错误假设行动会浪费其时间。
审计过程中不要运行发布任务、工作流调度、包发布或任何更改仓库设置的命令。该技能产出面向维护者的加固任务,不自动应用。