DEV Community

Cover image for Seguridad como proof of work: por qué el compliance no salva a nadie
Juan Torchia
Juan Torchia

Posted on • Originally published at juanchi.dev

Seguridad como proof of work: por qué el compliance no salva a nadie

El 80% de los breaches documentados en 2024 involucran credenciales expuestas. No zero-days. No exploits sofisticados. Credenciales. En texto plano, en repos, en variables de entorno commiteadas, en Slack. Cuando leí eso tuve que releer dos veces porque yo acababa de revisar tres PRs con exactamente ese problema.

Y lo más incómodo no fue encontrarlas. Fue darme cuenta de que las tres habían pasado por revisión antes de llegar a mí.

Seguridad como proof of work: la trampa del compliance visible

Hay algo que cambió en los últimos años y no terminé de nombrarlo hasta esta semana. La seguridad se convirtió en una actividad de señalización. No en el sentido de que sea falsa — en el sentido de que el trabajo visible desplazó al trabajo efectivo.

Tenemos badges. Tenemos dashboards. Tenemos Dependabot mandando PRs automatizadas, Snyk escaneando cada push, SBOM generado en el pipeline, SPF y DKIM configurados en el DNS, DMARC en modo reject, secretos en Vault, rotación automática de tokens. Todo eso está. Todo eso es real y costó semanas de trabajo.

Y de todos modos alguien commiteó API_KEY=sk-prod-abc123... en un archivo .env que alguien más decidió no agregar al .gitignore porque "es solo el repo interno".

Eso es lo que llamo seguridad como proof of work. Hacés el trabajo. Lo demostrás. El trabajo no te protege de lo que no midió nadie.

El problema real: la asimetría de visibilidad

Cuando configurás DMARC, hay un cambio en el DNS. Es auditable. Aparece en logs. Podés mostrarle a alguien la pantalla y decir "esto lo hice yo". Cuando creás una cultura donde nadie commitea secrets porque todos entienden por qué no se hace — eso no aparece en ningún dashboard.

El trabajo invisible de seguridad es:

  • La conversación que tuviste con el junior explicándole qué es un secret y por qué importa
  • El proceso de onboarding que diseñaste para que el día uno incluya configurar el gestor de contraseñas del equipo
  • La PR que rechazaste y el comentario que escribiste explicando el razonamiento, no solo el error
  • La decisión de no dar acceso de escritura al repo de producción aunque fuera "más cómodo"
  • El momento en que dijiste "esto lo movemos a variables de entorno" antes de que nadie lo pidiera

Nada de eso aparece en el compliance report. Nada de eso suma puntos en la auditoría. Pero es exactamente lo que falta cuando un secret llega a main.

Por qué el tooling solo no alcanza

Hice el ejercicio esta semana. Busqué en el historial de git del proyecto cuántas veces gitleaks o detect-secrets habían bloqueado algo antes de que llegue a revisión.

La respuesta fue ninguna. No porque no estuvieran configurados — estaban. Sino porque el secret estaba en un archivo que el hook no escaneaba porque alguien lo había agregado a la excepción lista hace seis meses por una razón que nadie recuerda.

# .gitleaks.toml que heredé
[allowlist]
  description = "Archivos excluidos del escaneo"
  paths = [
    # ⚠️ Esto se agregó en julio y nadie sabe por qué
    '''(?i)(\.env\.example|\.env\.local|config/secrets)''',
    # ⚠️ Este path incluye el archivo donde estaban los secrets reales
    '''(?i)(tests/fixtures)'''
  ]
Enter fullscreen mode Exit fullscreen mode

Eso es lo que pasa cuando el tooling se configura una vez y nadie lo revisa. Se convierte en teatro. El scanner corre, el badge dice verde, el secret está en el repo.

Lo mismo me pasó cuando estaba optimizando imágenes Docker — las herramientas de análisis de vulnerabilidades en capas te dicen exactamente qué CVEs están presentes, pero si tu proceso de build copia archivos que no deberían estar ahí, el problema no es la imagen sino el Dockerfile. La herramienta ve lo que puede ver.

