Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
gh-safe-repo — CLI em Python que cria repositórios GitHub com padrões seguros — proteção de branch, Dependabot, varredura de segredos e varredura de segurança pré-execução — aplicados automaticamente. | Kitploit
Ferramentas/GitHubGitHub/ariesq/gh-safe-repo
Utilitários de Propósito GeralScanners de VulnerabilidadesScripting e AutomaçãoAuditoria de ConfiguraçãoSegurança na NuvemDevSecOpsDetecção de Segredos
GitHubariesq/gh-safe-repo

gh-safe-repo

CLI em Python que cria repositórios GitHub com padrões seguros — proteção de branch, Dependabot, varredura de segredos e varredura de segurança pré-execução — aplicados automaticamente.

Ver Repositório
383há 1 diaRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

gh-safe-repo

Crie repositórios GitHub com configurações seguras aplicadas automaticamente. Substitui a lista de verificação de configurações pós-criação de cinco minutos por um único comando.``` gh-safe-repo create <owner/repo>

root@kitploit:~
Proteção de branches, tags imutáveis, Dependabot, permissões restritas do Actions, varredura de segredos com proteção contra push, e wiki e projetos desativados — tudo configurado antes de você escrever sua primeira linha de código.

gh-safe-repo está em desenvolvimento ativo. Funciona bem para o caso de uso de criar um novo repositório com padrões seguros. Estou trabalhando no polimento das opções de CLI para melhor alinhamento com as expectativas dos usuários. Espere mudanças significativas até chegarmos a um ponto em que estarei fazendo releases e tenha CI/CD bem definido. ✌️

---

## Índice

- [Por quê](#por-quê)
- [O que ele altera](#o-que-ele-altera)
- [Requisitos](#requisitos)
- [Instalação](#instalação)
- [Início Rápido](#início-rápido)
- [Referência da CLI](#referência-da-cli)
- [Saída do Dry Run / Plano](#saída-do-dry-run--plano)
- [Modo Correção (Auditar Repositórios Existentes)](#modo-correção-auditar-repositórios-existentes)
- [Espelhando Repositórios (`--from`)](#espelhando-repositórios---from)
- [Criando um Repositório a partir de um Diretório Local (`--local`)](#criando-um-repositório-a-partir-de-um-diretório-local---local)
- [Scanner de Segurança Pré-voo](#scanner-de-segurança-pré-voo)
  - [Escaneamento independente](#escaneamento-independente)
  - [Suprimindo falsos positivos](#suprimindo-falsos-positivos)
- [Configuração](#configuração)
- [Limitações do Plano GitHub](#limitações-do-plano-github)
- [Como Funciona](#como-funciona)
- [Desenvolvimento](#desenvolvimento)

---

## Por quê

As configurações padrão do GitHub são otimizadas para descoberta e flexibilidade, não para segurança. Cada novo repositório vem com:

- Wiki e Projetos ativados (superfície de ataque, mesmo que não utilizados)
- Merge commits permitidos (histórico bagunçado, mas não é a principal preocupação)
- Sem proteção de branch (qualquer pessoa com acesso de escrita pode fazer push diretamente para `main`)
- Sem alertas do Dependabot
- GitHub Actions com permissões de escrita no repositório
- Actions autorizados a aprovar pull requests

Corrigir tudo isso manualmente leva minutos por repositório e é fácil de esquecer. `gh-safe-repo` aplica um conjunto de padrões opinativos, porém práticos, de uma só vez, com uma pré-visualização do plano para que você saiba exatamente o que será alterado antes que qualquer mudança aconteça.

---

## O que ele altera

### Configurações do repositório

| Configuração | Padrão GitHub | Padrão seguro | Observações |
|---|---|---|---|
| Visibilidade | Público | **Privado** | Use `--public` para substituir |
| Wiki | Ativado | **Desativado** | |
| Projetos | Ativado | **Desativado** | |
| Issues | Ativado | Ativado | |
| Excluir branch ao mesclar | Desligado | Desligado | Defina como `true` na configuração para limpeza automática |
| Permitir merge commits | Ativado | Ativado | Defina como `false` na configuração para apenas squash |
| Permitir squash merge | Ativado | Ativado | |
| Permitir rebase merge | Ativado | Ativado | |

### GitHub Actions

| Configuração | Padrão GitHub | Padrão seguro |
|---|---|---|
| Actions permitidas | Todas | **Selecionadas** (GitHub-próprias + criadores verificados; customizável) |
| Permissões padrão do fluxo de trabalho | Leitura/escrita | **Somente leitura** |
| Actions podem aprovar PRs | Sim | **Não** |
| Exigir fixação por SHA | Não | **Sim** (fluxos de trabalho devem fixar ações a um commit SHA, não a uma tag mutável) |
| Política de aprovação de fork PR | Contribuidores de primeira viagem novos no GitHub | **Todos os contribuidores externos** — exigir aprovação antes que forks PR executem CI. Opções: apenas contas novas do GitHub (padrão GitHub), primeiros contribuidores do repositório, ou todos os forks PR (mais seguro) |

### Proteção de branch (repositórios públicos, ou qualquer repositório em plano pago)

| Regra | Valor |
|---|---|
| Exigir pull request antes de mesclar | Sim |
| Revisões de aprovação necessárias | 1 |
| Descartar revisões obsoletas ao fazer push | Sim |
| Exigir resolução de conversas | Sim |
| Permitir force pushes | Não |
| Permitir exclusão de branch | Não |
| Aplicar a administradores | Não (permite que ferramentas do proprietário façam push) |

A proteção de branch é aplicada via **API de Rulesets** por padrão (`use_rulesets = true`): um único ruleset `gh-safe-repo defaults` cobre todas as branches configuradas e expressa "administradores podem contornar" através de um ator de bypass em vez da flag clássica `enforce_admins`. Defina `use_rulesets = false` para o caminho clássico legado por branch (mantido por um ciclo de release).

**Migrando um repositório existente da proteção clássica:** se `fix` encontrar proteção clássica de branch em um repositório, ele se recusa a convertê-la para um ruleset a menos que você passe `--migrate-branch-protection`. Regras exclusivas do clássico não têm equivalente no ruleset que esta ferramenta constrói e seriam descartadas silenciosamente — lacunas conhecidas:

- `required_status_checks` — verificações de CI obrigatórias não são modeladas no corpo do ruleset.
- `restrictions` (restrições de push por usuário/equipe) — Rulesets modelam isso de forma diferente através de atores de bypass; não é um mapeamento 1:1.
- Divergência por branch — um ruleset de condição compartilhada única não pode expressar regras diferentes para `master` vs `main`.

Com a flag, `fix` cria/atualiza o ruleset e então exclui a proteção clássica em cada branch para que as duas camadas não se acumulem.

### Proteção de tags (repositórios públicos, ou qualquer repositório em plano pago)

A proteção de tags cria um GitHub Ruleset direcionado a todas as tags (`*` por padrão, configurável via `protected_tags`). As seguintes regras são aplicadas:

| Regra do ruleset | Aplicada? | Observações |
|---|---|---|
| Restringir criações | Não | |
| **Restringir atualizações** | **Sim** | Impede reescrita / force-push de tags |
| **Restringir exclusões** | **Sim** | Impede `git push --delete` de tags |
| Exigir histórico linear | Não | |
| Exigir que implantações tenham sucesso | Não | |
| Exigir commits assinados | Não | |
| Exigir que verificações de status passem | Não | |
| Bloquear force pushes | Não | |

Os administradores do repositório estão na lista de bypass (consistente com o padrão `enforce_admins = false` da proteção de branch). Só funciona em repositórios públicos ou planos GitHub pagos (mesma restrição da proteção de branch). Repositórios privados de plano gratuito verão isso ignorado na saída do plano.

### Segurança

| Funcionalidade | Comportamento |
|---|---|
| Alertas do Dependabot | Ativado (repositórios públicos / planos pagos) |
| Atualizações de segurança do Dependabot | Ativado (abre PRs automaticamente para dependências vulneráveis) |
| Varredura de segredos | Automática em repositórios públicos; ativada em planos privados pagos |
| Proteção contra push | Ativada (bloqueia commits contendo segredos suportados) |
| Relato privado de vulnerabilidades | Ativado (permite que pesquisadores de segurança relatem privadamente) |
| Gráfico de dependências | Automático em repositórios públicos; sem API REST para privados (apenas interface) |

---

## Requisitos

- Python 3.8+
- [`gh` CLI](https://cli.github.com/) instalada e autenticada (`gh auth login`), **ou** `GITHUB_TOKEN` definido no seu ambiente
- Para `--local` / `--from` (que fazem push ou clonam código): suas credenciais git habituais devem estar configuradas — seja uma chave SSH carregada no `ssh-agent` (quando `gh config get git_protocol` é `ssh`) ou um helper de credenciais HTTPS (`gh auth setup-git` configura um automaticamente). O token OAuth **não** é usado para git push, portanto arquivos de fluxo de trabalho (`.github/workflows/*`) são enviados sem a necessidade do escopo OAuth `workflow`.
- [`uv`](https://docs.astral.sh/uv/) para instalação a partir do código-fonte (recomendado)
- `truffleHog` v3 (opcional — usado pelo scanner pré-voo; detectado automaticamente no PATH, ou executado via podman/docker; recai para regex se nenhum estiver disponível)

---

## Instalação

### A partir do código-fonte com uv (recomendado)```bash
git clone https://github.com/your-username/gh-safe-repo
cd gh-safe-repo
uv tool install .

Isto instala gh-safe-repo no ambiente de ferramentas do uv e o adiciona ao seu PATH.

Executar diretamente sem instalar```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:~
### Verificar```bash
gh-safe-repo --help

Início Rápido```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:~
---

## Referência da CLI```
gh-safe-repo create <owner/repo> [OPTIONS]
gh-safe-repo fix <owner/repo> [OPTIONS]
gh-safe-repo scan <path> [OPTIONS]

Todos os comandos que interagem com o GitHub exigem o formato owner/repo (por exemplo, myuser/my-repo). Para create, o proprietário é validado em relação à sua conta autenticada do GitHub para evitar erros em sistemas com várias contas. Para fix, são necessárias permissões de administrador no repositório alvo, permitindo que você corrija repositórios de propriedade de organizações ou outras contas onde você tem acesso de administrador.

create — Criar um novo repositório

Um create simples (sem --local/--from) inicializa o repositório para que uma branch padrão exista para proteção de branch, depois remove o README.md gerado automaticamente para que o novo repositório comece limpo. Defina auto_init = true na configuração para manter o README. --local/--from enviam seu próprio histórico e nunca criam um README.

fix — Auditar e corrigir um repositório existente

scan — Verificação local de segredos

OpçãoDescrição
--config [PATH]Caminho para o arquivo de configuração; --config simples usa apenas os padrões incorporados
--debugMostra detalhes do scanner

O código de saída é 0 se não houver achados críticos, 1 se forem encontrados críticos.


Saída de Dry Run / Plano

--dry-run mostra exatamente o que gh-safe-repo faria, sem fazer alterações ou chamadas de API. Use antes de executar de verdade. Combine com --json para saída do plano legível por máquina:

---```bash gh-safe-repo create <owner/repo> --dry-run --json gh-safe-repo fix <owner/repo> --dry-run --json

root@kitploit:~
Quando `--json` está ativo, o plano é escrito para stdout como um objeto JSON e todas as outras mensagens (progresso, avisos, o rodapé "Dry run") vão para stderr, para que a saída fique limpa para pipe ou script.```
$ 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.

Cores das ações:

Saída 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` inclui apenas os tipos presentes no plano. Os consumidores devem usar `.get("delete", 0)` etc. em vez de assumir que todas as quatro chaves estão presentes.

---

## Modo de Correção (Auditar Repositórios Existentes)

`fix` compara as configurações atuais de um repositório existente com os padrões seguros e aplica as correções. Nenhuma varredura de segredos — `fix` é puramente sobre configurações de repositório.```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

Modo de correção:

  1. Obtém o valor atual de cada configuração via API do GitHub
  2. Compara com os padrões seguros desejados
  3. Mostra uma tabela de plano com UPDATE para configurações alteradas e SKIP para configurações já no valor desejado (detecção de no-op — nunca faz chamadas de API que não alterariam nada)
  4. Solicita confirmação antes de aplicar (pule com --yes)

Apenas mudanças reais são aplicadas — configurações já no valor desejado são exibidas como SKIP e não geram chamadas de API.


Espelhando Repositórios (--from)

--from espelha um repositório existente em um novo com padrões seguros. Funciona tanto para destinos privados quanto públicos:```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:~
**O que acontece, em ordem:**

1. Suas credenciais git para `github.com` são verificadas de antemão (sonda SSH quando `gh config get git_protocol` é `ssh`; HTTPS é confiável), então uma chave ausente falha rapidamente antes de qualquer repositório ser criado
2. O repositório de origem é clonado localmente (clone completo, sem `--depth`, para que o truffleHog possa percorrer todo o histórico de commits)
3. O [scanner de segurança de pré-voo](#pre-flight-security-scanner) é executado no clone local
4. Você revisa os resultados e confirma (ou aborta)
5. Um novo repositório é criado (privado por padrão, ou público com `--public`)
6. Permissões de Actions e configurações de segurança são aplicadas (Dependabot, varredura de segredos, proteção contra push)
7. O histórico completo é espelhado: `git clone --mirror` + `git push --mirror`
8. A proteção de branches e tags é aplicada (após o push do código, para que o branch de destino exista)

Se a varredura revelar um problema e você abortar, nenhum código é copiado para o GitHub.

> **Nota:** `--from` usa o formato `owner/repo` tanto para a origem quanto para o destino.

---

## Criando um Repositório a partir de um Diretório Local (`--local`)

`--local PATH` é a contraparte local-para-GitHub de `--from`. Ele cria um novo repositório no GitHub e envia código de um repositório git local. `PATH` deve ser um repositório git inicializado (`git init` ou um clone).```bash
gh-safe-repo create <owner/repo> --local ~/projects/myapp
gh-safe-repo create <owner/repo> --local ~/projects/myapp --public

O que acontece, em ordem:

  1. Suas credenciais git para github.com são verificadas de antemão (sonda SSH quando gh config get git_protocol é ssh; HTTPS é confiável), então uma chave ausente falha rapidamente antes de qualquer repositório ser criado
  2. O verificador de segurança pré-voo é executado diretamente no diretório local (nenhum clone necessário)
  3. Você revisa as descobertas e confirma (ou aborta)
  4. Um novo repositório é criado, e as permissões de ações e configurações de segurança são aplicadas
  5. Todo o histórico é enviado com push --all --tags (todos os ramos e tags)
  6. A proteção de ramos e tags é aplicada (após o envio do código, para que o ramo alvo exista)
  7. origin é adicionado ao repositório local original apontando para a nova URL do GitHub, e o rastreamento upstream do ramo atual é configurado — então git push e git pull funcionam imediatamente sem configuração extra.

Ambos --local e --from funcionam para repositórios privados e públicos. Eles são mutuamente exclusivos.

O ramo padrão local (através de git -C PATH symbolic-ref HEAD) é usado para direcionar as regras de proteção de ramo, então a proteção é aplicada no ramo correto mesmo que não seja main.

Dica: Execute gh-safe-repo scan PATH primeiro se quiser inspecionar as descobertas sem criar nada.


Verificador de Segurança Pré-voo

O verificador é executado localmente e nunca envia código para o GitHub. Use-o de forma independente antes de qualquer envio, ou ele é executado automaticamente como parte dos fluxos de trabalho --from e --local.

Varredura autônoma```bash

Scan the current directory

gh-safe-repo scan .

Scan an explicit path

gh-safe-repo scan ~/projects/myapp

root@kitploit:~
Código de saída é `0` se não houver achados críticos, `1` se forem encontrados críticos — então ele se compõe perfeitamente com outros comandos:```bash
gh-safe-repo scan . && git push

The full [pre_flight_scan] config applies: banned_strings, max_file_size_mb, trufflehog_mode, etc.

O que detecta

Mecanismo de varredura

gh-safe-repo automaticamente escolhe o melhor scanner disponível usando uma cadeia de descoberta de três etapas:

  1. truffleHog v3 no PATH — executa trufflehog --version, verifica se é v3 e o utiliza. Uma instalação v2 ou uma versão não reconhecida exibe um aviso e cai para a etapa 2.
  2. podman ou docker — se nenhum truffleHog nativo for encontrado, o scanner executa o truffleHog em um contêiner (ghcr.io/trufflesecurity/trufflehog:latest) usando podman run ou docker run, montando o caminho de varredura como somente leitura no mesmo caminho absoluto para que os caminhos de saída JSON sejam idênticos a uma execução nativa.
  3. Fallback de regex — se nem uma instalação nativa nem um tempo de execução de contêiner estiverem disponíveis, um aviso é exibido e o scanner de regex é executado em vez disso. Ele também sempre é executado em adição ao truffleHog para emails e TODOs, e captura padrões de ID de chave isolados que o truffleHog deliberadamente ignora (o truffleHog requer ambas as metades de um par de credenciais, por exemplo, AWS Key ID e Secret Access Key, antes de sinalizar uma descoberta).

O scanner selecionado é mostrado no cabeçalho "Running pre-flight security scan..." e na entrada SCAN da tabela de plano, por exemplo:``` 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:~
Variáveis de ambiente respeitadas pelo caminho do contêiner: `CONTAINER_RUNTIME` para substituir a seleção do runtime (por exemplo, `CONTAINER_RUNTIME=docker`), e `TRUFFLEHOG_IMAGE` para fixar uma tag de imagem específica.

### Executando truffleHog via podman ou Docker (sem instalação local)

Nenhuma configuração manual é necessária. O `gh-safe-repo` detecta podman ou docker automaticamente (passo 2 acima) e executa truffleHog em um contêiner com os mounts de volume corretos. As variáveis de ambiente `CONTAINER_RUNTIME` e `TRUFFLEHOG_IMAGE` são respeitadas.

Um wrapper de shell (`tools/trufflehog`) e um `Containerfile` para construir uma imagem local fixada são fornecidos em [`tools/`](https://github.com/ariesq/gh-safe-repo/blob/HEAD/tools/README.md) para usuários que desejam o truffleHog baseado em contêiner disponível em todo o sistema, ou que precisam de uma imagem isolada (air-gapped).

### Revisão interativa```
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]:
  • Resultados críticos: O padrão é abortar (N). Você deve digitar explicitamente y para continuar.
  • Apenas avisos: O padrão é continuar (Y). Pressione Enter para prosseguir ou digite n para abortar.
  • Nenhum resultado: A varredura é concluída silenciosamente e o fluxo de trabalho continua.

Segredos são ocultados na saída. Endereços de e-mail e TODOs mostram a linha correspondente.

Cobertura da varredura

Diretórios de artefatos de construção (node_modules, __pycache__, .venv, venv, dist, build) são ignorados por padrão para manter as varreduras rápidas. Em repositórios git, esta omissão é condicional: antes de remover um diretório, o scanner executa git ls-files -- <dir> para verificar se algum arquivo dentro dele é rastreado. Se estiverem, o diretório é varrido normalmente.

Isso significa que árvores node_modules ou dist versionadas — incomuns, mas acontecem — não são perdidas silenciosamente. Diretórios não versionados (o caso normal) continuam a ser ignorados como antes.

Um aviso ainda é exibido quando subdiretórios SKIP_DIRS são encontrados em um repositório fonte clonado, pois sua presença pode indicar que mais conteúdo do que o esperado foi comitado.

Suprimindo falsos positivos

Duas chaves de configuração permitem suprimir resultados conhecidamente seguros sem desabilitar categorias inteiras de verificação.

scan_exclude_paths — ignora arquivos ou diretórios completamente. Os valores são padrões regex separados por nova linha/vírgula que correspondem ao caminho relativo do arquivo. Um arquivo correspondente é excluído de todas as verificações: segredos, e-mails, TODOs, arquivos grandes e detecção de arquivos de contexto de IA. Os mesmos padrões também são passados para o truffleHog via --exclude-paths, para que a cobertura seja consistente independentemente de qual mecanismo de scanner está ativo.```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`** — suprimir achados de e-mail para endereços específicos ou domínios inteiros. Os valores são separados por nova linha/vírgula, insensíveis a maiúsculas/minúsculas. Entradas começando com `@` correspondem a todos os e-mails naquele domínio; caso contrário, a entrada deve corresponder exatamente ao endereço completo. Aplica-se tanto à árvore de trabalho quanto aos achados do histórico do git.```ini
[pre_flight_scan]
# Suppress bot addresses and placeholder domains
exclude_emails = [email protected], [email protected], @example.com

Configuração do Scanner```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:~
Quando strings proibidas ou arquivos de contexto de IA são encontrados, o scanner imprime um comando `git filter-repo` pronto para execução para removê-los do histórico do repositório de origem antes de re-executar.

---

## Configuração

`gh-safe-repo` procura a configuração nesta ordem (a primeira correspondência vence):

1. **`--config PATH`** — substituição explícita
2. **`./gh-safe-repo.ini`** — diretório de trabalho atual
3. **`$XDG_CONFIG_HOME/gh-safe-repo/gh-safe-repo.ini`** — padrão para `~/.config` quando `$XDG_CONFIG_HOME` não está definido

Apenas `--config` (sem caminho) ignora completamente a busca por arquivo e usa apenas os padrões internos.
Todos os valores têm padrões seguros — nenhum arquivo de configuração é necessário para começar.

Um exemplo de configuração totalmente anotado está incluído no repositório como `gh-safe-repo.ini.example`. Copie-o para começar:```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

Referência completa de configuração```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:~
---

## Limitações do Plano GitHub

Alguns recursos estão disponíveis apenas dependendo da visibilidade do repositório e do seu plano GitHub.

| Recurso | Grátis + Público | Grátis + Privado | Pro/Equipe + Privado |
|---|:---:|:---:|:---:|
| Proteção de branch / Regras | Sim | Não | Sim |
| Proteção de tag (Regras) | Sim | Não | Sim |
| Alertas do Dependabot | Sim | Não | Sim |
| Atualizações de segurança do Dependabot | Sim | Não | Sim |
| Varredura de segredos | Automático | Não | Sim |
| Proteção de push | Sim | Não | Sim |
| Relatório privado de vulnerabilidades | Sim | Sim | Sim |
| Gráfico de dependências | Automático | Não | Sim |

O `gh-safe-repo` detecta o nível do seu plano e a visibilidade do repositório em tempo real. Recursos indisponíveis aparecem como `SKIP` na saída do plano com um motivo claro — a ferramenta nunca falha silenciosamente.

---

## Como Funciona```
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)

Arquitetura de plugins

Cada categoria de configurações é uma classe de plugin autocontida (gh_safe_repo/plugins/). Cada plugin:

  1. Obtém o estado atual da API do GitHub
  2. Compara com o estado desejado da configuração
  3. Retorna um Plan (lista de objetos Change: ADD / UPDATE / DELETE / SKIP)
  4. Aplica apenas mudanças reais — sem chamadas de API para operações nulas

Isso significa que o modo de auditoria e o modo de criação usam o mesmo caminho de planejamento/aplicação. A única diferença é se o estado atual é obtido de um repositório existente ou assumido como os padrões do GitHub.

Autenticação

As chamadas de API resolvem um token nesta ordem:

  1. Variável de ambiente GITHUB_TOKEN — permite direcionar uma conta específica sem alternar a sessão ativa do gh (e é a única credencial necessária em CI)
  2. gh auth token — o que o gh auth login configurou
  3. Erro se nenhum estiver disponível

Os tokens são passados para processos filhos gh api como GH_TOKEN no ambiente do subprocesso e nunca são registrados em logs.

As operações Git (--local / --from push e clone) usam suas próprias credenciais Git — chave SSH ou helper de credenciais — por padrão, não o token da API. Em ambientes sem nenhum dos dois (ex.: CI com apenas GITHUB_TOKEN), a ferramenta recorre ao push via HTTPS com o token na URL; a configuração [git_transport] mode controla isso (veja a referência de configuração). URLs com token nunca são escritas no .git/config do seu repositório e são ocultadas de toda saída.

Abordagem da API

Todas as chamadas de API do GitHub passam por gh api via subprocess. Isso mantém a autenticação inteiramente na CLI gh — sem código de gerenciamento de token, sem fluxo OAuth, sem fixação de versão do PyGithub. Corpos de requisição JSON são passados via --input - (stdin), não por flags --field.


Desenvolvimento```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:~
Consulte [`tests/README.md`](https://github.com/ariesq/gh-safe-repo/blob/HEAD/tests/README.md) para descrições de arquivos de teste, convenções de mocking e como adicionar novos testes.

### Estrutura do projeto```
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/

Consulte gh_safe_repo/README.md para o mapa de módulos, arquitetura de plugins e um guia para adicionar novas configurações.

Política de dependências

Não há dependências de tempo de execução. Tudo usa a biblioteca padrão do Python (argparse, configparser, subprocess, json, re). Não adicione pacotes de terceiros sem discussão.

pytest é a única dependência de desenvolvimento, declarada como uma entrada [dependency-groups] nativa do UV em pyproject.toml.


Trabalhos relacionados

Estes projetos foram estudados durante o design e influenciaram a arquitetura do gh-safe-repo. São ferramentas distintas com escopos e modelos de usuário diferentes — consulte docs/LEARNINGS.md para notas técnicas detalhadas sobre como os padrões foram adaptados.

  • github/safe-settings — Aplicativo GitHub de nível organizacional (Node.js/Probot) que aplica configurações de repositório a partir de uma configuração central. Fonte do padrão de arquitetura de plugins (uma classe por categoria de configuração, fetch → diff → apply) e da abordagem de comparação mergeDeep.

  • repository-settings/app — Variante mais simples por repositório do safe-settings, também em Node.js/Probot. Forneceu uma referência mais limpa para o padrão de plugin base Diffable.

  • nicholasgasior/gh-repo-settings — Extensão CLI escrita em Go com um fluxo de trabalho plan/apply. Inspiração principal para o padrão de wrapper de subprocesso gh api e o design de saída do plano de simulação (dry-run).

Baixar ferramenta
OpçãoDescrição
--publicCriar como repositório público (padrão: privado)
--local PATHEnvia código de um repositório git local para o novo repositório. Executa verificação prévia primeiro. Mutuamente exclusivo com --from.
--from OWNER/REPOEspelha código de um repositório existente para o novo repositório. Executa verificação prévia. Mutuamente exclusivo com --local.
--yes / -yPular prompt de confirmação e aplicar imediatamente (para uso em scripts/lotes)
--dry-runExibe o plano sem fazer alterações
--jsonEmite o plano como JSON para stdout em vez da tabela ANSI
--config [PATH]Caminho para o arquivo de configuração; --config simples usa apenas os padrões incorporados
--debugImprime cada chamada de API e resposta
OpçãoDescrição
--yes / -yPular prompt de confirmação e aplicar imediatamente (para uso em scripts/lotes)
--dry-runMostra diff das configurações sem aplicar alterações
--jsonEmite o plano como JSON para stdout em vez da tabela ANSI
--config [PATH]Caminho para o arquivo de configuração; --config simples usa apenas os padrões incorporados
--debugImprime cada chamada de API e resposta, além da identidade do repositório resolvida (id, nome completo, tipo de proprietário)
AçãoSignificado
ADD (verde)Nova configuração sendo aplicada
UPDATE (amarelo)Configuração existente sendo alterada (modo de auditoria)
DELETE (vermelho)Configuração sendo removida
SKIP (acinzentado)Nenhuma ação necessária — já está no valor desejado, ou recurso indisponível na sua combinação de plano/visibilidade
CategoriaSeveridadeExemplos
Segredos codificadosCríticoChaves AWS (AKIA…), tokens GitHub (ghp_…, github_pat_…), chaves privadas, URLs de banco de dados
Strings banidasCríticoQuaisquer strings literais que você configurar (nomes de usuário, nomes de host internos, nomes de código)
Arquivos de contexto de IACríticoCLAUDE.md, AGENTS.md, .cursorrules, copilot-instructions.md, .cursor/ — podem conter notas internas de desenvolvimento; o histórico do git pode ser mais sensível que a versão atual
Endereços de emailAvisoQualquer padrão [email protected] na árvore de trabalho e no histórico do git
Arquivos grandesAvisoArquivos acima do limite de tamanho configurado (padrão: 100 MB)
Comentários TODO/FIXMEInformação# TODO, # FIXME, # HACK, # XXX