Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
gh-safe-repo — CLI de Python que crea repositorios de GitHub con valores predeterminados seguros: protección de ramas, Dependabot, escaneo de secretos y escaneo de seguridad previo al vuelo, aplicados automáticamente. | Kitploit
Herramientas/GitHubGitHub/ariesq/gh-safe-repo
Utilidades de Propósito GeneralEscáneres de VulnerabilidadesScripting y AutomatizaciónAuditoría de ConfiguraciónSeguridad en la NubeDevSecOpsDetección de Secretos
GitHubariesq/gh-safe-repo

gh-safe-repo

CLI de Python que crea repositorios de GitHub con valores predeterminados seguros: protección de ramas, Dependabot, escaneo de secretos y escaneo de seguridad previo al vuelo, aplicados automáticamente.

Ver Repositorio
383hace 13h 28mRevisado por Kitploit

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

gh-safe-repo

Crea repositorios de GitHub con configuraciones seguras aplicadas automáticamente. Reemplaza la lista de verificación de configuración posterior a la creación de cinco minutos con un solo comando.``` gh-safe-repo create <owner/repo>

root@kitploit:~
Protección de ramas, etiquetas inmutables, Dependabot, permisos restringidos de Actions, escaneo de secretos con protección contra push, y wiki y proyectos deshabilitados — todo configurado antes de escribir tu primera línea de código.  

gh-safe-repo está en pleno desarrollo. Funciona bien para el caso de uso de crear un nuevo repositorio con valores seguros predeterminados. Estoy trabajando en pulir las opciones de CLI para alinearlas mejor con las expectativas de los usuarios. Espera cambios importantes hasta que lleguemos a un punto en el que publique versiones y tenga CI/CD bien definido. ✌️

---

## Tabla de Contenidos

- [Por qué](#por-qué)
- [Qué cambia](#qué-cambia)
- [Requisitos](#requisitos)
- [Instalación](#instalación)
- [Inicio rápido](#inicio-rápido)
- [Referencia de CLI](#referencia-de-cli)
- [Ejecución en seco / Salida del plan](#ejecución-en-seco--salida-del-plan)
- [Modo de corrección (auditar repositorios existentes)](#modo-de-corrección-auditar-repositorios-existentes)
- [Clonar repositorios (`--from`)](#clonar-repositorios---from)
- [Crear un repositorio desde un directorio local (`--local`)](#crear-un-repositorio-desde-un-directorio-local---local)
- [Escáner de seguridad prevuelo](#escáner-de-seguridad-prevuelo)
  - [Escaneo independiente](#escaneo-independiente)
  - [Suprimir falsos positivos](#suprimir-falsos-positivos)
- [Configuración](#configuración)
- [Limitaciones del plan de GitHub](#limitaciones-del-plan-de-github)
- [Cómo funciona](#cómo-funciona)
- [Desarrollo](#desarrollo)

---

## Por qué

La configuración predeterminada de los repositorios de GitHub está optimizada para la detectabilidad y la flexibilidad, no para la seguridad. Cada repositorio nuevo viene con:

- Wiki y Proyectos habilitados (superficie de ataque, incluso si no se usan)
- Confirmaciones de fusión permitidas (historial desordenado, pero no es la preocupación principal)
- Sin protección de ramas (cualquiera con acceso de escritura puede hacer push directamente a `main`)
- Sin alertas de Dependabot
- GitHub Actions con permisos de escritura en el repositorio
- Actions que pueden aprobar solicitudes de extracción

Arreglar todo esto manualmente toma minutos por repositorio y es fácil de olvidar. `gh-safe-repo` aplica un conjunto de valores predeterminados prácticos y opinados de una sola vez, con una vista previa del plan para que sepas exactamente qué cambiará antes de que ocurra.

---

## Qué cambia

### Configuración del repositorio

| Configuración | Predeterminado de GitHub | Predeterminado seguro | Notas |
|---|---|---|---|
| Visibilidad | Público | **Privado** | Usa `--public` para anular |
| Wiki | Habilitado | **Deshabilitado** | |
| Proyectos | Habilitado | **Deshabilitado** | |
| Issues | Habilitado | Habilitado | |
| Eliminar rama al fusionar | Desactivado | Desactivado | Configurar a `true` en la configuración para limpieza automática |
| Permitir confirmaciones de fusión | Activado | Activado | Configurar a `false` en la configuración para solo squash |
| Permitir squash merge | Activado | Activado | |
| Permitir rebase merge | Activado | Activado | |

### GitHub Actions

| Configuración | Predeterminado de GitHub | Predeterminado seguro |
|---|---|---|
| Actions permitidas | Todas | **Seleccionadas** (propiedad de GitHub + creadores verificados; personalizable) |
| Permisos de flujo de trabajo predeterminados | Lectura/escritura | **Solo lectura** |
| Actions pueden aprobar PRs | Sí | **No** |
| Exigir anclaje SHA | No | **Sí** (los flujos de trabajo deben anclar acciones a un SHA de confirmación, no a una etiqueta mutable) |
| Política de aprobación de PRs de bifurcación | Nuevos contribuyentes, nuevos en GitHub | **Todos los contribuyentes externos** — requiere aprobación antes de que los flujos de trabajo de PRs bifurcadas ejecuten CI. Opciones: solo cuentas nuevas de GitHub (predeterminado de GitHub), primeros contribuyentes del repositorio, o todos los PRs bifurcados (más seguro) |

### Protección de ramas (repositorios públicos, o cualquier repositorio en un plan de pago)

| Regla | Valor |
|---|---|
| Requerir solicitud de extracción antes de fusionar | Sí |
| Revisiones de aprobación requeridas | 1 |
| Descartar revisiones obsoletas al hacer push | Sí |
| Requerir resolución de conversación | Sí |
| Permitir forzar push | No |
| Permitir eliminación de rama | No |
| Aplicar a administradores | No (permite que las herramientas del propietario hagan push) |

La protección de ramas se aplica mediante la **API de Rulesets** por defecto (`use_rulesets = true`): un único conjunto de reglas `gh-safe-repo defaults` cubre cada rama configurada y expresa "los administradores pueden omitir" a través de un actor de omisión en lugar de la bandera clásica `enforce_admins`. Configura `use_rulesets = false` para la ruta clásica por rama (mantenida por un ciclo de lanzamiento).

**Migrar un repositorio existente desde protección clásica:** si `fix` encuentra protección de rama clásica en un repositorio, se niega a convertirla en un conjunto de reglas a menos que pases `--migrate-branch-protection`. Las reglas solo clásicas no tienen equivalente en el conjunto de reglas que esta herramienta construye y se eliminarían silenciosamente de lo contrario — brechas conocidas:

- `required_status_checks` — las comprobaciones de CI requeridas no se modelan en el cuerpo del ruleset.
- `restrictions` (restricciones de push por usuario/equipo) — Rulesets modela esto de manera diferente mediante actores de omisión; no es un mapeo 1:1.
- Divergencia por rama — un ruleset de condición compartida única no puede expresar reglas diferentes para `master` vs `main`.

Con la bandera, `fix` crea/actualiza el ruleset y luego elimina la protección clásica en cada rama para que las dos capas no se acumulen.

### Protección de etiquetas (repositorios públicos, o cualquier repositorio en un plan de pago)

La protección de etiquetas crea un Ruleset de GitHub dirigido a todas las etiquetas (`*` por defecto, configurable mediante `protected_tags`). Se aplican las siguientes reglas:

| Regla del ruleset | ¿Aplicada? | Notas |
|---|---|---|
| Restringir creaciones | No | |
| **Restringir actualizaciones** | **Sí** | Evita sobrescribir / forzar push de etiquetas |
| **Restringir eliminaciones** | **Sí** | Evita `git push --delete` de etiquetas |
| Requerir historial lineal | No | |
| Requerir que los despliegues tengan éxito | No | |
| Requerir confirmaciones firmadas | No | |
| Requerir que las comprobaciones de estado pasen | No | |
| Bloquear forzar push | No | |

Los administradores del repositorio están en la lista de omisión (consistente con el valor predeterminado `enforce_admins = false` de la protección de rama). Solo funciona en repositorios públicos o planes de pago de GitHub (misma restricción que la protección de rama). Los repositorios privados de plan gratuito verán esto omitido en la salida del plan.

### Seguridad

| Característica | Comportamiento |
|---|---|
| Alertas de Dependabot | Habilitado (repositorios públicos / planes de pago) |
| Actualizaciones de seguridad de Dependabot | Habilitado (abre automáticamente PRs para dependencias vulnerables) |
| Escaneo de secretos | Automático en repositorios públicos; habilitado en planes privados de pago |
| Protección contra push | Habilitado (bloquea confirmaciones que contengan secretos compatibles) |
| Informe de vulnerabilidad privado | Habilitado (permite que investigadores de seguridad informen de forma privada) |
| Gráfico de dependencias | Automático en repositorios públicos; sin API REST para privados (solo interfaz) |

---

## Requisitos

- Python 3.8+
- [`gh` CLI](https://cli.github.com/) instalada y autenticada (`gh auth login`), **o** `GITHUB_TOKEN` configurada en tu entorno
- Para `--local` / `--from` (que hacen push o clonan código): tus credenciales git habituales deben estar configuradas — ya sea una clave SSH cargada en `ssh-agent` (cuando `gh config get git_protocol` es `ssh`) o un helper de credenciales HTTPS (`gh auth setup-git` configura uno automáticamente). El token OAuth **no** se usa para git push, por lo que los archivos de flujo de trabajo (`.github/workflows/*`) se envían sin necesidad del alcance `workflow` de OAuth.
- [`uv`](https://docs.astral.sh/uv/) para instalación desde fuente (recomendado)
- `truffleHog` v3 (opcional — usado por el escáner prevuelo; se detecta automáticamente desde PATH, o se ejecuta mediante podman/docker; recurre a regex si ninguno está disponible)

---

## Instalación

### Desde fuente con uv (recomendado)```bash
git clone https://github.com/your-username/gh-safe-repo
cd gh-safe-repo
uv tool install .

Esto instala gh-safe-repo en el entorno de herramientas de uv y lo agrega a tu PATH.

Ejecutar directamente sin 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

Inicio 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:~
## Referencia de CLI```
gh-safe-repo create <owner/repo> [OPTIONS]
gh-safe-repo fix <owner/repo> [OPTIONS]
gh-safe-repo scan <path> [OPTIONS]

Todos los comandos que interactúan con GitHub requieren el formato owner/repo (por ejemplo, myuser/my-repo). Para create, el propietario se valida contra tu cuenta autenticada de GitHub para evitar errores en sistemas con múltiples cuentas. Para fix, se requieren permisos de administrador en el repositorio objetivo, lo que te permite arreglar repositorios propiedad de organizaciones u otras cuentas donde tengas acceso de administrador.

create — Crear un nuevo repositorio

Un create simple (sin --local/--from) inicializa el repositorio para que exista una rama predeterminada para la protección de ramas, luego elimina el README.md generado automáticamente para que el nuevo repositorio comience limpio. Establece auto_init = true en la configuración para conservar el README en su lugar. --local/--from envían tu propio historial y nunca crean un README.

fix — Auditar y corregir un repositorio existente

scan — Escaneo local de secretos

OptionDescription
--config [PATH]Ruta al archivo de configuración; --config sin argumentos usa solo los valores predeterminados integrados
--debugMuestra los detalles del escáner

El código de salida es 0 si no se encuentran hallazgos críticos, 1 si se encuentran críticos.


Ejecución en seco / Salida del plan

--dry-run muestra exactamente lo que gh-safe-repo haría, sin realizar ningún cambio ni llamadas a la API. Úsalo antes de ejecutar realmente. Combínalo con --json para obtener una salida del plan legible por máquina:```bash gh-safe-repo create <owner/repo> --dry-run --json gh-safe-repo fix <owner/repo> --dry-run --json

root@kitploit:~
Cuando `--json` está activo, el plan se escribe en stdout como un objeto JSON y todos los demás mensajes (progreso, advertencias, el pie de página "Dry run") van a stderr, para que la salida esté limpia para tuberías o scripts.```
$ 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.

Colores de las acciones:

Salida 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` solo incluye los tipos que están presentes en el plan. Los consumidores deben usar `.get("delete", 0)` etc. en lugar de asumir que las cuatro claves están presentes.

---

## Modo de Corrección (Auditar Repositorios Existentes)

`fix` compara los ajustes actuales de un repositorio existente con los valores predeterminados seguros y aplica las correcciones necesarias. Sin escaneo de secretos — `fix` se ocupa únicamente de los ajustes del repositorio.```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 corrección:

  1. Obtiene el valor actual de cada ajuste a través de la API de GitHub
  2. Compara con los valores seguros predeterminados deseados
  3. Muestra una tabla de planificación con UPDATE para ajustes modificados y SKIP para ajustes que ya tienen el valor deseado (detección sin operación — nunca realiza llamadas a la API que no cambiarían nada)
  4. Solicita confirmación antes de aplicar (se omite con --yes)

Solo se aplican cambios reales — los ajustes que ya tienen el valor deseado se muestran como SKIP y no generan llamadas a la API.


Repositorios espejo (--from)

--from crea un espejo de un repositorio existente en uno nuevo con valores seguros predeterminados. Funciona tanto para destinos privados como 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:~
**Lo que sucede, en orden:**

1. Tus credenciales de git para `github.com` se verifican de antemano (sonda SSH cuando `gh config get git_protocol` es `ssh`; HTTPS es confiable), por lo que una clave faltante falla rápidamente antes de que se cree cualquier repositorio
2. El repositorio fuente se clona localmente (clon completo, sin `--depth`, para que truffleHog pueda recorrer todo el historial de confirmaciones)
3. El [escáner de seguridad previo al vuelo](#pre-flight-security-scanner) se ejecuta en el clon local
4. Revisas los hallazgos y confirmas (o cancelas)
5. Se crea un nuevo repositorio (privado por defecto, o público con `--public`)
6. Se aplican permisos de Actions y configuraciones de seguridad (Dependabot, escaneo de secretos, protección de push)
7. El historial completo se refleja: `git clone --mirror` + `git push --mirror`
8. Se aplica protección de ramas y etiquetas (después del push de código, para que la rama de destino exista)

Si el escáner revela un problema y cancelas, nunca se copia código a GitHub.

> **Nota:** `--from` usa el formato `owner/repo` tanto para el origen como para el destino.

---

## Crear un Repositorio desde un Directorio Local (`--local`)

`--local PATH` es la contraparte local a GitHub de `--from`. Crea un nuevo repositorio de GitHub y envía código desde un repositorio git local. `PATH` debe ser un repositorio git inicializado (`git init` o un clon).```bash
gh-safe-repo create <owner/repo> --local ~/projects/myapp
gh-safe-repo create <owner/repo> --local ~/projects/myapp --public

Qué sucede, en orden:

  1. Tus credenciales de git para github.com se verifican de antemano (sondeo SSH cuando gh config get git_protocol es ssh; HTTPS es confiable), por lo que una clave faltante falla rápidamente antes de que se cree cualquier repositorio.
  2. El escáner de seguridad prevuelo se ejecuta directamente en el directorio local (no se necesita clonar)
  3. Revisas los hallazgos y confirmas (o abortas)
  4. Se crea un nuevo repositorio y se aplican los permisos de acciones y la configuración de seguridad
  5. El historial completo se sube con push --all --tags (todas las ramas y etiquetas)
  6. Se aplica la protección de ramas y etiquetas (después de subir el código, para que la rama objetivo exista)
  7. Se añade origin al repositorio local original apuntando a la nueva URL de GitHub, y se configura el seguimiento ascendente de la rama actual — así que git push y git pull funcionan inmediatamente sin configuración adicional.

Tanto --local como --from funcionan para repositorios privados y públicos. Son mutuamente excluyentes.

La rama predeterminada local (a través de git -C PATH symbolic-ref HEAD) se usa para dirigir las reglas de protección de ramas, de modo que la protección se aplique en la rama correcta incluso si no es main.

Consejo: Ejecuta gh-safe-repo scan PATH primero si quieres inspeccionar los hallazgos sin crear nada.


Escáner de seguridad prevuelo

El escáner se ejecuta localmente y nunca envía código a GitHub. Úsalo de forma independiente antes de cualquier push, o se ejecuta automáticamente como parte de los flujos de trabajo --from y --local.

Escaneo independiente```bash

Scan the current directory

gh-safe-repo scan .

Scan an explicit path

gh-safe-repo scan ~/projects/myapp

root@kitploit:~
El código de salida es `0` si no se encuentran hallazgos críticos, `1` si se encuentran críticos — por lo que se compone limpiamente con otros comandos:```bash
gh-safe-repo scan . && git push

La configuración completa de [pre_flight_scan] aplica: banned_strings, max_file_size_mb, trufflehog_mode, etc.

Lo que detecta

Motor de escáner

gh-safe-repo elige automáticamente el mejor escáner disponible mediante una cadena de descubrimiento de tres pasos:

  1. truffleHog v3 en PATH — ejecuta trufflehog --version, verifica que sea v3 y lo utiliza. Una instalación v2 o una versión no reconocida imprime una advertencia y pasa al paso 2.
  2. podman o docker — si no se encuentra truffleHog nativo, el escáner ejecuta truffleHog en un contenedor (ghcr.io/trufflesecurity/trufflehog:latest) usando podman run o docker run, montando la ruta de escaneo en modo solo lectura en la misma ruta absoluta para que las rutas de salida JSON sean idénticas a una ejecución nativa.
  3. Respaldo con expresiones regulares — si no hay instalación nativa ni runtime de contenedor disponible, se imprime una advertencia y se ejecuta el escáner de expresiones regulares. También se ejecuta siempre además de truffleHog para correos electrónicos y TODOs, y captura patrones de ID de clave solitarios que truffleHog omite deliberadamente (truffleHog requiere ambas mitades de un par de credenciales, por ejemplo, AWS Key ID y Secret Access Key, antes de marcar un hallazgo).

El escáner seleccionado se muestra en el encabezado "Running pre-flight security scan..." y en la entrada SCAN de la tabla del plan, por ejemplo:``` 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:~
Variables de entorno que respeta la ruta del contenedor: `CONTAINER_RUNTIME` para anular la selección del runtime (por ejemplo, `CONTAINER_RUNTIME=docker`) y `TRUFFLEHOG_IMAGE` para fijar una etiqueta de imagen específica.

### Ejecutar truffleHog mediante podman o Docker (sin instalación local)

No se requiere configuración manual. `gh-safe-repo` detecta automáticamente podman o docker (paso 2 anterior) y ejecuta truffleHog en un contenedor con los montajes de volumen correctos. Se respetan las variables de entorno `CONTAINER_RUNTIME` y `TRUFFLEHOG_IMAGE`.

Se proporcionan un envoltorio de shell (`tools/trufflehog`) y un `Containerfile` para construir una imagen local fija en [`tools/`](https://github.com/ariesq/gh-safe-repo/blob/HEAD/tools/README.md) para usuarios que deseen tener truffleHog basado en contenedor disponible en todo el sistema, o que necesiten una imagen aislada.

### Revisión interactiva```
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]:
  • Hallazgos críticos: El valor predeterminado es abortar (N). Debes escribir explícitamente y para continuar.
  • Solo advertencias: El valor predeterminado es continuar (Y). Presiona Enter para proceder o escribe n para abortar.
  • Sin hallazgos: El escaneo se completa silenciosamente y el flujo de trabajo continúa.

Los secretos se redactan en la salida. Las direcciones de correo electrónico y los TODOs muestran la línea correspondiente.

Cobertura del escaneo

Los directorios de artefactos de compilación (node_modules, __pycache__, .venv, venv, dist, build) se omiten de forma predeterminada para mantener los escaneos rápidos. En repositorios git, esta omisión es condicional: antes de omitir un directorio, el escáner ejecuta git ls-files -- <dir> para verificar si hay archivos dentro que estén siendo rastreados. Si los hay, el directorio se escanea normalmente.

Esto significa que los árboles node_modules o dist confirmados (inusuales, pero ocurren) no se pasan por alto silenciosamente. Los directorios no confirmados (el caso normal) continúan omitiéndose como antes.

Todavía se imprime una advertencia cuando se encuentran subdirectorios SKIP_DIRS en un repositorio fuente clonado, ya que su presencia puede indicar que se ha confirmado más contenido del esperado.

Supresión de falsos positivos

Dos claves de configuración te permiten suprimir hallazgos conocidos como seguros sin deshabilitar categorías de verificación completas.

scan_exclude_paths — omitir archivos o directorios por completo. Los valores son patrones regex separados por nueva línea/comas que se comparan con la ruta de archivo relativa. Un archivo que coincide es excluido de todas las verificaciones: secretos, correos electrónicos, TODOs, archivos grandes y detección de archivos de contexto de IA. Los mismos patrones también se pasan a truffleHog a través de --exclude-paths, por lo que la cobertura es consistente independientemente del motor de escaneo activo.```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`** — suprime los hallazgos de correos electrónicos para direcciones específicas o dominios completos. Los valores están separados por nueva línea o coma, sin distinción entre mayúsculas y minúsculas. Las entradas que comienzan con `@` coinciden con todos los correos electrónicos de ese dominio; de lo contrario, la entrada debe coincidir exactamente con la dirección completa. Se aplica tanto a los hallazgos del árbol de trabajo como del historial de git.```ini
[pre_flight_scan]
# Suppress bot addresses and placeholder domains
exclude_emails = [email protected], [email protected], @example.com

Configuración del escáner```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:~
Cuando se encuentran cadenas prohibidas o archivos de contexto de IA, el escáner imprime un comando `git filter-repo` listo para ejecutar, para eliminarlos del historial del repositorio de origen antes de volver a ejecutarlo.

---

## Configuración

`gh-safe-repo` busca la configuración en este orden (el primero que coincide gana):

1. **`--config RUTA`** — anulación explícita
2. **`./gh-safe-repo.ini`** — directorio de trabajo actual
3. **`$XDG_CONFIG_HOME/gh-safe-repo/gh-safe-repo.ini`** — predeterminado a `~/.config` cuando `$XDG_CONFIG_HOME` no está establecido

`--config` sin argumento (sin ruta) omite la búsqueda de archivo por completo y usa solo los valores predeterminados internos.
Todos los valores tienen valores predeterminados seguros: no se requiere un archivo de configuración para empezar.

En el repositorio se incluye un ejemplo de configuración completamente anotado como `gh-safe-repo.ini.example`. Cópialo para empezar:```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

Referencia completa de configuración```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:~
---

## Limitaciones del Plan de GitHub

Algunas características solo están disponibles según la visibilidad del repositorio y tu plan de GitHub.

| Característica | Gratuito + Público | Gratuito + Privado | Pro/Equipo + Privado |
|---|:---:|:---:|:---:|
| Protección de ramas / Conjuntos de reglas | Sí | No | Sí |
| Protección de etiquetas (Conjuntos de reglas) | Sí | No | Sí |
| Alertas de Dependabot | Sí | No | Sí |
| Actualizaciones de seguridad de Dependabot | Sí | No | Sí |
| Escaneo de secretos | Auto | No | Sí |
| Protección contra envíos | Sí | No | Sí |
| Reporte privado de vulnerabilidades | Sí | Sí | Sí |
| Gráfico de dependencias | Auto | No | Sí |

`gh-safe-repo` detecta el nivel de tu plan y la visibilidad del repositorio en tiempo de ejecución. Las características no disponibles aparecen como `SKIP` en la salida del plan con una razón clara: la herramienta nunca falla en silencio.

---

## Cómo 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)

Arquitectura de plugins

Cada categoría de configuración es una clase de plugin autocontenida (gh_safe_repo/plugins/). Cada plugin:

  1. Obtiene el estado actual de la API de GitHub
  2. Compara con el estado deseado de la configuración
  3. Devuelve un Plan (lista de objetos Change: ADD / UPDATE / DELETE / SKIP)
  4. Aplica solo cambios reales — sin llamadas API para operaciones no necesarias

Esto significa que el modo de auditoría y el modo de creación usan la misma ruta de plan/aplicación. La única diferencia es si el estado actual se obtiene de un repositorio existente o se asumen los valores predeterminados de GitHub.

Autenticación

Las llamadas a la API resuelven un token en este orden:

  1. GITHUB_TOKEN variable de entorno — te permite apuntar a una cuenta específica sin cambiar la sesión activa de gh (y es la única credencial necesaria en CI)
  2. gh auth token — lo que haya configurado gh auth login
  3. Error si ninguno está disponible

Los tokens se pasan a los procesos hijos de gh api como GH_TOKEN en el entorno del subproceso y nunca se registran.

Las operaciones de Git (--local / --from push y clone) usan tus propias credenciales de git — clave SSH o helper de credenciales — por defecto, no el token de API. En entornos sin ninguno (por ejemplo, CI con solo GITHUB_TOKEN), la herramienta recurre a hacer push sobre HTTPS con el token en la URL; la opción de configuración [git_transport] mode controla esto (consulte la referencia de configuración). Las URL con token nunca se escriben en .git/config de tu repositorio y se eliminan de toda la salida.

Enfoque de la API

Todas las llamadas a la API de GitHub pasan por gh api a través de subprocess. Esto mantiene la autenticación completamente en la CLI de gh — sin código de gestión de tokens, sin flujo OAuth, sin fijación de versión de PyGithub. Los cuerpos de las solicitudes JSON se pasan mediante --input - (stdin), no con banderas --field.


Desarrollo```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:~
Vea [`tests/README.md`](https://github.com/ariesq/gh-safe-repo/blob/HEAD/tests/README.md) para descripciones de archivos de prueba, convenciones de simulación y cómo añadir nuevas pruebas.

### Estructura del proyecto```
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 el mapa de módulos, la arquitectura de complementos y una guía para agregar nuevas configuraciones.

Política de dependencias

No hay dependencias en tiempo de ejecución. Todo usa la biblioteca estándar de Python (argparse, configparser, subprocess, json, re). No agregue paquetes de terceros sin discusión.

pytest es la única dependencia de desarrollo, declarada como una entrada nativa de UV [dependency-groups] en pyproject.toml.


Trabajo Previo

Estos proyectos se estudiaron durante el diseño e influyeron en la arquitectura de gh-safe-repo. Son herramientas distintas con diferentes alcances y modelos de usuario; consulte docs/LEARNINGS.md para obtener notas técnicas detalladas sobre cómo se adaptaron los patrones.

  • github/safe-settings — Aplicación de GitHub a nivel de organización (Node.js/Probot) que aplica configuraciones de repositorio desde una configuración central. Fuente del patrón de arquitectura de complementos (una clase por categoría de configuración, obtener → diferenciar → aplicar) y el enfoque de comparación mergeDeep.

  • repository-settings/app — Variante más simple por repositorio de safe-settings, también Node.js/Probot. Proporcionó una referencia más limpia para el patrón de complemento base Diffable.

  • nicholasgasior/gh-repo-settings — Extensión CLI escrita en Go con un flujo de trabajo plan/apply. Inspiración principal para el patrón de envoltorio de subprocesos gh api y el diseño de salida del plan de ejecución en seco.

Descargar herramienta
OptionDescription
--publicCrear como repositorio público (predeterminado: privado)
--local PATHEnvía código desde un repositorio git local al nuevo repositorio. Primero ejecuta un escaneo previo. Mutuamente excluyente con --from.
--from OWNER/REPORefleja código desde un repositorio existente al nuevo repositorio. Ejecuta un escaneo previo. Mutuamente excluyente con --local.
--yes / -yOmite el mensaje de confirmación y aplica inmediatamente (para uso en scripting/lotes)
--dry-runImprime el plan sin realizar ningún cambio
--jsonEmite el plan como JSON a stdout en lugar de la tabla ANSI
--config [PATH]Ruta al archivo de configuración; --config sin argumentos usa solo los valores predeterminados integrados
--debugImprime cada llamada y respuesta de API
OptionDescription
--yes / -yOmite el mensaje de confirmación y aplica inmediatamente (para uso en scripting/lotes)
--dry-runMuestra el diff de configuración sin aplicar cambios
--jsonEmite el plan como JSON a stdout en lugar de la tabla ANSI
--config [PATH]Ruta al archivo de configuración; --config sin argumentos usa solo los valores predeterminados integrados
--debugImprime cada llamada y respuesta de API, más la identidad del repositorio resuelta (id, nombre completo, tipo de propietario)
Acción
Significado
ADD (verde)Nuevo ajuste aplicándose
UPDATE (amarillo)Ajuste existente cambiándose (modo auditoría)
DELETE (rojo)Ajuste eliminándose
SKIP (atenuado)No se necesita acción — ya en el valor deseado, o función no disponible en su combinación de plan/visibilidad
CategoríaGravedadEjemplos
Secretos hardcodeadosCríticaClaves AWS (AKIA…), tokens de GitHub (ghp_…, github_pat_…), claves privadas, URLs de bases de datos
Strings prohibidosCríticaCualquier cadena literal que configures (nombres de usuario, nombres de host internos, nombres en clave)
Archivos de contexto de IACríticaCLAUDE.md, AGENTS.md, .cursorrules, copilot-instructions.md, .cursor/ — pueden contener notas internas de desarrollo; el historial de git puede ser más sensible que la versión actual
Direcciones de correo electrónicoAdvertenciaCualquier patrón [email protected] en el árbol de trabajo y el historial de git
Archivos grandesAdvertenciaArchivos por encima del umbral de tamaño configurado (por defecto: 100 MB)
Comentarios TODO/FIXMEInformativo# TODO, # FIXME, # HACK, # XXX