El momento del cyber café — y qué aprendí de verdad

En 2005 tenía 14 años y laburaba en un cyber café. Cuando se caía la conexión a las 11pm con el local lleno, yo tenía que arreglarlo. No había documentación. No había runbook. No había nadie a quien llamar.

Aprendí redes a la fuerza en esas noches. Pero más que redes, aprendí algo sobre seguridad que tardé años en articular: el adversario no te avisa cuándo va a atacar, y no respeta tu horario de compliance.

Los tipos que explotaban las máquinas del cyber para minar, para proxear tráfico, para usar el ancho de banda — no esperaban que yo tuviera el antivirus actualizado. Actuaban en el momento en que el sistema era vulnerable, que generalmente era las 2am cuando yo no estaba.

Eso es asimetría real. Y veinte años después, sigue siendo el problema central.

Lo que deberían medir los equipos y no miden

Si tuviese que diseñar métricas de seguridad que importan, no arrancaría por Dependabot. Arrancaría por acá:

Tiempo hasta detección de un secret en el repo — no tiempo hasta resolución, tiempo hasta que alguien se da cuenta. Si tardaste tres días en notar que había una key en main, el scanner no está funcionando como herramienta de alerta real.

Tasa de rechazos de PR por razones de seguridad — si este número es cero, no es porque el equipo sea perfecto. Es porque nadie está mirando.

Cobertura real del escaneo — no "el scanner corre", sino qué porcentaje del código que llegó a main pasó efectivamente por el scanner sin excepciones. Esto es distinto y la diferencia es enorme.

Proporción de secrets rotados proactivamente vs. reactivamente — si todos tus secrets se rotan después de un incidente, el proceso de seguridad es reactivo disfrazado de proactivo.

# Lo que quiero saber vs. lo que me dicen los dashboards

# Dashboard típico:
metricas_visibles = {
    "dependabot_prs_merged": 47,
    "snyk_vulnerabilities_fixed": 12,
    "dmarc_compliance": "100%",
    "secrets_vault_rotations": 8
}

# Lo que importa y nadie mide:
metricas_reales = {
    # ¿Cuánto tardaste en detectar el último secret expuesto?
    "tiempo_deteccion_ultimo_secret": "3 días",
    # ¿Qué % del código realmente escaneado (sin excepciones)?
    "cobertura_real_scanner": "67%",  # no 100%
    # ¿Cuántas rotaciones fueron ANTES de un incidente?
    "rotaciones_proactivas_vs_reactivas": "2 de 8",
    # ¿Cuántos rechazos de PR por seguridad este mes?
    "pr_rechazadas_seguridad": 0  # ← esto es una bandera roja
}
Enter fullscreen mode Exit fullscreen mode

Cuando estoy pensando en workflows automatizados con Claude Code o en cómo los agentes de IA ya resuelven cosas que estaba reimplementando a mano, siempre termino en el mismo punto: la automatización amplifica lo que tenés. Si tenés un proceso sano, la automatización lo escala. Si tenés teatro de seguridad, la automatización escala el teatro.

Los gotchas que nadie documenta

Gitleaks con excepciones heredadas — revisá el allowlist de gitleaks o detect-secrets en tu repo. Ahora mismo. Si tiene paths o patrones que no podés explicar, probablemente estén cubriendo algo que no deberían.

Pre-commit hooks que se skipeangit commit --no-verify existe y el equipo lo sabe. El hook en pre-commit no es una barrera, es un recordatorio. Si la cultura no está, el hook no alcanza.

Secrets en mensajes de commit — los scanners de código no siempre escanean el historial de commits. Un secret que llegó y se removió en el mismo día puede seguir siendo accesible en el historial si el repo es público o si alguien clonó antes del cleanup.

Variables de entorno en logs — este es el que más me quema. Configurás todo perfecto, los secrets están en Vault, las variables se inyectan en runtime. Y después alguien agrega un console.log(process.env) para debuggear y lo commitea sin darse cuenta. Los logs de producción ahora tienen todo.

