Saltar al contenido principal

gh-secure: asegurando un repositorio de GitHub en dos minutos

· 9 min de lectura
Nuria Liaño
Fundadora y profe de sistema, redes y programación

La seguridad tiene un problema curioso: sabemos que es importante, pero muchas veces la dejamos para después.

Primero queremos que el proyecto funcione. Luego desplegarlo. Después arreglar ese bug que lleva tres semanas esperando. Y cuando todo parece estar más o menos estable pensamos: vale, ahora debería revisar la seguridad.

El problema es que ese “ahora” puede tardar bastante en llegar.

Hace poco descubrí gh-secure, una extensión de GitHub CLI creada por GitHub Security Lab que intenta solucionar precisamente una pequeña parte de ese problema: configurar una serie de protecciones básicas de seguridad en un repositorio de GitHub sin tener que hacerlo todo manualmente.

Y decidí probarla en un proyecto real.

¿Qué es gh-secure?​

gh-secure es una extensión para la CLI de GitHub que permite revisar y activar varias funcionalidades de seguridad recomendadas por GitHub Security Lab.

No instala un antivirus mágico ni convierte un proyecto en inexpugnable.

Lo que hace es algo bastante más sencillo —y, precisamente por eso, útil—: automatizar la configuración de varias medidas de seguridad que GitHub ya ofrece.

Actualmente trabaja con cinco áreas:

  • Branch Protection
  • Private Vulnerability Reporting
  • Secret Scanning
  • Dependabot
  • Code Scanning con CodeQL

Es decir, muchas de esas opciones que probablemente hemos visto alguna vez navegando por la configuración de un repositorio, pero que no siempre nos paramos a configurar.

La propuesta de GitHub Security Lab es bastante directa: elevar la seguridad base de un proyecto en unos minutos.

Instalándolo​

Antes de probarlo: gh-secure está pensado principalmente para repositorios públicos y proyectos open source en GitHub, y necesita permisos de administración (admin) o mantenimiento (maintain) sobre el repositorio. Además, Code Scanning con CodeQL depende de que el proyecto use lenguajes compatibles y de que la funcionalidad esté disponible en el plan de GitHub correspondiente.

Si ya se utiliza GitHub CLI, instalarlo es simplemente:

gh extension install GitHubSecurityLab/gh-secure

Después podemos comprobar la configuración de seguridad actual del repositorio:

gh secure status

Este comando me parece especialmente interesante porque antes de tocar nada permite ver qué protecciones están habilitadas y cuáles faltan.

Pero hay otro comando que, personalmente, ejecutaría siempre antes de aplicar cambios:

gh secure --yes --dry-run

--dry-run simula las modificaciones sin aplicarlas.

Y esto me gusta especialmente.

Cuando una herramienta va a cambiar reglas de ramas, análisis de código o configuración de seguridad de un repositorio, prefiero saber exactamente qué pretende hacer antes de darle permiso.

Una vez revisado, se puede ejecutar:

gh secure

de forma interactiva, o:

gh secure --yes

para activar directamente las funcionalidades seleccionadas.

¿Qué cambia realmente en el proyecto?​

Aquí es donde gh-secure empieza a resultar interesante.

No modifica el código de la aplicación. Lo que hace es añadir protecciones alrededor del proceso de desarrollo.

1. Proteger la rama principal​

Una de las primeras medidas es Branch Protection.

En un proyecto en el que se trabaja con ramas y Pull Requests tiene bastante sentido impedir que main pueda modificarse alegremente.

La idea es sencilla:

feature/*
│
▼
Pull Request
│
├── tests
├── revisión
├── CodeQL
│
▼
main

Así se reduce la posibilidad de que un cambio accidental —o directamente malicioso— llegue a la rama principal sin pasar por los controles establecidos.

Hay un detalle importante: si el repositorio ya utiliza Rulesets, gh-secure lo detecta y avisa antes de habilitar la protección de ramas tradicional.

Esto evita acabar con dos sistemas de reglas superpuestos sin darse cuenta.

2. Evitar subir secretos al repositorio​

Probablemente esta sea una de las funciones que más valoro.

En cualquier proyecto real empiezan a aparecer cosas como:

DATABASE_PASSWORD=...
CLOUDFLARE_API_TOKEN=...
STRIPE_SECRET_KEY=...

Naturalmente, deberían vivir en un gestor de secretos, variables de entorno o mecanismos equivalentes.

Pero también somos humanos.

Un:

git add .
git commit -m "fix config"
git push

puede acabar siendo bastante más emocionante de lo previsto.

Secret Scanning analiza el repositorio buscando credenciales y otros secretos, mientras que Push Protection puede bloquear el push antes de que determinados secretos terminen publicados.

GitHub indica que actualmente puede proteger frente a más de 300 tipos y patrones de tokens pertenecientes a más de 180 proveedores.

No sustituye a gestionar correctamente los secretos, pero añade una barrera adicional ante errores humanos.

Y cualquier cosa que consiga que un error tonto no termine convirtiéndose en una tarde rotando credenciales me parece bienvenida.

3. Dependabot​

Esta seguramente sea la funcionalidad más conocida.

Nuestros proyectos dependen de paquetes que, a su vez, dependen de otros paquetes.

Y alguno de ellos terminará teniendo una vulnerabilidad.

Dependabot comprueba las dependencias del proyecto frente a vulnerabilidades conocidas y puede crear Pull Requests para actualizar las versiones afectadas.

Eso no significa:

“Dependabot ha creado un PR, hago merge y me olvido”.

Una actualización puede romper cosas y sigue siendo necesario revisar y probar los cambios.

Pero sí evita depender exclusivamente de acordarse de comprobar manualmente si alguna de las 200 dependencias del proyecto tiene una vulnerabilidad conocida.

4. Analizar el código con CodeQL​

Aquí entramos en una parte que me parece especialmente interesante.

gh-secure también puede activar Code Scanning mediante CodeQL.

CodeQL analiza el código buscando patrones relacionados con vulnerabilidades de seguridad.

Además, el análisis puede ejecutarse con los pushes y Pull Requests, haciendo que la seguridad forme parte del ciclo normal de desarrollo.

Para mí este es uno de los cambios conceptuales más importantes.

La seguridad deja de ser:

desarrollar → desplegar → algún día revisar seguridad

y pasa a acercarse más a:

desarrollar
↓
Pull Request
↓
tests + análisis de seguridad
↓
merge
↓
deploy

No significa que CodeQL vaya a encontrar absolutamente todas las vulnerabilidades.

Ninguna herramienta puede hacer eso.

Pero introduce análisis de seguridad de manera continua sin tener que acordarse de lanzarlo manualmente.

5. Private Vulnerability Reporting​

Esta función me parece especialmente útil en proyectos públicos.

Si alguien encuentra una vulnerabilidad, ¿cómo te la comunica?

Lo último que quieres es descubrirla mediante una issue pública que explique perfectamente cómo explotarla.

Private Vulnerability Reporting proporciona un canal para que investigadores o usuarios puedan comunicar problemas de seguridad de forma privada.

Es una de esas funcionalidades que probablemente no valores demasiado...

hasta el día que la necesitas.

Lo que me ha gustado​

Lo primero es la simplicidad.

No está intentando inventar cinco herramientas nuevas de seguridad. Está utilizando funcionalidades que GitHub ya proporciona y facilitando que se configuren correctamente.

También me gusta muchísimo que exista --dry-run.

Poder ejecutar:

gh secure --yes --dry-run

antes de modificar nada hace que probar la herramienta sea bastante menos intimidante.

Otro punto interesante es que se pueden activar funcionalidades individualmente.

Por ejemplo:

gh secure secret-scanning

o:

gh secure branch-protection dependabot

No es necesario aceptar toda la configuración de golpe.

Y, sobre todo, me gusta una idea que hay detrás de la herramienta:

hacer que tener una seguridad base razonable sea más fácil que no tenerla.

Lo que no me gusta tanto​

También hay que poner las expectativas en su sitio.

Ejecutar:

gh secure --yes

no significa que el proyecto sea seguro.

Y creo que este es probablemente el mayor peligro de herramientas de este tipo: generar una falsa sensación de seguridad.

gh-secure puede ayudar a detectar secretos, dependencias vulnerables o determinados problemas en el código, pero no conoce toda la arquitectura de nuestra aplicación.

No sabe si nuestra API está correctamente autorizada.

No sabe si hemos configurado mal PostgreSQL.

No sabe si nuestros backups funcionan.

No sabe si nuestros contenedores se ejecutan con más privilegios de los necesarios.

No sabe si tenemos un endpoint que permite acceder a información que un usuario no debería poder consultar.

En otras palabras:

mejora la seguridad del repositorio y del proceso de desarrollo, pero no sustituye una estrategia de seguridad.

También hay que revisar especialmente la protección de ramas.

Activarla puede modificar el flujo de trabajo de un repositorio y obligar, por ejemplo, a trabajar mediante Pull Requests en situaciones en las que antes se permitía hacer push directamente.

Eso puede ser exactamente lo que buscamos, pero conviene saberlo antes de ejecutar el comando.

Entonces, ¿lo utilizaría?​

Sí.

Pero no porque piense que gh-secure vaya a solucionar la seguridad de un proyecto.

Lo utilizaría porque el coste de introducir estas protecciones es ridículamente pequeño comparado con el beneficio que pueden aportar.

Instalar:

gh extension install GitHubSecurityLab/gh-secure

Comprobar:

gh secure status

Simular:

gh secure --yes --dry-run

Revisar.

Y aplicar únicamente aquello que tenga sentido para el proyecto.

Son unos minutos.

A cambio podemos incorporar protección de ramas, detección de secretos, vigilancia de dependencias, análisis estático de seguridad y un mecanismo privado para reportar vulnerabilidades.

Me parece un intercambio bastante bueno.

La parte que realmente me interesa​

Después de probarlo, creo que lo más interesante de gh-secure no es realmente gh-secure.

Es el enfoque.

Cuando un proyecto empieza a crecer es muy fácil centrarse únicamente en funcionalidades:

¿Qué desarrollamos ahora?

Pero llega un momento en el que también hay que empezar a preguntarse:

¿Qué pasa cuando algo sale mal?

¿Qué ocurre si alguien sube una credencial?

¿Qué ocurre si aparece una vulnerabilidad en una dependencia?

¿Qué ocurre si un cambio inseguro intenta llegar a producción?

¿Qué ocurre si alguien externo encuentra una vulnerabilidad?

No existe un comando que responda completamente a todas esas preguntas.

Pero podemos ir construyendo pequeñas barreras.

Tests.

Pull Requests.

Branch Protection.

Secret Scanning.

Dependabot.

CodeQL.

Backups.

Observabilidad.

Control de accesos.

Y probablemente esa sea la idea con la que me quedo después de probar gh-secure:

la seguridad no suele consistir en instalar una herramienta enorme al final del proyecto. Consiste en ir introduciendo pequeñas barreras durante todo el proceso de desarrollo.

gh-secure simplemente hace que cinco de esas barreras sean bastante fáciles de empezar a utilizar.


Proyecto: GitHubSecurityLab/gh-secure
Repositorio oficial: https://github.com/GitHubSecurityLab/gh-secure