¡No puedes pasar!

Gandalf, plantado en mitad del puente de Khazad-dûm, golpea la piedra con el bastón y le grita al Balrog “¡No puedes pasar!”. Es una de las escenas más épicas de “El Señor de los Anillos”, y también la forma en que muchos equipos de desarrollo ven al equipo de seguridad: un señor con barba que aparece al final del camino, cuando ya está todo hecho, y que no te deja cruzar. El Balrog, en esta versión, es la release que tenía que salir el viernes.

He visto esa escena repetirse muchas veces en todos los años que llevo metido en esto. El patrón es casi siempre el mismo: el equipo trabaja semanas en una funcionalidad, alguien lanza un análisis de seguridad pocos días antes de la fecha de entrega, sale un informe en PDF con cientos de hallazgos ordenados por colores, y a partir de ahí empieza la negociación. Que si este es un falso positivo, que si aquel lo arreglamos en la siguiente versión, que si quién firma la excepción, etc. Al final la release sale casi igual que estaba, todo el mundo acaba de mal humor y la seguridad real del producto no ha mejorado gran cosa.

¿Por qué acaban los desarrolladores odiando al equipo de seguridad? Es fácil de explicar: porque la seguridad les llega tarde, les llega con ruido y les llega sin solución. Si arreglas esas tres cosas, el odio desaparece, o al menos se queda en las quejas de siempre que provoca cualquier cambio.

Que llegue pronto

En 2003, a raíz del gusano SQL Slammer, escribí en el boletín que el gran problema de la seguridad era el factor humano: un fallo conocido y parcheado seis meses antes había tumbado medio Internet porque nadie había aplicado el parche. Mi receta de entonces era cumplir la política de seguridad “a rajatabla”. Hoy sigo pensando que el factor humano es el eslabón débil, pero la receta ha cambiado: en lugar de exigir a las personas que no se equivoquen, hay que montar el sistema para que equivocarse sea difícil y, si pasa, se note enseguida.

Eso es lo que la gente llama shift left, y en la práctica significa algo muy concreto: el aviso tiene que aparecer donde el desarrollador ya está mirando, y en el momento en que todavía tiene el contexto fresco. Un secreto subido al repositorio se tiene que detectar en el commit, con un hook de pre-commit, y no tres semanas después en una auditoría. Un fallo en el código Terraform se tiene que ver como comentario en la pull request, al lado de la línea que lo causa. Una dependencia con una vulnerabilidad crítica se tiene que señalar en el mismo pipeline que compila el código. Herramientas para todo esto hay de sobra y muchas son Software Libre (gitleaks, Trivy, Semgrep, Checkov, etc.); lo difícil nunca ha sido elegir la herramienta, sino colocarla en el sitio adecuado.

Y que sea rápido. Si los controles de seguridad añaden diez minutos a cada build, alguien encontrará la forma de saltárselos, y tendrá parte de razón. Los análisis pesados, como los dinámicos o los escaneos completos de imágenes, pueden correr por la noche o en paralelo, fuera del camino crítico. En la pull request solo debe ir lo que es rápido y lo que de verdad importa.

Que no haga ruido

Este es el error que más veces he visto cometer. Activas un escáner de contenedores sobre una imagen base cualquiera, te devuelve trescientas vulnerabilidades, la mitad sin parche disponible y la mayoría en librerías que tu aplicación ni siquiera carga, y decides que el pipeline falle si hay alguna. Resultado: el pipeline falla siempre, el equipo aprende a ignorarlo en una semana y en un mes alguien ha puesto continue-on-error: true “temporalmente”. Un control que siempre está en rojo es exactamente igual de útil que uno que no existe.

Lo que me ha funcionado es empezar por muy poco y bloquear todavía menos. Al principio, el pipeline solo se para por dos cosas: secretos en el código y vulnerabilidades críticas que tienen arreglo disponible. Todo lo demás se informa, se registra y se revisa con calma, pero no frena a nadie. Cuando el equipo se acostumbra y el contador baja, se sube el listón. Es más lento que encender todo el primer día, pero es la única forma que conozco de que los controles sigan encendidos seis meses después.

Las excepciones también forman parte del ruido. Siempre va a haber hallazgos que no se pueden arreglar en el momento, y mirar para otro lado no los hace desaparecer. Lo sensato es que cada excepción tenga un responsable, un motivo y una fecha de caducidad, y que esté en el repositorio junto al código, no en un correo perdido. Cuando caduca, el pipeline vuelve a avisar y alguien tiene que decidir otra vez.

Y la mejor forma de detectar el ruido es escuchar a quien lo sufre. Cada vez que un equipo de desarrollo se me ha quejado con razón de un control demasiado draconiano, lo he corregido inmediatamente. Para mí ese es el papel de quien hace DevOps: mediar entre todas las partes y buscar el equilibrio entre funcionalidad, entrega, seguridad, calidad, etc. Se acabó lo del administrador de sistemas clásico de “el sistema es mío y aquí se hace lo que yo diga”, que frustraba a todo el que tenía alrededor y creaba muy mal rollo en los equipos.

Que traiga la solución

Un informe que dice “tienes 47 vulnerabilidades” no arregla nada: solo le pasa el marrón al equipo de desarrollo, que tiene que averiguar qué actualizar, a qué versión y si se rompe algo. Una pull request que actualiza la librería afectada, con los tests en verde, es una solución que solo hay que revisar y aceptar. Herramientas como Renovate o Dependabot hacen exactamente eso, y en mi experiencia han hecho más por la seguridad de las dependencias que todos los informes en PDF juntos.

Lo mismo vale para la plataforma. Si la plantilla de pipelines que usa todo el mundo ya trae los análisis configurados, si las imágenes base son mínimas y se actualizan solas, si los contenedores arrancan sin root por defecto y si el módulo de Terraform para crear un bucket ya lo crea cifrado y privado, el desarrollador tiene la seguridad hecha sin pensar en ella. Es lo que ahora se llama golden path: el camino fácil y el camino seguro tienen que ser el mismo camino. Cuando no lo son, la gente coge el fácil, siempre.

Y queda la parte que no se automatiza: explicar el porqué. Un equipo que entiende por qué no debe guardar un token en una variable de entorno visible en los logs no necesita que se lo prohíba nadie. Una sesión corta, un ejemplo real de lo que puede pasar o una revisión conjunta de un hallazgo valen más que cualquier política escrita en la wiki que nadie lee.

El Gandalf que hace falta

No digo que la seguridad nunca deba decir que no. Hay cosas que no pueden pasar, y para eso están los controles que bloquean. Pero el trabajo de alguien que hace DevSecOps no es plantarse en el puente al final del camino, sino ir con el equipo desde el principio, avisar de los trasgos antes de que aparezcan y conseguir que el puente aguante. Más guía de la Comunidad del Anillo y menos portero de discoteca.

Lo dicho, que nadie tenga que gritar “¡No puedes pasar!” la víspera de una release.

Contenidos bajo licencia CC BY-NC-SA 4.0