El problema del .env.example — este archivo existe para documentar qué variables necesitás. Invariablemente, en algún momento, alguien lo edita con valores reales "temporalmente" y lo commitea. El .env.example debería ser revisado en cada PR que lo toque.

FAQ: seguridad como proof of work

¿Qué es lo primero que debería revisar en un proyecto heredado?
El historial de git buscando patterns de secrets, el allowlist de los scanners de seguridad, y los permisos de acceso al repo. En ese orden. El allowlist de los scanners es el más ignorado y el más peligroso porque da falsa sensación de cobertura.

¿Dependabot y Snyk son inútiles entonces?
No, son necesarios pero no suficientes. Resuelven el problema de dependencias con vulnerabilidades conocidas, que es real. No resuelven el problema de secrets hardcodeados, malas prácticas de acceso, o configuraciones inseguras. Son una capa, no una solución completa.

¿Cómo convencés a un equipo de tomarse en serio los secrets si el delivery pressure es alto?
No con charlas de seguridad. Con el primer incidente real que les toca cerca. Antes de eso, lo más efectivo que encontré es automatizar el rechazo — que el CI/CD no avance si detect-secrets encuentra algo, sin excepciones posibles sin aprobación explícita del tech lead.

¿Qué hago si ya hay secrets en el historial de git?
Primero, asumir que están comprometidos y rotar todo. Segundo, usar git filter-repo para reescribir el historial (no git filter-branch, que está deprecado). Tercero, forzar a todos los que clonaron el repo a hacer un fresh clone porque sus copias locales siguen teniendo el historial viejo.

¿El problema es técnico o cultural?
Las dos, pero en distinta proporción según el equipo. El tooling es la parte fácil — un día de trabajo y tenés gitleaks, detect-secrets y pre-commit hooks configurados. La parte difícil es que todos en el equipo entiendan por qué importa, no solo que hay una regla. La diferencia entre esas dos cosas es exactamente lo que separa el equipo que tiene el secret hardcodeado aprobado en main del equipo que no lo tiene.

¿Vale la pena certificarse en seguridad (CISSP, CEH, etc.)?
Depende de para qué. Si querés hacer seguridad ofensiva o dedicarte exclusivamente a seguridad, sí. Si sos developer o arquitecto que quiere ser más riguroso con seguridad en el día a día, el tiempo invertido en entender el OWASP Top 10 en profundidad y practicar threat modeling te da más retorno que una certificación.

Conclusión: el trabajo que no se ve

Hay algo que me quedó de esas noches en el cyber café a los 14 años que conecta con todo esto. Cuando arreglabas la conexión a las 11pm y el local volvía a funcionar, nadie sabía exactamente qué habías hecho. Solo sabían que funcionaba. El trabajo visible era el resultado, no el proceso.

La seguridad real funciona igual. Cuando funciona, no pasa nada. Nadie aplaude el breach que no ocurrió. Nadie celebra el secret que nunca llegó a main. El proof of work de la seguridad efectiva es, paradójicamente, la ausencia de eventos.

El problema es que en un mundo donde la atención va a lo visible, terminamos optimizando para lo visible. Badges, dashboards, compliance reports. Todo eso tiene valor — no lo estoy tirando abajo. Pero si esas herramientas se convierten en el objetivo en lugar del medio, estamos haciendo teatro.

El secreto hardcodeado que encontré esta semana no me sorprendió porque el equipo sea malo. Me sorprendió porque el equipo tiene todo lo visible configurado y de todos modos pasó. Eso es exactamente la señal que buscaba.

Si estás pensando en cuánto de tu stack de seguridad es real vs. señalización, el ejercicio que te propongo es simple: tomá el último incidente o near-miss que tuviste, y rastreá exactamente en qué punto del proceso debería haber sido detectado y por qué no lo fue. La respuesta casi siempre está en una excepción que nadie recuerda haber puesto, o en un proceso que asumía que otra persona lo estaba mirando.

El trabajo invisible de seguridad es el que más importa. Y es exactamente el que menos tiempo le dedicamos.

Top comments (0)