通过一条命令创建应用了安全默认设置的 GitHub 仓库。
gh-safe-repo create <owner/repo>
分支保护、不可变标签、锁定的 Actions、Dependabot、带推送保护的密钥扫描以及私有漏洞报告,都会在你推送第一个提交之前配置好。同一个工具还会审计并修复你已有的仓库,并在代码离开你的机器之前扫描本地代码中的密钥。
状态: 核心工作流稳定,并已通过端到端验证,但 CLI 仍在打磨中。在 1.0 之前可能会有偶发的破坏性变更。
--local 和 --fromGitHub 的默认设置更偏向可发现性而非安全性:新仓库没有分支保护、没有 Dependabot,并且 Actions 可以写入仓库并批准自己的拉取请求。gh-safe-repo 改变了这一点,并在触碰任何内容之前向你展示计划:
--public 使其公开。每个设置都可配置。有关确切值,请参阅安全默认值;有关如何更改它们,请参阅配置。
要求:
gh CLI(gh auth login),或在环境中设置了 GITHUB_TOKENuvPATH 中找到,或通过 podman/docker 运行;两者都没有时,会使用正则扫描器。使用 --local 或 --from 推送代码还需要你用于 GitHub 的常规 git 凭据。请参阅推送代码。
git clone https://github.com/AriESQ/gh-safe-repo
cd gh-safe-repo
uv tool install .
gh-safe-repo --help
无需安装即可运行:
uv sync
./gh-safe-repo create <owner/repo>
1. 预览。 --dry-run 不会发起任何 API 调用,也不会创建任何内容。
$ gh-safe-repo create AriESQ/demo-repo --dry-run
Configuring AriESQ/demo-repo...
Planned Changes
Type Category Setting Value / Note
------ ----------------- -------------------------------------- ----------------------------------------------------------------
ADD repo repository AriESQ/demo-repo
DELETE file readme README.md
UPDATE actions allowed_actions 'all' → 'selected'
UPDATE actions verified_allowed False → True
UPDATE actions sha_pinning_required False → True
UPDATE actions default_workflow_permissions 'write' → 'read'
UPDATE actions can_approve_pull_request_reviews True → False
SKIP branch_protection branch_protection Branch protection requires a public repo or paid GitHub plan
SKIP security dependabot_alerts Requires a public repo or paid GitHub plan
SKIP security secret_scanning Requires a public repo or paid GitHub plan
SKIP security dependabot_security_updates Requires a public repo or paid GitHub plan
SKIP security private_vulnerability_reporting Requires a public repo or paid GitHub plan
SKIP security enable_dependency_graph Requires a public repo or paid GitHub plan
SKIP security enable_secret_scanning_push_protection Requires a public repo or paid GitHub plan
SKIP tag_protection tag_protection Tag protection rulesets require a public repo or paid GitHub plan
7 change(s) to apply, 8 skipped
Dry run — no changes made.
SKIP 行展示的是免费计划下私有仓库的样子。这些功能需要公开仓库或付费计划,工具会明确说明这一点,而不是静默失败。参见 GitHub 计划限制。
2. 应用。 去掉 --dry-run。你会看到相同的计划,然后出现确认提示(--yes 可跳过该提示)。
gh-safe-repo create AriESQ/demo-repo
3. 开始工作。 成功后,你会看到一个 Verified 部分(每项设置都从 GitHub 回读验证)以及一个带有可直接粘贴命令的横幅:
╭─ Done ───────────────────────────────────────────────────╮
│ Repository created successfully! │
│ https://github.com/AriESQ/demo-repo │
│ │
│ Add remote to existing repo: │
│ SSH : git remote add origin [email protected]:AriESQ/… │
│ HTTPS: git remote add origin https://github.com/… │
│ │
│ Clone fresh: │
│ SSH : git clone [email protected]:AriESQ/demo-repo.git │
│ HTTPS: git clone https://github.com/AriESQ/demo-… │
╰──────────────────────────────────────────────────────────╯
你首选的协议(gh config get -h github.com git_protocol)会列在最前面。
gh-safe-repo create <owner/repo> # private (default)
gh-safe-repo create <owner/repo> --public # public: branch and tag protection apply
仓库已初始化,因此存在一个默认分支(分支保护需要它),随后自动生成的 README.md 会被删除,以便你从干净状态开始。在配置中设置 auto_init = true 可保留它。所有者必须与你已认证的账户匹配;这可以防止在多账户系统上出现错误。
gh-safe-repo create <owner/repo> --local ~/projects/myapp
扫描目录以查找密钥,创建仓库,推送每个分支和标签,然后在你的原始目录中设置 origin 和上游跟踪,使 git push 立即可用。如果 origin 已指向其他位置,则保持不变,横幅会告诉你应该运行什么命令。之后,每个已推送的分支和标签都会与 GitHub 逐 SHA 进行校验。详情见推送代码。
gh-safe-repo create <owner/repo> --from <owner/source>
gh-safe-repo create <owner/pub> --from <owner/priv> --public # scanned thoroughly first
以完整历史克隆源仓库,对其进行扫描,将其镜像到新仓库,并复制源的默认分支、描述和主题。如果你在扫描阶段中止,则不会有任何代码到达 GitHub。
gh-safe-repo fix <owner/repo> --dry-run # what is out of compliance?
gh-safe-repo fix <owner/repo> # apply the missing defaults
gh-safe-repo fix <owner/repo> --yes # no prompt, for scripts
fix 会读取每一项设置,对存在差异的项显示 UPDATE,对已经正确的项显示 SKIP,并且只对真正的变更调用 API。它仅处理设置(不进行密钥扫描)。你需要拥有该仓库的管理员权限,该仓库可能归属于某个组织或其他账户。
gh-safe-repo scan .
gh-safe-repo scan . && git push # exit 1 on critical findings
仅限本地。不会向 GitHub 发送任何内容。参见预检扫描器。
gh-safe-repo [--config PATH] [--debug] create <owner/repo> [OPTIONS]
gh-safe-repo [--config PATH] [--debug] fix <owner/repo> [OPTIONS]
gh-safe-repo [--config PATH] [--debug] scan <path> [OPTIONS]
--config 和 --debug 是全局选项,可以放在命令之前或之后;
如果给出两次,后一个生效。其他选项必须跟在命令之后。
--config 接受可选值,因此单独的 --config 应放在最后:
gh-safe-repo --config scan ./src 会把 scan 当作路径读取。
所有面向 GitHub 的命令都接受 owner/repo(例如 myuser/my-repo)。
全局选项
| 选项 | 描述 |
|---|---|
--config [PATH] | 要使用的配置文件。单独的 --config 仅使用内置默认值 |
--debug | 打印每次 API 调用和响应。对于 fix,还会打印解析后的仓库身份(id、全名、所有者类型) |
create <owner/repo>
| 选项 | 描述 |
|---|---|
--public | 创建公开仓库(默认:私有) |
--local PATH | 将本地 git 仓库推送到新仓库。运行预检扫描。与 --from 互斥 |
--from OWNER/REPO | 将现有仓库镜像到新仓库。运行预检扫描。与 --local 互斥 |
--yes、-y | 跳过确认提示。扫描警告会被接受;严重发现仍会中止运行(退出码 1)。当 stdin 不是终端时必需 |
--dry-run | 打印计划,不进行任何 API 调用 |
--json | 将计划以 JSON 形式输出到 stdout。在实际运行时,会在结束时打印一次,并附带 verification 块 |
fix <owner/repo>
| 选项 | 描述 |
|---|---|
--yes、-y | 跳过确认提示。当 stdin 不是终端时必需 |
--dry-run | 显示设置差异而不应用 |
--migrate-branch-protection | 将经典分支保护转换为规则集。参见分支保护 |
--json | 将计划以 JSON 形式输出到 stdout。在实际运行时,会在结束时打印一次,并附带 verification 块 |
scan <path>
| 选项 | 描述 |
|---|---|
--json | 将发现以 JSON 形式输出到 stdout |
Type 列在终端中会着色。当 stdout 不是终端或设置了 NO_COLOR 时,颜色会被丢弃。
| 类型 | 含义 |
|---|---|
ADD | 正在应用的新设置 |
UPDATE | 正在更改的现有设置 |
DELETE | 正在移除的设置或文件 |
SKIP | 无需操作:已经正确,或在此计划/可见性下不可用 |
使用 --json 时,文档是 stdout 上的唯一内容。进度、警告、提示和横幅会输出到 stderr。