Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
gh-safe-repo — Python CLI,可自动创建具有安全默认设置的GitHub仓库——分支保护、Dependabot、秘密扫描和预检安全扫描。 | Kitploit
工具/GitHubGitHub/ariesq/gh-safe-repo
通用工具漏洞扫描器脚本与自动化配置审计云安全DevSecOps秘密检测
GitHubariesq/gh-safe-repo

gh-safe-repo

Python CLI,可自动创建具有安全默认设置的GitHub仓库——分支保护、Dependabot、秘密扫描和预检安全扫描。

查看仓库
383520天前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

gh-safe-repo

创建自动应用安全默认设置的GitHub仓库。用一个命令取代创建后需要五分钟检查的设置清单。``` gh-safe-repo create <owner/repo>

root@kitploit:~
分支保护、不可变标签、Dependabot、受限的 Actions 权限、带有推送保护的密钥扫描,以及禁用的 Wiki 和 Projects——所有这些在你编写第一行代码之前就已配置完毕。

gh-safe-repo 正处于重度开发阶段。它对于使用安全默认值创建新仓库的场景表现出色。我正在努力完善 CLI 选项,以更好地符合用户预期。在发展到发布版本并稳定 CI/CD 之前,预计会有破坏性变更。✌️

---

## 目录

- [为什么](#为什么)
- [它改变了什么](#它改变了什么)
- [要求](#要求)
- [安装](#安装)
- [快速开始](#快速开始)
- [CLI 参考](#cli-参考)
- [模拟运行/计划输出](#模拟运行计划输出)
- [修复模式(审计现有仓库)](#修复模式审计现有仓库)
- [镜像仓库(`--from`)](#镜像仓库---from)
- [从本地目录创建仓库(`--local`)](#从本地目录创建仓库---local)
- [预检安全扫描器](#预检安全扫描器)
  - [独立扫描](#独立扫描)
  - [抑制误报](#抑制误报)
- [配置](#配置)
- [GitHub 计划限制](#github-计划限制)
- [工作原理](#工作原理)
- [开发](#开发)

---

## 为什么

GitHub 的默认仓库设置针对可发现性和灵活性进行了优化,而非安全性。每个新仓库都附带:

- Wiki 和 Projects 已启用(攻击面,即使未使用)
- 允许合并提交(历史混乱,但并非主要问题)
- 无分支保护(任何具有写入权限的人都可以直接推送到 `main`)
- 无 Dependabot 警报
- GitHub Actions 具有对仓库的写入权限
- Actions 允许批准 PR

手动修复所有这些设置每个仓库需要几分钟,而且很容易忘记。`gh-safe-repo` 一次性应用一套有主见但实用的默认设置,并提供计划预览,让你在执行任何更改之前确切知道将要更改的内容。

---

## 它改变了什么

### 仓库设置

| 设置 | GitHub 默认值 | 安全默认值 | 备注 |
|---|---|---|---|
| 可见性 | 公开 | **私有** | 传递 `--public` 以覆盖 |
| Wiki | 启用 | **禁用** | |
| Projects | 启用 | **禁用** | |
| Issues | 启用 | 启用 | |
| 合并后删除分支 | 关闭 | 关闭 | 在配置中设置为 `true` 以自动清理 |
| 允许合并提交 | 开启 | 开启 | 在配置中设置为 `false` 以仅允许压缩合并 |
| 允许压缩合并 | 开启 | 开启 | |
| 允许变基合并 | 开启 | 开启 | |

### GitHub Actions

| 设置 | GitHub 默认值 | 安全默认值 |
|---|---|---|
| 允许的操作 | 全部 | **选定**(GitHub 拥有 + 已验证创建者;可自定义) |
| 默认工作流权限 | 读/写 | **只读** |
| Actions 可以批准 PR | 是 | **否** |
| 要求 SHA 固定 | 否 | **是**(工作流必须将操作固定到提交 SHA,而非可变标签) |
| Fork PR 批准策略 | 首次贡献者(新 GitHub 用户) | **所有外部贡献者**——在 fork PR 工作流运行 CI 之前需要批准。选项:仅全新 GitHub 账户(GitHub 默认)、仓库首次贡献者、或所有 fork PR(最安全) |

### 分支保护(公开仓库,或任何付费计划上的仓库)

| 规则 | 值 |
|---|---|
| 合并前要求拉取请求 | 是 |
| 所需批准审查数 | 1 |
| 推送时忽略过期的审查 | 是 |
| 要求解决对话 | 是 |
| 允许强制推送 | 否 |
| 允许删除分支 | 否 |
| 对管理员强制执行 | 否(允许所有者工具进行推送) |

分支保护默认通过 **规则集 API** 应用(`use_rulesets = true`):一个单一的 `gh-safe-repo defaults` 规则集覆盖每个已配置的分支,并通过绕过参与者而非经典的 `enforce_admins` 标志来表示“管理员可以绕过”。设置 `use_rulesets = false` 以使用传统的每个分支经典路径(保留一个发布周期)。

**从经典保护迁移现有仓库:** 如果 `fix` 在仓库上发现经典分支保护,除非传递 `--migrate-branch-protection`,否则拒绝将其转换为规则集。仅限经典的规则在该工具构建的规则集中没有等效项,否则会静默丢弃——已知差距:

- `required_status_checks`——规则集主体中未建模所需的 CI 检查。
- `restrictions`(按用户/团队的推送限制)——规则集通过绕过参与者以不同方式建模,非 1:1 映射。
- 每个分支的差异——单个共享条件规则集无法为 `master` 和 `main` 表达不同规则。

使用该标志时,`fix` 创建/更新规则集,然后删除每个分支上的经典保护,以避免两层叠加。

### 标签保护(公开仓库,或任何付费计划上的仓库)

标签保护创建一个 GitHub 规则集,针对所有标签(默认 `*`,可通过 `protected_tags` 配置)。强制实施以下规则:

| 规则集规则 | 强制实施? | 备注 |
|---|---|---|
| 限制创建 | 否 | |
| **限制更新** | **是** | 防止重写/强制推送标签 |
| **限制删除** | **是** | 防止 `git push --delete` 标签 |
| 要求线性历史 | 否 | |
| 要求部署成功 | 否 | |
| 要求签名提交 | 否 | |
| 要求状态检查通过 | 否 | |
| 阻止强制推送 | 否 | |

仓库管理员在绕过列表中(与分支保护 `enforce_admins = false` 默认值一致)。仅适用于公开仓库或付费 GitHub 计划(与分支保护相同限制)。免费计划的私有仓库将在计划输出中看到此步骤被跳过。

### 安全

| 功能 | 行为 |
|---|---|
| Dependabot 警报 | 启用(公开仓库/付费计划) |
| Dependabot 安全更新 | 启用(自动打开易受攻击依赖项的 PR) |
| 密钥扫描 | 公开仓库自动;私有付费计划启用 |
| 推送保护 | 启用(阻止包含支持密钥的提交) |
| 私有漏洞报告 | 启用(允许安全研究人员私下报告) |
| 依赖关系图 | 公开仓库自动;私有仓库无 REST API(仅 UI) |

---

## 要求

- Python 3.8+
- 已安装并认证的 [`gh` CLI](https://cli.github.com/)(`gh auth login`),**或** 在环境中设置 `GITHUB_TOKEN`
- 对于 `--local` / `--from`(推送或克隆代码):你的常规 git 凭证必须设置好——要么是加载到 `ssh-agent` 中的 SSH 密钥(当 `gh config get git_protocol` 为 `ssh` 时),要么是 HTTPS 凭证助手(`gh auth setup-git` 会自动配置一个)。OAuth 令牌**不**用于 git 推送,因此工作流文件(`.github/workflows/*`)推送时无需 OAuth `workflow` 作用域。
- [`uv`](https://docs.astral.sh/uv/) 用于从源代码安装(推荐)
- `truffleHog` v3(可选——用于预检扫描器;自动从 PATH 检测,或通过 podman/docker 运行;如果两者都不可用,则回退到正则表达式)

---

## 安装

### 使用 uv 从源代码安装(推荐)```bash
git clone https://github.com/your-username/gh-safe-repo
cd gh-safe-repo
uv tool install .

这将把 gh-safe-repo 安装到 uv 的工具环境中,并将其添加到你的 PATH 中。

无需安装直接运行```bash

git clone https://github.com/your-username/gh-safe-repo cd gh-safe-repo uv sync # creates .venv ./gh-safe-repo create <owner/repo>

root@kitploit:~
### 验证```bash
gh-safe-repo --help

快速入门```bash

Create a private repo with all safe defaults

gh-safe-repo create <owner/repo>

Preview what would happen — no changes made

gh-safe-repo create <owner/repo> --dry-run

Create a public repo (branch protection + security scanning applied)

gh-safe-repo create <owner/repo> --public

Mirror an existing repo into a new private repo (with pre-flight scan)

gh-safe-repo create <owner/repo> --from <owner/source>

Mirror a private repo to a new public repo (with pre-flight scan)

gh-safe-repo create <owner/pub> --from <owner/priv> --public

Create a repo from a local directory (with pre-flight scan)

gh-safe-repo create <owner/repo> --local ~/projects/myapp

Same, but make it public (branch protection applied before push)

gh-safe-repo create <owner/repo> --local ~/projects/myapp --public

Audit an existing repo and apply any missing safe defaults

gh-safe-repo fix <owner/repo>

Audit without making changes

gh-safe-repo fix <owner/repo> --dry-run

Apply fixes without confirmation prompt (scripting/batch use)

gh-safe-repo fix <owner/repo> --yes

Scan a local repo for secrets before pushing anywhere

gh-safe-repo scan . gh-safe-repo scan ~/projects/myapp

root@kitploit:~
---

## CLI 参考```
gh-safe-repo create <owner/repo> [OPTIONS]
gh-safe-repo fix <owner/repo> [OPTIONS]
gh-safe-repo scan <path> [OPTIONS]

所有与GitHub交互的命令都需要使用 owner/repo 格式(例如 myuser/my-repo)。对于 create,会根据你已认证的GitHub账户验证所有者,以防止在多账户系统上出错。对于 fix,则需要目标仓库的管理员权限,从而允许你修复由组织或其他账户拥有且你具有管理员访问权限的仓库。

create — 创建新仓库

单纯的 create(没有 --local/--from)会初始化仓库以使默认分支存在用于分支保护,然后删除自动生成的 README.md,使新仓库从干净状态开始。在配置中设置 auto_init = true 可以保留README。--local/--from 推送你自己的历史记录,且从不创建README。

fix — 审计并修复现有仓库

scan — 本地秘密扫描

选项说明
--config [PATH]配置文件路径;单独的 --config 仅使用内置默认值
--debug显示扫描器详情

如果没有严重发现,退出代码为 0,如果发现严重问题则为 1。


试运行 / 计划输出

--dry-run 精确显示 gh-safe-repo 将会执行的操作,而不做任何更改或API调用。在实际运行前使用它。与 --json 结合以获取机器可读的计划输出:```bash gh-safe-repo create <owner/repo> --dry-run --json gh-safe-repo fix <owner/repo> --dry-run --json

root@kitploit:~
当 `--json` 激活时,计划将作为 JSON 对象写入 stdout,所有其他消息(进度、警告、“试运行”脚注)将写入 stderr,因此输出是干净的,适合管道或脚本处理。```
$ gh-safe-repo create <owner/repo> --dry-run

  Plan for my-project (private)

  Category            Action  Setting                          Value
  ──────────────────────────────────────────────────────────────────
  Repository          ADD     repository                       my-project (private)
  Repository          ADD     has_wiki                         false
  Repository          ADD     has_projects                     false
  Actions             ADD     default_workflow_permissions     read
  Actions             ADD     can_approve_pull_request_reviews false
  Branch Protection   SKIP    branch_protection                Not available for private repos on free plan
  Security            SKIP    dependabot_alerts                Not available for private repos on free plan
  1 setting skipped (GitHub plan limitation).
  Dry run — no changes made.

操作颜色:

操作含义
ADD(绿色)正在应用的新设置

JSON 输出(--json):```json { "changes": [ { "type": "add", "category": "repository", "key": "has_wiki", "old": null, "new": false, "reason": null }, { "type": "skip", "category": "branch_protection", "key": "branch_protection", "old": null, "new": null, "reason": "Not available for private repos on free plan" } ], "summary": { "add": 5, "skip": 2 } }

root@kitploit:~
`summary` 仅包含计划中存在的类型。使用者应使用 `.get("delete", 0)` 等方法,而不是假设所有四个键都存在。

---

## 修复模式(审计现有仓库)

`fix` 将现有仓库的当前设置与安全默认值进行比较,并应用任何修正。不进行秘密扫描 — `fix` 纯粹与仓库设置有关。```bash
# See what's out of compliance
gh-safe-repo fix <owner/repo> --dry-run

# Apply missing safe defaults
gh-safe-repo fix <owner/repo>

# Apply without confirmation prompt (scripting/batch use)
gh-safe-repo fix <owner/repo> --yes

修复模式:

  1. 通过 GitHub API 获取每个设置的当前值
  2. 与期望的安全默认值进行比较
  3. 显示一个计划表,用 UPDATE 表示已更改的设置,用 SKIP 表示已经处于期望值的设置(无操作检测——它从不发起会改变任何内容的 API 调用)
  4. 在应用前提示确认(使用 --yes 跳过)

仅应用实际更改——已经处于期望值的设置显示为 SKIP,并且不产生 API 调用。


镜像仓库(--from)

--from 将现有仓库镜像到一个带有安全默认设置的新仓库。它适用于私密和公开目的地:```bash

Mirror into a new private repo (default)

gh-safe-repo create <owner/repo> --from <owner/source>

Mirror a private repo to a new public repo (riskiest operation — scanned thoroughly)

gh-safe-repo create <owner/pub> --from <owner/priv> --public

root@kitploit:~
**按顺序执行的操作:**

1. 你的 `github.com` 的 Git 凭据会首先被验证(当 `gh config get git_protocol` 为 `ssh` 时进行 SSH 探测;HTTPS 被认为是可信的),因此,在创建任何仓库之前,缺失密钥会快速失败。
2. 源仓库被克隆到本地(完整克隆,不使用 `--depth`,以便 truffleHog 可以遍历完整的提交历史)。
3. [预检安全扫描器](#pre-flight-security-scanner)在本地克隆上运行。
4. 你审查发现并确认(或中止)。
5. 创建一个新仓库(默认私有,或使用 `--public` 设为公开)。
6. 应用 Actions 权限和安全设置(Dependabot、秘密扫描、推送保护)。
7. 完整历史被镜像:`git clone --mirror` + `git push --mirror`。
8. 应用分支和标签保护(在代码推送之后,因此目标分支存在)。

如果扫描发现问题而你中止,则不会有任何代码被复制到 GitHub。

> **注意:** `--from` 对源和目标都使用 `owner/repo` 格式。

---

## 从本地目录创建仓库(`--local`)

`--local PATH` 是 `--from` 的本地到 GitHub 对应项。它创建一个新的 GitHub 仓库,并从本地 git 仓库推送代码。`PATH` 必须是一个已初始化的 git 仓库(`git init` 或克隆)。```bash
gh-safe-repo create <owner/repo> --local ~/projects/myapp
gh-safe-repo create <owner/repo> --local ~/projects/myapp --public

按顺序发生的事情:

  1. 首先验证你用于 github.com 的 git 凭据(当 gh config get git_protocol 为 ssh 时进行 SSH 探测;HTTPS 被信任),因此如果密钥缺失,会在创建任何仓库之前快速失败
  2. 起飞前安全检查器 直接在本地目录上运行(无需克隆)
  3. 你审查发现结果并确认(或中止)
  4. 创建一个新仓库,并应用 actions 权限和安全设置
  5. 使用 push --all --tags 推送完整历史(所有分支和标签)
  6. 应用分支和标签保护(在代码推送之后,因此目标分支已存在)
  7. 将 origin 添加到原始本地仓库,指向新的 GitHub URL,并配置当前分支的上游跟踪 — 这样 git push 和 git pull 立即生效,无需额外设置。

--local 和 --from 都适用于私有和公开仓库。它们互斥。

使用本地默认分支(通过 git -C PATH symbolic-ref HEAD)来定位分支保护规则,因此保护会应用于正确的分支,即使它不是 main。

提示: 如果你想在不创建任何东西的情况下检查发现结果,请先运行 gh-safe-repo scan PATH。


起飞前安全检查器

检查器在本地运行,从不将代码发送到 GitHub。在任何推送之前独立使用它,或者它会作为 --from 和 --local 工作流的一部分自动运行。

独立扫描```bash

Scan the current directory

gh-safe-repo scan .

Scan an explicit path

gh-safe-repo scan ~/projects/myapp

root@kitploit:~
Exit code is `0` if no critical findings, `1` if criticals are found — so it composes cleanly with other commands:```bash
gh-safe-repo scan . && git push

完整的 [pre_flight_scan] 配置同样适用:banned_strings、max_file_size_mb、trufflehog_mode 等。

检测内容

扫描引擎

gh-safe-repo 通过三步发现链自动选择最佳可用的扫描器:

  1. PATH 中的 truffleHog v3 —— 运行 trufflehog --version,确认为 v3 后使用。如果安装的是 v2 或无法识别的版本,则打印警告并回退至第 2 步。
  2. podman 或 docker —— 如果未找到原生 truffleHog,则扫描器在容器(ghcr.io/trufflesecurity/trufflehog:latest)中运行 truffleHog,使用 podman run 或 docker run,以只读方式挂载扫描路径至相同的绝对路径,使得 JSON 输出路径与原生运行一致。
  3. 正则表达式回退 —— 如果既没有原生安装也没有容器运行时可用,则打印警告并改用正则表达式扫描器。此外,该扫描器始终与 truffleHog 一起运行以检测电子邮件和 TODO,并捕获 truffleHog 有意跳过的孤立密钥 ID 模式(truffleHog 需要凭证对的两个部分,例如 AWS 密钥 ID 和 秘密访问密钥,才会标记发现)。

所选扫描器会显示在“运行预检安全扫描...”标题以及计划表的 SCAN 条目中,例如:``` Running pre-flight security scan... (truffleHog v3.93.4) Running pre-flight security scan... (truffleHog via podman) Running pre-flight security scan... (regex only — see warning above)

root@kitploit:~
容器路径识别的环境变量:`CONTAINER_RUNTIME` 用于覆盖运行时选择(例如 `CONTAINER_RUNTIME=docker`),以及 `TRUFFLEHOG_IMAGE` 用于固定特定的镜像标签。

### 通过 podman 或 Docker 运行 truffleHog(无需本地安装)

无需手动设置。`gh-safe-repo` 会自动检测 podman 或 docker(上述步骤2),并使用正确的卷挂载在容器中运行 truffleHog。`CONTAINER_RUNTIME` 和 `TRUFFLEHOG_IMAGE` 环境变量会被遵循。

提供了一个 shell 包装脚本(`tools/trufflehog`)和一个用于构建固定本地镜像的 `Containerfile`,位于 [`tools/`](https://github.com/ariesq/gh-safe-repo/blob/master/tools/README.md) 中,适用于希望系统范围内使用基于容器的 truffleHog,或需要离线镜像的用户。

### 交互式审查```
Pre-flight scan: my-private-project

  CRITICAL  my_private_project/config.py:12  AWS Access Key ID
            [redacted]

  WARNING   my_private_project/setup.py:3    Email address
            author_email="[email protected]"

  1 critical finding, 1 warning.

  Critical findings detected. Continue anyway? [y/N]:
  • 关键发现: 默认中止(N)。你必须显式输入y以继续。
  • 仅警告: 默认继续(Y)。按回车键继续或输入n中止。
  • 没有发现: 扫描静默完成,工作流继续。

输出中的机密信息会被编辑。电子邮件地址和TODO会显示匹配行。

扫描覆盖范围

默认跳过构建产物目录(node_modules、__pycache__、.venv、venv、dist、build)以保持扫描速度。在git仓库中,这种跳过是有条件的:在修剪目录之前,扫描器会运行git ls-files -- <dir>来检查其中是否有文件被跟踪。如果有,则正常扫描该目录。

这意味着已提交的node_modules或dist树——虽然不常见,但确实存在——不会被无声地遗漏。未提交的目录(通常情况)继续像之前一样被跳过。

当在克隆的源代码仓库中发现SKIP_DIRS子目录时,仍然会打印一条警告,因为它们的出现可能表明提交的内容比预期的多。

抑制误报

两个配置键可以让你抑制已知安全的发现,而无需禁用整个检查类别。

scan_exclude_paths —— 完全跳过文件或目录。值是以换行符/逗号分隔的正则表达式模式,与相对文件路径匹配。匹配的文件会被排除在所有检查之外:机密、电子邮件、TODO、大文件和AI上下文文件检测。相同的模式也会通过--exclude-paths传递给truffleHog,因此无论使用哪个扫描引擎,覆盖范围都是一致的。```ini [pre_flight_scan]

Exclude the GitHub API spec (example tokens) and all test fixtures

scan_exclude_paths = docs/api.github.com.json tests/fixtures/

root@kitploit:~
**`exclude_emails`** — 抑制针对特定地址或整个域名的邮件发现结果。值以换行符或逗号分隔,不区分大小写。以 `@` 开头的条目匹配该域名下的所有邮件地址;否则条目必须精确匹配完整地址。适用于工作目录和 Git 历史记录中的发现结果。```ini
[pre_flight_scan]
# Suppress bot addresses and placeholder domains
exclude_emails = [email protected], [email protected], @example.com

扫描器配置```ini

[pre_flight_scan] scan_for_secrets = true scan_for_emails = true scan_for_todos = true max_file_size_mb = 100

Scan git history for email addresses (requires scan_for_emails = true)

scan_email_history = true

Scanner selection: auto | native | docker | off

auto — try native truffleHog, fall back to container (podman/docker), then regex (default)

native — native truffleHog only; no container fallback

docker — container only; skip native PATH check

off — regex scanner only, no truffleHog attempt

trufflehog_mode = auto

Flag AI context files (CLAUDE.md, AGENTS.md, .cursorrules, etc.) as critical findings.

Their git history may contain more sensitive content than the current version.

warn_ai_context_files = true

Literal strings to flag as critical findings (case-insensitive).

Comma-separated or one per line (continuation lines must be indented).

banned_strings = secret

password

credential

Exclude files/directories from all scan checks (regex patterns, comma/newline separated).

The same patterns are passed to truffleHog via --exclude-paths.

scan_exclude_paths = docs/api.github.com.json

tests/fixtures/

Suppress email findings for specific addresses or entire domains (case-insensitive).

Entries starting with @ match all emails at that domain; otherwise exact address match.

exclude_emails = [email protected], [email protected], @example.com

root@kitploit:~
当发现被禁止的字符串或AI上下文文件时,扫描器会输出一条可直接运行的`git filter-repo`命令,用于在重新运行前将这些内容从源代码仓库的历史记录中移除。

---

## 配置

`gh-safe-repo` 按以下顺序查找配置(优先匹配第一个):

1. **`--config PATH`** — 显式覆盖
2. **`./gh-safe-repo.ini`** — 当前工作目录
3. **`$XDG_CONFIG_HOME/gh-safe-repo/gh-safe-repo.ini`** — 当 `$XDG_CONFIG_HOME` 未设置时,默认为 `~/.config`

单独的 `--config`(不带路径)会完全跳过文件查找,仅使用内置默认值。
所有值都有安全的默认值 —— 无需配置文件即可开始使用。

一个带有完整注释的示例配置文件包含在仓库中,文件名为 `gh-safe-repo.ini.example`。将其复制以开始使用:```bash
# User-level config (XDG)
mkdir -p "${XDG_CONFIG_HOME:-$HOME/.config}/gh-safe-repo"
cp gh-safe-repo.ini.example "${XDG_CONFIG_HOME:-$HOME/.config}/gh-safe-repo/gh-safe-repo.ini"

# Or project-level config (current directory)
cp gh-safe-repo.ini.example ./gh-safe-repo.ini

完整的配置参考```ini

[repo]

Whether new repos are private by default

private = true

Disable features that create clutter if unused

has_wiki = false has_projects = false has_issues = true

Auto-delete head branches after merge (default: off, matching GitHub)

delete_branch_on_merge = false

Merge strategies (all enabled by default, matching GitHub)

Set allow_merge_commit = false for squash-only workflows

allow_squash_merge = true allow_merge_commit = true allow_rebase_merge = true

Whether a plain create leaves an initialized README in the new repo.

false (default): the repo still gets a default branch (needed for branch

protection), but the auto-generated README.md is removed afterward.

true: keep the initialized README.

(Ignored for --local/--from, which always push your own history instead.)

auto_init = false

[actions]

Which actions are allowed to run: all | local_only | selected

allowed_actions = selected

When allowed_actions = selected, control which external actions are permitted:

github_owned_allowed = true # actions maintained by GitHub (e.g. actions/checkout) verified_allowed = true # actions from Marketplace verified creators

patterns_allowed = myorg/* # comma-separated allowlist (wildcards OK)

Principle of least privilege: read-only by default

Options: read | write

default_workflow_permissions = read

Prevent Actions from self-approving pull requests

can_approve_pull_request_reviews = false

Require workflows to pin actions to a specific commit SHA instead of a mutable tag

sha_pinning_required = true

[branch_protection]

Applied to public repos on any plan, and private repos on paid plans.

Branch to protect

protected_branch = main

Require a pull request before merging

require_pull_request = true

Number of approvals required

required_approving_reviews = 1

Dismiss existing approvals when new commits are pushed

dismiss_stale_reviews = true

Require all review comments to be resolved before merging

require_conversation_resolution = true

Do not enforce rules on administrators

false = repo owner can still push directly (needed for --from mirror workflow)

enforce_admins = false

Block force-pushes

allow_force_pushes = false

Block branch deletion

allow_deletions = false

Use the Rulesets API (default) instead of the legacy classic branch-protection

path. A single ruleset covers all configured branches, supports bypass actors,

and is GitHub's forward direction (new rule types are Rulesets-only). Set false

to fall back to the classic per-branch API, which is kept for one release cycle.

use_rulesets = true

[tag_protection]

Immutable tags via Rulesets API.

Only works on public repos or paid GitHub plans (same restriction as branch protection).

Glob pattern(s) for tags to protect — comma-separated.

protected_tags = *

Prevent deletion of matching tags (git tag -d / git push --delete)

prevent_tag_deletion = true

Prevent rewriting matching tags (git tag -f / force-push)

prevent_tag_update = true

[security]

Enable Dependabot vulnerability alerts

enable_dependabot_alerts = true

Auto-open PRs to fix vulnerable dependencies

enable_dependabot_security_updates = true

Let security researchers report vulnerabilities privately

enable_private_vulnerability_reporting = true

Block commits that contain supported secrets

enable_secret_scanning_push_protection = true

Note: The following features have no REST API and must be configured via UI or dependabot.yml:

- Grouped security updates: use dependabot.yml groups with applies-to: security-updates

- Automatic dependency submission: enable via repository settings UI

- Dependency graph: automatic for public repos; enable via UI for private repos

[pre_flight_scan] scan_for_secrets = true scan_for_emails = true scan_for_todos = true

Flag files larger than this threshold

max_file_size_mb = 100

Scan git history for email addresses (requires scan_for_emails = true)

scan_email_history = true

Scanner selection: auto | native | docker | off

auto = try native truffleHog, fall back to container (podman/docker), then regex

native = native PATH only

docker = container only

off = regex only

trufflehog_mode = auto

Flag AI context files (CLAUDE.md, AGENTS.md, .cursorrules, etc.) as critical findings.

warn_ai_context_files = true

Literal strings to flag as critical findings (case-insensitive).

Comma-separated, or one per line with continuation indentation.

banned_strings = secret

password

credential

Exclude files/directories from all scan checks (regex patterns, comma/newline separated).

Passed to truffleHog via --exclude-paths as well as applied to the regex walk.

scan_exclude_paths = docs/api.github.com.json

tests/fixtures/

Suppress email findings for specific addresses or entire domains (case-insensitive).

Entries starting with @ match all emails at that domain; otherwise exact address match.

exclude_emails = [email protected], [email protected], @example.com

[git_transport]

How git push/clone authenticates when using --local or --from: auto | user_creds | token

auto — use your own git credentials (SSH key or credential helper) when a

path exists; fall back to pushing over HTTPS with the API token in

the URL only when there is no SSH setup and no credential helper

(e.g. CI with just GITHUB_TOKEN). (default)

user_creds — never use the API token for git. Pushes with your own credentials

only; this avoids needing the workflow token scope to push

.github/workflows files.

token — always push over HTTPS with the API token in the URL. For CI where

the token was granted the workflow scope intentionally.

mode = auto

root@kitploit:~
---

## GitHub 计划限制

某些功能仅根据仓库可见性和您的 GitHub 计划可用。

| Feature | Free + Public | Free + Private | Pro/Team + Private |
|---|:---:|:---:|:---:|
| Branch protection / Rulesets | Yes | No | Yes |
| Tag protection (Rulesets) | Yes | No | Yes |
| Dependabot alerts | Yes | No | Yes |
| Dependabot security updates | Yes | No | Yes |
| Secret scanning | Auto | No | Yes |
| Push protection | Yes | No | Yes |
| Private vulnerability reporting | Yes | Yes | Yes |
| Dependency graph | Auto | No | Yes |

`gh-safe-repo` 在运行时检测您的计划级别和仓库可见性。不可用的功能在计划输出中显示为 `SKIP`,并附有明确的原因——该工具永远不会静默失败。

---

## 工作原理```
gh-safe-repo create <owner/repo>
      │
      ├─ Parse owner/repo, validate owner matches authenticated user (create only)
      ├─ Load config (./gh-safe-repo.ini or $XDG_CONFIG_HOME/gh-safe-repo/gh-safe-repo.ini)
      ├─ Apply CLI flag overrides (--public, etc.)
      ├─ Authenticate via gh CLI or GITHUB_TOKEN
      ├─ GET /user → owner login + plan level  (single cached call)
      │
      ├─ Build plan (each plugin compares desired vs. current state)
      │   ├─ RepositoryPlugin  → repo creation + basic settings
      │   ├─ ActionsPlugin     → allowed actions, workflow permissions, SHA pinning
      │   ├─ BranchProtectionPlugin → Rulesets API (default; classic if use_rulesets = false)
      │   ├─ SecurityPlugin    → Dependabot, secret scanning, push protection, private vuln reporting
      │   └─ TagProtectionPlugin → immutable tags via Rulesets API
      │
      ├─ Print plan table
      │
      └─ Apply (unless --dry-run)
          ├─ POST /user/repos
          ├─ PATCH /repos/{owner}/{repo}       (settings)
          ├─ PUT  /repos/{owner}/{repo}/actions/permissions/workflow
          ├─ POST/PATCH /repos/{owner}/{repo}/rulesets  (branch protection; default)
          │   or PUT /repos/{owner}/{repo}/branches/main/protection (if use_rulesets = false)
          ├─ PUT  /repos/{owner}/{repo}/vulnerability-alerts
          ├─ PUT  /repos/{owner}/{repo}/automated-security-fixes
          ├─ PUT  /repos/{owner}/{repo}/private-vulnerability-reporting
          ├─ PATCH /repos/{owner}/{repo}  (security_and_analysis: push protection)
          ├─ POST /repos/{owner}/{repo}/rulesets  (tag protection ruleset)
          ├─ git clone --mirror + git push --mirror (if --from)
          └─ git clone <local> + git push --all --tags (if --local, git repo)
              or git init + add -A + commit + push (if --local, plain dir)

插件架构

每一类设置都是一个自包含的插件类 (gh_safe_repo/plugins/)。每个插件:

  1. 从 GitHub API 获取当前状态
  2. 与配置中的期望状态进行比较
  3. 返回一个 Plan(Change 对象列表:ADD / UPDATE / DELETE / SKIP)
  4. 仅应用实际变更——对无操作不发起 API 调用

这意味着审计模式和创建模式使用相同的计划/应用路径。唯一的区别在于,当前状态是从现有仓库获取还是假定为 GitHub 默认值。

身份认证

API 调用按以下顺序解析令牌:

  1. GITHUB_TOKEN 环境变量——允许你在不切换活动 gh 会话的情况下定位特定账户(也是在 CI 中唯一需要的凭据)
  2. gh auth token——由 gh auth login 设置的任何内容
  3. 如果两者都不可用,则报错

令牌作为 GH_TOKEN 传递给子进程 gh api 的子进程环境,并且从不记录。

Git 操作(--local / --from 的推送和克隆)默认使用你自己的 git 凭据——SSH 密钥或凭据助手——而不是 API 令牌。在两者都不可用的环境中(例如只有 GITHUB_TOKEN 的 CI),该工具会回退到通过 HTTPS 推送,并在 URL 中包含令牌;[git_transport] mode 配置设置控制此行为(请参阅配置参考)。包含令牌的 URL 永远不会写入你的仓库 .git/config,并且会从所有输出中移除。

API 方式

所有 GitHub API 调用都通过 subprocess 使用 gh api。这使身份验证完全保留在 gh CLI 中——无需令牌管理代码,无需 OAuth 流程,无需固定 PyGithub 版本。JSON 请求正文通过 --input -(标准输入)传递,而不是 --field 标志。


开发```bash

Clone and set up

git clone https://github.com/your-username/gh-safe-repo cd gh-safe-repo uv sync # creates .venv, installs pytest

Run tests

uv run pytest tests/ -v

Run the tool directly (without installing)

./gh-safe-repo create <owner/repo> --dry-run

Install globally (picks up the current source)

uv tool install .

root@kitploit:~
参见 [`tests/README.md`](https://github.com/ariesq/gh-safe-repo/blob/master/tests/README.md) 了解测试文件描述、模拟约定以及如何添加新测试。

### 项目结构```
gh-safe-repo/
├── gh-safe-repo          # Thin launcher (entry point for direct use)
├── gh_safe_repo/         # Package — see gh_safe_repo/README.md for internals
│   ├── cli.py            # Subparser dispatch (create, fix, scan)
│   ├── commands/         # Subcommand implementations
│   │   ├── _common.py    # Shared helpers, CLIContext, plan formatting
│   │   ├── create.py     # create subcommand
│   │   ├── fix.py        # fix subcommand
│   │   └── scan.py       # scan subcommand
│   └── plugins/          # Settings plugins (one per category)
├── pyproject.toml        # Build config, entry points
├── gh-safe-repo.ini.example  # Fully annotated example config
└── tests/

有关模块映射、插件架构以及添加新设置的指南,请参见gh_safe_repo/README.md。

依赖策略

没有运行时依赖。所有内容均使用 Python 标准库(argparse、configparser、subprocess、json、re)。未经讨论,请勿添加第三方包。

pytest 是唯一的开发依赖,已在 pyproject.toml 中声明为 UV 原生的 [dependency-groups] 条目。


先前工作

在设计过程中,我们研究了以下项目,它们影响了 gh-safe-repo 的架构。这些是不同的工具,具有不同的作用范围和用户模型——有关模式如何适应的详细技术说明,请参见 docs/LEARNINGS.md。

  • github/safe-settings — 一个组织级别的 GitHub 应用程序(Node.js/Probot),可从中央配置强制执行仓库设置。提供了插件架构模式(每个设置类别一个类,fetch → diff → apply)以及 mergeDeep 比较方法的来源。

  • repository-settings/app — 一个更简单的每个仓库变体的 safe-settings,也是 Node.js/Probot。为 Diffable 基础插件模式提供了更清晰的参考。

  • nicholasgasior/gh-repo-settings — 一个用 Go 编写的 CLI 扩展,具有 plan/apply 工作流。是 gh api 子进程包装器模式和 dry-run plan 输出设计的主要灵感来源。

下载工具
选项说明
--public创建为公开仓库(默认:私有)
--local PATH从本地git仓库推送代码到新仓库。先运行预检扫描。与 --from 互斥。
--from OWNER/REPO从现有仓库镜像代码到新仓库。运行预检扫描。与 --local 互斥。
--yes / -y跳过确认提示并立即应用(用于脚本/批处理)
--dry-run打印计划但不做任何更改
--json将计划以JSON格式输出到stdout而不是ANSI表格
--config [PATH]配置文件路径;单独的 --config 仅使用内置默认值
--debug打印每个API调用和响应
选项说明
--yes / -y跳过确认提示并立即应用(用于脚本/批处理)
--dry-run显示设置差异但不应用更改
--json将计划以JSON格式输出到stdout而不是ANSI表格
--config [PATH]配置文件路径;单独的 --config 仅使用内置默认值
--debug打印每个API调用和响应,以及解析后的仓库标识(id, full name, owner type)
UPDATE(黄色)现有设置正在更改(审计模式)
DELETE(红色)正在删除的设置
SKIP(暗色)无需操作——已达到所需值,或您的计划/可见性组合不支持此功能
类别严重级别示例
硬编码密钥严重AWS 密钥(AKIA…)、GitHub 令牌(ghp_…、github_pat_…)、私钥、数据库 URL
禁用字符串严重你配置的任何字面字符串(用户名、内部主机名、项目代号)
AI 上下文文件严重CLAUDE.md、AGENTS.md、.cursorrules、copilot-instructions.md、.cursor/ —— 可能包含内部开发笔记;Git 历史可能比当前版本更敏感
电子邮件地址警告工作树和 Git 历史中任何 [email protected] 模式
大文件警告超过配置大小阈值的文件(默认:100 MB)
TODO/FIXME 注释信息# TODO、# FIXME、# HACK、# XXX