Pentest

Secretos en repositorios y variables de entorno

Alguien prueba una integración, pega la clave de la API en un archivo de configuración, hace commit y sigue con lo suyo. Dos semanas después se da cuenta, borra el archivo, hace otro commit y se queda tranquilo. La clave sigue ahí. Este es el error de seguridad más humano que existe y conviene entender por qué el "borrado" no borra nada.

Por qué borrar el archivo no alcanza

Git guarda la historia completa. Cuando eliminás un archivo, el commit nuevo registra que ya no existe, pero el commit anterior, con la clave adentro, sigue siendo parte del repositorio. Cualquiera que clone el proyecto puede recorrer el historial y recuperarla. Lo mismo vale para las ramas viejas, las etiquetas y los forks que alguien haya hecho en el medio.

Si el repositorio fue público aunque sea un rato, hay que asumir que la credencial se copió. Existen programas que rastrean repositorios nuevos todo el tiempo en busca de patrones de claves, y lo hacen en cuestión de minutos. Si fue privado, el riesgo es menor pero no nulo: lo ven todos los que tengan acceso hoy y los que lo tengan mañana, incluidos servicios de integración y copias locales en notebooks.

Reescribir la historia con herramientas de limpieza ayuda a reducir la exposición, pero no es una solución por sí sola. Las copias ya clonadas no se enteran.

Qué hacer cuando ya pasó

El orden importa y la limpieza va al final:

  1. Rotá la credencial de inmediato. Generá una nueva, actualizala donde se usa y revocá la anterior. Todo lo demás es secundario.
  2. Revisá los registros del servicio al que daba acceso, buscando usos que no reconozcas durante el período de exposición.
  3. Si la clave tenía más permisos de los que necesitaba, aprovechá para crear la nueva con el mínimo indispensable.
  4. Recién ahí, limpiá el historial si corresponde y avisá al equipo para que vuelva a clonar o sincronice.

Rotar sin limpiar es suficiente. Limpiar sin rotar no sirve de nada.

Evitar que ocurra

Lo primero es sacar los secretos del código. Las contraseñas, tokens y claves de API entran a la aplicación desde afuera, normalmente por variables de entorno o por un gestor de secretos. El código lee, por ejemplo, os.environ["DB_PASSWORD"] y falla con un error claro si no está definida.

Los archivos locales de configuración (el típico .env) tienen que estar en .gitignore desde el primer commit, no después del susto. Una práctica útil es versionar un archivo de ejemplo con los nombres de las variables y valores falsos:

# .gitignore
.env
*.pem
*.key

# .env.example (este sí se versiona)
DB_PASSWORD=cambiar-esto
API_TOKEN=cambiar-esto

El .gitignore solo evita agregar archivos nuevos; no hace nada con los que ya estaban rastreados. Si el .env ya se había subido, hay que sacarlo del índice además de ignorarlo.

Variables de entorno: útiles, con límites

Las variables de entorno son un paso adelante, pero no son una caja fuerte. Se heredan a los procesos hijos, pueden aparecer en volcados de diagnóstico, en páginas de error con el entorno completo o en los registros de una herramienta de despliegue que imprime todo. Evitá escribirlas en los logs, no las pases como argumentos de línea de comandos (quedan visibles en la lista de procesos) y desconfiá de las plantillas de depuración que muestran el entorno.

Cuando el proyecto crece, un gestor de secretos aporta cosas que las variables no dan: control de quién lee cada secreto, registro de accesos, rotación automatizada y credenciales de corta vida. No hace falta empezar por ahí, pero conviene saber a dónde ir cuando el equipo pase de dos personas a diez.

Detectar antes de que llegue al remoto

Los detectores de secretos buscan patrones conocidos (formatos de claves, cadenas de alta entropía, nombres de variable sospechosos) y se pueden correr en dos lugares:

Esperá falsos positivos y algún falso negativo. Una clave con formato propio, o partida en dos variables, puede pasar sin ser detectada. Por eso la detección acompaña a la práctica de fondo, no la reemplaza.

Permisos mínimos como seguro

Hay una pregunta que ordena todo: si esta credencial se filtra mañana, ¿qué puede hacer quien la tenga? Una clave que solo lee un bucket de un entorno de pruebas es un incidente menor. Una clave de administrador de toda la cuenta es el peor día del año. Separá credenciales por entorno y por servicio, dales vencimiento cuando se pueda y vas a notar que cada filtración duele bastante menos.