Saltar al contenido principal

% 16k.es

Me cago en la leche, he subido una API KEY a github

Domingo por la tarde. Estaba escribiendo código absurdo en una tarde fría y lluviosa de otoño.

Después de un largo día frente al portátil, la cosa por fin funcionaba. Estaba usando un servicio en la nube para… lo que sea. Estaba cansado, y quería pushear ya el código a github e irme a ver una peli.

Como de costumbre, creé una copia del archivo de configuración y lo redacté para eliminar los secretos (la preciada API_KEY).

trufflehog puede salvarte el día

Hecho esto, abrí .gitignore para añadir el fichero de confifguración. El ejercicio habitual.

Entonces oí unas voces en mi cabeza. Era mi mujer protestando; era casi la hora de cenar, así que preparé algo rápido y volví al teclado.

Eché un último vistazo al archivo .gitignore que estaba editando. Distraído, lo cerré, y luego ejecuté git add -A.

Y git commit -m "mensaje de mierda".

Y git push origin main.

Me recosté en la silla y, de repente, me entró un escalofrío. ¿Había guardado el .gitignore con el archivo de configuración?

Ni siquiera tuve que comprobarlo, sabía la respuesta. En ese momento no estaba seguro de si es realmente posible borrar completamente un secreto de git (y todavía no estoy seguro del todo…) así que me apresuré a eliminar el repositorio antes de que alguien pudiera encontrarlo.

esto ha arruinado muchas vidas

Me di bastante prisa pero ¿cuánto tarda en descubrirse un secreto filtrado? ¿Minutos? ¿Segundos?

Por supuesto tuve que invalidar la key por si acaso.

## ¿Cómo evitar esto?

Esto no debería volver a pasar. ¡Pero estas cosas pasan!

Hay herramientas que pueden escanear el código en busca de secretos; pero confiar en un escaneo manual puede no ser una buena idea. Es como .. confiar en que edito .gitignore correctamente o muevo los secretos fuera del espacio de trabajo mientras escribo código estúpido para pasar el rato.

Esto debería hacerse automáticamente.

Una de estas herramientas es truflehog.

Trufflehog es capaz de escanear diferentes artefactos (un repositorio local o remoto de git, un sistema de ficheros, syslog, travis, jenkins…) Viene en varios sabores pero tiene una versión libre/de código abierto, así que puedo probarlo tranquilamente.

No estoy seguro pero parece ser una combinación de expresiones regulares y cálculos de entropía. Este enfoque puede dar lugar a falsos positivos, así que hay que tener cuidado. Ni que decir tiene que los falsos negativos también son posibles.

En cualquier caso, he comprobado mi repositorio:

$ trufflehog filesystem --config=generic.yml --no-update -x exclusions.txt Projects/ai-commit/
🐷🔑🐷  TruffleHog. Unearth your secrets. 🐷🔑🐷

2024-10-21T22:33:12+02:00	info-0	trufflehog	running source	{"source_manager_worker_id": "8C7xP", "with_units": true}
Found unverified result 🐷🔑❓
Detector Type: CustomRegex
Decoder Type: PLAIN
Raw result: api_key = *****************
Name: generic-api-key
File: Projects/ai-commit/config.ini
Line: 2

[...] trufflehog	finished scanning	{"chunks": 4, "bytes": 2005, "verified_secrets": 0, "unverified_secrets": 1, "scan_duration": "16.016782ms", "trufflehog_version": "3.82.11"}

Voilà, ahí está la clave. ¡Bien por trufflehog!

## Automatizando la comprobación

Hemos visto cómo ejecutar truffeohog manualmente, pero también podemos (¡y debemos!) automatizar la comprobación.

Por ejemplo, podemos añadir un hook script de git que ejecute trufflehog antes de hacer el commit: un script pre-commit.

Configurar el script pre-commit es fácil: sólo hay que escribir el script .git/hooks/pre-commit y hacerlo ejecutable.

#!/bin/bash

[...]

# avoid commiting secrets!
p_dir=~/Projects/ai-commit
/usr/local/bin/trufflehog filesystem --config=generic.yml --no-update -x ${p_dir}/exclude.txt --json --fail ${p_dir} >/dev/null 2>&1

if [ $? -ne 0 ]; then
    echo 
    echo "=================================="
    echo "          WARNING!!!              "
    echo "Check your code for leaked secrets"
    echo "=================================="
    echo 
    exit 1
fi

Precauciones:

  • el script debe llamarse pre-commit y debe ser ejecutable
  • el script debe terminar con un código de salida distinto de cero si falla (en este caso, si encuentra un secreto)
  • asegurarse de que config.hooksPath existe:
git config --local core.hooksPath .git/hooks

Ejemplo. Vamos a intentar comitear mi secreto de nuevo:

$ git add .
$ git commit -m "i should not push this..."

==================================
          WARNING!!!              
Check your code for leaked secrets
==================================

y se aborta el commit.

Hala, corro a ponerlo en todas mis aplicaciones antes de que sea demasiado tarde.