开源仓库
为仓库的公开发布做好准备,使没有先前背景的外部人员能够构建、使用和贡献,并确保没有敏感内容随附。按顺序执行步骤;密钥审计首先进行,因其结果(保留还是重建仓库)会影响后续所有操作。
何时使用
- 将私有仓库设为公开
- 审计已有的公开仓库的发布质量(“使其正式”)
- 为项目选择许可证
- 在公开发布前设置打包、版本控制或发布自动化
何时不使用
- 对已发布项目的常规开发(无发布事件)
- 审计第三方代码的漏洞(使用安全审核技能)
- 从保持私有的仓库发布包 — 仅应用发布管理步骤;跳过其余步骤
工作流程
步骤 1:检测组织配置文件
bash {baseDir}/scripts/detect_org.sh
该脚本检查 git 远程和最近提交者邮箱,并打印一个配置文件名称。如果打印 trailofbits,立即阅读 references/trailofbits.md 并在后续步骤中应用其许可证策略、发布账户和流程说明。如果打印 generic,则仅使用通用指南。如果用户说检测错误,相信用户。
步骤 2:审计密钥 — 优先于其他一切
一个曾经包含密钥(API 密钥、凭据、客户数据)的仓库不应直接公开。重写历史易出错且无法覆盖分支、缓存或 CI 工件。可靠的修复方法是创建一个新仓库:复制当前树,提交,并私下归档旧仓库。
- 询问项目是否处理过密钥或客户机密材料。对于安全咨询公司的工具,还需询问测试夹具或示例数据是否来自客户项目。
- 如果可能,使用专用工具扫描完整历史 —
gitleaks git .或trufflehog git file://.— 而不是目测。 - 检查 git 树之外:GitHub Actions 日志和工件、旧版本、问题和 PR 历史以及仓库 Wiki 都会随仓库一起公开。
- 公开后,在仓库设置中启用 GitHub 密钥扫描和推送保护。
拒绝以下合理化理由 — 这是发布后无法修复的唯一步骤:
- “密钥已撤销,所以历史没问题。” 撤销的凭据仍会泄露基础设施名称、内部 URL 以及攻击者用于定位的模式。
- “我们将使用 git-filter-repo 重写历史。” 重写会遗漏分支、克隆、缓存和 CI 工件;新仓库方法不会。
- “只是测试数据。” 来自客户项目或生产系统的夹具无论标签如何都是机密的。
步骤 3:运行就绪性检查
bash {baseDir}/scripts/check_readiness.sh
该脚本打印存在指示器清单(README、LICENSE、CONTRIBUTING、SECURITY.md、CI、测试、semver 标签等),并警告可能包含密钥的已跟踪文件。将未勾选项视为讨论提示而非硬性失败 — 研究原型不需要旗舰库所需的一切。与用户一起查看差距并修复对此项目重要的部分。
步骤 4:文档
README 是项目的门面。确认它解释了:
- 项目是什么以及它解决什么问题(第一段)
- 如何安装 — 包管理器、容器镜像或从源码构建;仅使用仓库中的内容,全新克隆构建必须能工作
- 如何使用 — 至少一个具体、可复制粘贴的示例
- 如何贡献 — 内联或通过
CONTRIBUTING.md - 许可证 — 一个简短的命名部分
还要添加:
SECURITY.md,包含漏洞报告说明(联系地址或 GitHub 私有漏洞报告)。对于安全工具,这是基础要求。- API 文档,构建并托管(通过 CI 的 GitHub Pages 是常规方式),从 README 和仓库网站字段链接。有关每个生态系统的文档工具,请参阅下面的语言参考。
- 如果项目期待外部贡献者,则需行为准则。
步骤 5:许可
没有许可证意味着不是开源,无论可见性如何。阅读 references/licensing.md 了解选择标准和机制。简短版本:
- 如果步骤 1 中检测到组织策略,则应用该策略。
- 否则:Apache 2.0 作为宽松默认选择,当竞争对手私下修改是真实关切时使用 AGPLv3,非代码工件使用 Creative Commons。
- 添加
LICENSE文件,在包元数据中设置 SPDX 标识符,在 README 中声明许可证,并确认三者一致。
步骤 6:测试和 CI
- 确认测试套件存在并通过;带有失败默认分支的公共仓库表示已被放弃。
- 确保 CI 在每个 PR 上以及所有支持的语言版本和平台矩阵中运行测试。
- 在 CI 中强制执行格式化和 linting(下面参考中的每种语言工具),以便样式争论永不进入审查。
- 尊重现有工具。 不要替换工作中格式化程序、linter 或类型检查器作为开源的一部分。如果落后于当前一代(语言参考中列出了当前工具),警告维护者并让他们决定;仅当某类工具完全缺失 — 无类型检查器、无形格式化程序 — 时才添加当前默认工具。
- 考虑当覆盖率下降时使 CI 失败的覆盖率门禁。
- 在它们成为公共攻击面之前强化工作流程本身:
- 将第三方操作固定到完整提交 SHA;为
github-actions启用 Dependabot 以保持固定最新。 - 设置最小权限
permissions:块(从permissions: {}开始)。 - 使用
zizmor .github/workflows/审计,使用actionlint进行 lint。
- 将第三方操作固定到完整提交 SHA;为
步骤 7:仓库设置
- 默认分支的分支保护:禁止强制推送,需要 PR。新仓库优先使用 rulesets;经典分支保护仍受支持。
- 合并保护:必需的状态检查,以便 PR 不能合并失败测试。
- Dependabot 或 Renovate 用于依赖和 Actions 更新。分组更新以减少 PR 噪音,并设置冷却窗口(例如 7 天),以便新发布 — 有时被劫持 — 的版本在采用前经过生命周期。
.editorconfig以便贡献者的编辑器在空白基础上达成一致。- 标签:当有多个问题或 PR 需要标签时立即创建;带前缀的标签对方面扩展良好(
C:组件,P:平台)。参见 blight's labels 作为示例。
步骤 8:发布和版本控制
- 按照 semver 为每个发布打标签
vX.Y.Z;对于候选版本和预发布版本使用-rc.N/-pre.N后缀。 - 使发布由 CI 驱动:推送标签(或发布 GitHub Release)触发构建、打包和上传,无需手动步骤。发布应该是
git tag vX.Y.Z && git push origin vX.Y.Z。 - 使用组织拥有的账户而不是个人账户发布包,并在索引支持的地方使用受信发布(OIDC) 而不是长期令牌。
步骤 9:特定语言实践
从其标记文件识别项目的语言,并阅读匹配的参考以了解打包、发布和质量工具:
| 标记文件 | 参考 |
|---|---|
pyproject.toml, setup.py | references/python.md — 工具方面引用现代 Python 技能 |
CMakeLists.txt, Makefile (C/C++) | references/c-cpp.md |
Cargo.toml | references/rust.md |
go.mod | references/go.md |
package.json | references/javascript.md |
Gemfile, *.gemspec | references/ruby.md |
对于其他生态系统,应用横切原则:从全新克隆可重现构建、CI 驱动发布、受信发布或组织拥有的账户、以及包清单中的许可证元数据。
最终审查
在切换可见性之前,从外部人员角度验证:
- 克隆到干净目录并严格遵循 README 的构建说明 — 它们在没有内部知识的情况下能否工作?
- 重新运行
{baseDir}/scripts/check_readiness.sh并确认剩余的差距是有意选择的,并向用户说明。 - 确认密钥审计(步骤 2)确实已执行;这是发布后无法修复的唯一步骤。
然后将仓库设为公开是仓库设置更改。如果组织有发布公告的流程,可以将发布与公告配对。
附加资源
参考文件
- references/licensing.md — 许可证选择标准、SPDX 元数据、分支和重新许可
- references/trailofbits.md — Trail of Bits 策略覆盖(仅在步骤 1 检测到时加载)
- references/python.md、references/c-cpp.md、references/rust.md、references/go.md、references/javascript.md、references/ruby.md — 每种语言的打包、发布和质量工具
脚本
scripts/detect_org.sh— 根据 git 远程和提交者邮箱打印组织配置文件(trailofbits或generic)scripts/check_readiness.sh— 打印发布就绪文件的存在指示器并标记通常包含密钥的已跟踪文件