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, сканирование секретов с защитой от отправки (push protection), а также отключенные вики и проекты — всё настраивается до того, как вы напишете свою первую строку кода.  

gh-safe-repo находится в стадии активной разработки. Он хорошо работает для сценария создания нового репозитория с безопасными настройками по умолчанию. Я работаю над доработкой опций CLI, чтобы они наилучшим образом соответствовали ожиданиям пользователей. Ожидайте критических изменений, пока мы не достигнем этапа, когда я буду делать релизы и налажу CI/CD. ✌️

---

## Содержание

- [Зачем](#why)
- [Что меняется](#what-it-changes)
- [Требования](#requirements)
- [Установка](#installation)
- [Быстрый старт](#quick-start)
- [Справочник по CLI](#cli-reference)
- [Пробный запуск / Вывод плана](#dry-run--plan-output)
- [Режим исправления (аудит существующих репозиториев)](#fix-mode-audit-existing-repos)
- [Зеркалирование репозиториев (`--from`)](#mirroring-repos---from)
- [Создание репозитория из локальной директории (`--local`)](#creating-a-repo-from-a-local-directory---local)
- [Предварительный сканер безопасности](#pre-flight-security-scanner)
  - [Автономное сканирование](#standalone-scan)
  - [Подавление ложных срабатываний](#suppressing-false-positives)
- [Конфигурация](#configuration)
- [Ограничения планов GitHub](#github-plan-limitations)
- [Как это работает](#how-it-works)
- [Разработка](#development)

---

## Зачем

Стандартные настройки репозитория GitHub оптимизированы для обнаружения и гибкости, а не для безопасности. Каждый новый репозиторий поставляется с:

- Включенные вики и проекты (поверхность атаки, даже если не используются)
- Разрешены коммиты слияния (беспорядочная история, но это не главная проблема)
- Отсутствует защита веток (любой с правами записи может отправлять напрямую в `main`)
- Отсутствуют уведомления Dependabot
- GitHub Actions с правами записи в репозиторий
- Actions разрешены для одобрения pull request'ов

Исправление всего этого вручную занимает минуты на репозиторий и легко забывается. `gh-safe-repo` применяет субъективный, но практичный набор настроек по умолчанию одним выстрелом, с предварительным просмотром плана, чтобы вы точно знали, что изменится до того, как что-либо изменится.

---

## Что меняется

### Настройки репозитория

| Настройка | По умолчанию GitHub | Безопасное значение | Примечания |
|---|---|---|---|
| Видимость | Публичный | **Приватный** | Передайте `--public`, чтобы переопределить |
| Вики | Включено | **Отключено** | |
| Проекты | Включено | **Отключено** | |
| Issues | Включено | Включено | |
| Удалять ветку при слиянии | Выкл | Выкл | Установите `true` в конфиге для автоочистки |
| Разрешить коммиты слияния | Вкл | Вкл | Установите `false` в конфиге только для squash |
| Разрешить squash-слияние | Вкл | Вкл | |
| Разрешить rebase-слияние | Вкл | Вкл | |

### GitHub Actions

| Настройка | По умолчанию GitHub | Безопасное значение |
|---|---|---|
| Разрешённые actions | Все | **Выбранные** (принадлежащие GitHub + проверенные создатели; настраивается) |
| Разрешения рабочего процесса по умолчанию | Чтение/запись | **Только чтение** |
| Actions могут одобрять PR | Да | **Нет** |
| Требовать SHA-привязку | Нет | **Да** (рабочие процессы должны привязывать actions к SHA коммита, а не к изменяемому тегу) |
| Политика одобрения fork PR | Только новые участники на GitHub | **Все внешние участники** — требуется одобрение перед запуском CI для рабочих процессов fork PR. Варианты: только новые учётные записи GitHub (по умолчанию GitHub), участники впервые в репозитории, или все fork PR (самый безопасный) |

### Защита веток (публичные репозитории или любой репозиторий на платном тарифе)

| Правило | Значение |
|---|---|
| Требовать pull request перед слиянием | Да |
| Требуемое количество одобряющих рецензий | 1 |
| Отклонять устаревшие рецензии при push | Да |
| Требовать разрешения обсуждения | Да |
| Разрешить принудительные push | Нет |
| Разрешить удаление ветки | Нет |
| Применять к администраторам | Нет (позволяет инструментам владельца делать push) |

Защита веток применяется через **Rulesets API** по умолчанию (`use_rulesets = true`): единый ruleset `gh-safe-repo defaults` охватывает каждую настроенную ветку и выражает «администраторы могут обойти» через bypass actor, а не через классический флаг `enforce_admins`. Установите `use_rulesets = false` для устаревшего классического пути для каждой ветки (сохраняется на один цикл релиза).

**Миграция существующего репозитория с классической защиты:** если `fix` находит классическую защиту веток в репозитории, он отказывается преобразовывать её в ruleset, если вы не передадите `--migrate-branch-protection`. Правила, доступные только в классике, не имеют эквивалента в ruleset, который строит этот инструмент, и будут молча отброшены — известные пробелы:

- `required_status_checks` — требуемые проверки CI не моделируются в теле ruleset.
- `restrictions` (ограничения push по пользователю/команде) — Rulesets моделируют это иначе через bypass actors; соответствие не 1:1.
- Различия между ветками — единый ruleset с общим условием не может выражать разные правила для `master` и `main`.

С этим флагом `fix` создаёт/обновляет ruleset, а затем удаляет классическую защиту на каждой ветке, чтобы два слоя не накладывались.

### Защита тегов (публичные репозитории или любой репозиторий на платном тарифе)

Защита тегов создает GitHub Ruleset, нацеленный на все теги (`*` по умолчанию, настраивается через `protected_tags`). Применяются следующие правила:

| Правило ruleset | Применяется? | Примечания |
|---|---|---|
| Ограничить создание | Нет | |
| **Ограничить обновление** | **Да** | Предотвращает перезапись / принудительный push тегов |
| **Ограничить удаление** | **Да** | Предотвращает `git push --delete` тегов |
| Требовать линейную историю | Нет | |
| Требовать успешных развертываний | Нет | |
| Требовать подписанные коммиты | Нет | |
| Требовать прохождения проверок статуса | Нет | |
| Блокировать принудительные push | Нет | |

Администраторы репозитория находятся в списке обхода (согласуется с настройкой по умолчанию защиты веток `enforce_admins = false`). Работает только на публичных репозиториях или платных планах GitHub (то же ограничение, что и для защиты веток). В приватных репозиториях бесплатного плана это будет пропущено в выводе плана.

### Безопасность

| Функция | Поведение |
|---|---|
| Уведомления Dependabot | Включено (публичные репозитории / платные планы) |
| Обновления безопасности Dependabot | Включено (автоматически открывает PR для уязвимых зависимостей) |
| Сканирование секретов | Автоматически на публичных репозиториях; включено на приватных платных планах |
| Защита от отправки (push protection) | Включено (блокирует коммиты, содержащие поддерживаемые секреты) |
| Приватное сообщение об уязвимостях | Включено (позволяет исследователям безопасности сообщать приватно) |
| Граф зависимостей | Автоматически на публичных репозиториях; нет REST API для приватных (только UI) |

---

## Требования

- Python 3.8+
- `gh` CLI установлен и аутентифицирован (`gh auth login`), **или** `GITHUB_TOKEN` установлен в вашем окружении
- Для `--local` / `--from` (которые отправляют или клонируют код): ваши обычные учётные данные git должны быть настроены — либо SSH-ключ, загруженный в `ssh-agent` (когда `gh config get git_protocol` равен `ssh`), либо помощник с HTTPS-учётными данными (`gh auth setup-git` настраивает такой автоматически). Токен OAuth **не** используется для git push, поэтому файлы рабочих процессов (`.github/workflows/*`) отправляются без необходимости области OAuth `workflow`.
- `uv` для установки из исходников (рекомендуется)
- `truffleHog` v3 (опционально — используется предварительным сканером; автоматически определяется из PATH или запускается через podman/docker; переходит к regex, если ни то, ни другое недоступно)

---

## Установка

### Из исходников с помощью 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 — Создание нового репозитория

ПараметрОписание
--publicСоздать как публичный репозиторий (по умолчанию: приватный)
--local PATHОтправить код из локального git-репозитория в новый репозиторий. Сначала выполняется предварительная проверка. Взаимоисключающий с --from.
--from OWNER/REPOСкопировать код из существующего репозитория в новый. Выполняется предварительная проверка. Взаимоисключающий с --local.
--yes / -yПропустить подтверждение и применить немедленно (для использования в скриптах/пакетной обработке)
--dry-runПоказать план без внесения изменений
--jsonВывести план в формате JSON в stdout вместо таблицы ANSI
--config [PATH]Путь к файлу конфигурации; пустой --config использует только встроенные настройки по умолчанию
--debugВыводить каждый API-вызов и ответ

Простой create (без --local/--from) инициализирует репозиторий, чтобы существовала ветка по умолчанию для защиты веток, а затем удаляет автоматически сгенерированный README.md, чтобы новый репозиторий начинался чистым. Установите auto_init = true в конфигурации, чтобы сохранить README. --local/--from отправляют вашу собственную историю и никогда не создают README.

fix — Аудит и исправление существующего репозитория

ПараметрОписание
--yes / -yПропустить подтверждение и применить немедленно (для использования в скриптах/пакетной обработке)
--dry-runПоказать разницу настроек без применения изменений
--jsonВывести план в формате JSON в stdout вместо таблицы ANSI
--config [PATH]Путь к файлу конфигурации; пустой --config использует только встроенные настройки по умолчанию
--debugВыводить каждый API-вызов и ответ, а также разрешённую идентификацию репозитория (id, полное имя, тип владельца)

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` активен, план записывается в stdout как JSON-объект, а все остальные сообщения (прогресс, предупреждения, нижний колонтитул "Dry run") направляются в 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 (зелёный)Применяется новый параметр
UPDATE (жёлтый)Изменение существующего параметра (режим аудита)
DELETE (красный)Параметр удаляется
SKIP (тусклый)Действие не требуется — уже установлено нужное значение, или функция недоступна в вашей комбинации тарифа/видимости

Вывод 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. Ваши git-учётные данные для `github.com` проверяются заранее (SSP-зонд, если `gh config get git_protocol` — `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 и отправляет код из локального 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. Ваши учетные данные git для github.com проверяются заранее (SSH-зонд, когда gh config get git_protocol равно ssh; HTTPS считается доверенным), поэтому отсутствующий ключ быстро приводит к ошибке до создания любого репозитория
  2. Предварительный сканер безопасности запускается непосредственно в локальной директории (клонирование не требуется)
  3. Вы просматриваете результаты и подтверждаете (или отменяете)
  4. Создается новый репозиторий, и применяются разрешения действий и настройки безопасности
  5. Полная история отправляется с помощью push --all --tags (все ветки и теги)
  6. Применяется защита веток и тегов (после отправки кода, чтобы целевая ветка существовала)
  7. origin добавляется в исходный локальный репозиторий, указывая на новый URL GitHub, и настраивается отслеживание текущей ветки вверх по потоку — так что 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:~
Код завершения `0`, если критических находок нет, `1`, если критические найдены — так что он хорошо компонуется с другими командами:```bash
gh-safe-repo scan . && git push

Полная конфигурация [pre_flight_scan] применяется: banned_strings, max_file_size_mb, trufflehog_mode и т.д.

Что обнаруживает

КатегорияСерьёзностьПримеры
Жёстко закодированные секретыКритическийAWS keys (AKIA…), GitHub tokens (ghp_…, github_pat_…), закрытые ключи, URL баз данных
Запрещённые строкиКритическийЛюбые литеральные строки, которые вы настраиваете (имена пользователей, внутренние имена хостов, кодовые имена)
Файлы контекста ИИКритическийCLAUDE.md, AGENTS.md, .cursorrules, copilot-instructions.md, .cursor/ — могут содержать внутренние заметки разработчиков; история git может быть более чувствительной, чем текущая версия
Адреса электронной почтыПредупреждениеЛюбой шаблон [email protected] в рабочем дереве и истории git
Большие файлыПредупреждениеФайлы, превышающие заданный порог размера (по умолчанию: 100 МБ)
Комментарии TODO/FIXMEИнформация# TODO, # FIXME, # HACK, # XXX

Механизм сканирования

gh-safe-repo автоматически выбирает лучший доступный сканер, используя трёхэтапную цепочку обнаружения:

  1. truffleHog v3 на PATH — выполняет trufflehog --version, проверяет, что это v3, и использует его. Установка v2 или нераспознанная версия выводят предупреждение и переходят к шагу 2.
  2. podman или docker — если нативный truffleHog не найден, сканер запускает truffleHog в контейнере (ghcr.io/trufflesecurity/trufflehog:latest) с помощью podman run или docker run, монтируя путь сканирования только для чтения по тому же абсолютному пути, чтобы пути JSON-вывода были идентичны нативному запуску.
  3. Регулярное выражение (запасной вариант) — если ни нативная установка, ни среда выполнения контейнера недоступны, выводится предупреждение и запускается сканер на основе регулярных выражений. Он также всегда запускается в дополнение к truffleHog для почтовых адресов и TODO, и перехватывает одиночные шаблоны идентификаторов ключей, которые truffleHog намеренно пропускает (truffleHog требует обе половины пары учётных данных, например, идентификатор ключа AWS и секретный ключ доступа, прежде чем пометить находку).

Выбранный сканер отображается в заголовке "Running pre-flight security scan..." и в записи 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` для закрепления конкретного тега образа.

### Запуск truffleHog через podman или Docker (без локальной установки)

Ручная настройка не требуется. `gh-safe-repo` автоматически определяет podman или docker (шаг 2 выше) и запускает truffleHog в контейнере с правильными монтированиями томов. Учитываются переменные окружения `CONTAINER_RUNTIME` и `TRUFFLEHOG_IMAGE`.

Оболочка-обертка (`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). Нажмите Enter, чтобы продолжить, или введите n, чтобы прервать.
  • Находок нет: Сканирование завершается без вывода, и рабочий процесс продолжается.

Секреты скрыты в выводе. Адреса электронной почты и TODO показывают соответствующую строку.

Охват сканирования

Директории с артефактами сборки (node_modules, __pycache__, .venv, venv, dist, build) по умолчанию пропускаются для ускорения сканирования. В git-репозиториях этот пропуск является условным: перед удалением директории из сканирования сканер выполняет git ls-files -- <dir>, чтобы проверить, отслеживаются ли какие-либо файлы внутри. Если да, директория сканируется обычным образом.

Это означает, что зафиксированные в репозитории деревья node_modules или dist — необычно, но бывает — не пропускаются незаметно. Незафиксированные директории (обычный случай) по-прежнему пропускаются, как и раньше.

Предупреждение всё равно выводится, когда поддиректории SKIP_DIRS найдены в клонированном исходном репозитории, поскольку их наличие может указывать на то, что было зафиксировано больше контента, чем ожидалось.

Подавление ложных срабатываний

Два ключа конфигурации позволяют подавлять известные безопасные находки без отключения целых категорий проверок.

scan_exclude_paths — полностью пропускать файлы или директории. Значения — разделённые новой строкой или запятой regex-шаблоны, сопоставляемые с относительным путём файла. Соответствующий файл исключается из всех проверок: секреты, email-адреса, TODO, большие файлы и обнаружение файлов контекста ИИ. Те же шаблоны также передаются truffleHog через --exclude-paths, поэтому охват остаётся согласованным независимо от того, какой движок сканирования активен.```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`** — подавлять результаты поиска email для конкретных адресов или целых доменов. Значения разделяются новой строкой или запятой, регистронезависимые. Записи, начинающиеся с `@`, соответствуют всем email в этом домене; в противном случае запись должна точно совпадать с полным адресом. Применяется как к результатам в рабочем дереве, так и к истории 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:~
Когда найдены запрещенные строки или файлы контекста ИИ, сканер выводит готовую к запуску команду `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`** — по умолчанию `~/.config`, если `$XDG_CONFIG_HOME` не задан

Голый `--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.

| Функция | Бесплатный + Общедоступный | Бесплатный + Частный | Pro/Team + Частный |
|---|:---:|:---:|:---:|
| Защита веток / Наборы правил | Да | Нет | Да |
| Защита тегов (Наборы правил) | Да | Нет | Да |
| Оповещения Dependabot | Да | Нет | Да |
| Обновления безопасности Dependabot | Да | Нет | Да |
| Сканирование секретов | Авто | Нет | Да |
| Защита при отправке | Да | Нет | Да |
| Приватное сообщение об уязвимостях | Да | Да | Да |
| Граф зависимостей | Авто | Нет | Да |

`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 api как GH_TOKEN в окружении подпроцесса и никогда не логируются.

Git-операции (--local / --from push и clone) по умолчанию используют ваши собственные учётные данные git — SSH-ключ или помощник ввода учётных данных, а не токен API. В средах, где нет ни того, ни другого (например, CI только с GITHUB_TOKEN), инструмент понижает уровень до отправки по HTTPS с токеном в URL; настройка конфига [git_transport] mode управляет этим (см. справочник по конфигурации). URL-адреса, содержащие токен, никогда не записываются в .git/config вашего репозитория и скрыты из всего вывода.

Подход к API

Все вызовы GitHub API выполняются через gh api с помощью subprocess. Это полностью выносит аутентификацию в gh CLI — никакого кода управления токенами, OAuth-потока, привязки к версии PyGithub. Тела JSON-запросов передаются через --input - (stdin), а не через флаги --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 — единственная зависимость для разработки, объявленная как UV-native запись [dependency-groups] в pyproject.toml.


Предшествующие проекты

Эти проекты были изучены при проектировании и повлияли на архитектуру 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 — Расширение для CLI, написанное на Go с рабочим процессом plan/apply. Основное вдохновение для паттерна обёртки подпроцесса gh api и дизайна вывода плана в режиме пробного запуска.

Скачать инструмент