Introducción a la Automatización de Pruebas de Seguridad en el Ciclo DevOps
![Introducción a la Automatización de Pruebas de Seguridad en el Ciclo DevOps](/content/images/size/w1200/2025/01/Thumbnail-Devops-January.png)
En fintech.works nos dedicamos a producir software para el sector de procesamiento de pagos, lo cual nos obliga a mantener un estándar de seguridad durante todo el proceso de desarrollo.
Este estándar lo mantenemos mediante un sistema que debe cumplir los siguientes requisitos:
- Accesible: No debería tomar más de 5 minutos explicar el sistema a un nuevo developer, esto también implica el uso de herramientas conocidas y prácticas tradicionales.
- Inmediato: El sistema debe reportar problemas de seguridad encontrados minutos después de haberlo integrado a una rama importante.
- Medible: Una persona ajena al desarrollo debería poder saber a fin de mes la cantidad de problemas de seguridad reportados, mitigados y en proceso de mitigación.
- Auditable: Todo el proceso debería generar logs detallados que puedan ser verificados por un agente externo.
El objetivo de este blog es mostrar los checkpoints de seguridad que implementamos para poder cumplir estos requisitos.
Happy Path
En el siguiente diagrama podemos ver el camino típico que sigue un cambio en el código fuente desde que es publicado en una rama "feature" hasta que finalmente llega a la rama "main" donde puede considerarse en producción, esto implica que este cambio está expuesto al mundo exterior y a clientes.
![](https://blog.fintech.works/content/images/2025/01/Screenshot-2025-01-28-at-3.28.39-PM.jpg)
Siguiendo los pasos tenemos el siguiente flujo:
- Se baja la rama "main".
- Se agrega una funcionalidad nueva en una rama "feature" y se hace commit al repositorio.
- Se genera un pull-request a la rama "main" para integrar el cambio.
- Este pull request es aceptado o rechazado por un developer senior.
- Finalmente se integra a la rama "main" quedando en producción.
Checkpoint 1: White box lint
El primer checkpoint de seguridad lo encontramos en el propio IDE utilizado por los desarrolladores, para esto existe una gran variedad de linters dedicados exclusivamente a detectar problemas de seguridad como tokens en texto plano, valores de variables secretas en código y otros problemas que pueden ser llevados por error al repositorio compartido.
![](https://blog.fintech.works/content/images/2025/01/Screenshot-2025-01-28-at-3.29.25-PM.jpg)
Al ser el primer checkpoint, estadísticamente encuentran y permiten mitigar la mayoría de los problemas de seguridad en el código, reduciendo la carga de los checkpoints posteriores lo que aumenta su efectividad y disminuyen el ruido generado por sus alertas.
Checkpoint 2: White box CI/CD
Normalmente, el cliclo de vida de una rama feature está compuesta de N pull requests que van agregando funcionalidades nuevas, el checkpoint 2 se ejecuta cada vez que se crea un pull request nuevo, analizando el código nuevo y reportando los resultados en un comentario dentro del mismo. Opcionalmente también se envían por email reportes sobre el pull-request. Entre las herramientas listadas se encuentran:
- Sonar y Snyk: pruebas de vulnerabilidades en código.
- Git Leaks: chequeo de datos sensibles como contraseñas, API keys y tokens.
![](https://blog.fintech.works/content/images/2025/01/Screenshot-2025-01-28-at-3.30.36-PM.jpg)
Casi todas las herramientas de escaneo ofrecen la posibilidad de crear automáticamente pull-requests con fixes de los problemas de seguridad que encuentran, aunque en esta etapa pueden ser obviados al ser una rama de cambio constante.
Checkpoint 3: Black box testing
Con nuestro feature analizado por las herramientas de código estático, este pasa a una rama desplegable llamada "develop", aquí un pipeline CI/CD lo despliega a un ambiente de desarrollo junto a todas sus dependencias y microservicios complementarios.
Este despliegue actúa como trigger para una serie de pruebas de tipo "black box", esto es, escanear externamente la aplicación en funcionamiento, entre los problemas identificados en esta etapa se encuentran:
- Respuestas inconsistentes.
- Problemas de configuración.
- Medidas de seguridad mal aplicadas.
- Leak de datos sensibles.
Como ejemplo incluimos a ZAProxy y Burp Suite las cuales permiten automatizar sus pruebas.
![](https://blog.fintech.works/content/images/2025/01/Image-Devops-January--6-.png)
Checkpoint 4: Dependency checks
Si finalmente se hace un cambio sobre la rama "main", se activan los pipelines dedicados a la misma, donde uno de los pasos incluye el chequeo de dependencias, elegimos el "OWASP Dependency check" al ser el sistema más popular y respaldado por las listas de la National Vulnerability Database (NVD).
Las razones por las cuales los chequeos de dependencias los ubicamos al final del proceso son:
- Las dependencias normalmente afectan no solo al feature a ser integrado sino a todos los módulos y proyectos del repositorio, más aún si son "monorepos".
- Si varias feature branches contribuyen a la versión final, un chequeo en la rama de producción permite revisar las dependencias resultantes tras combinar todos los cambios. Esto puede detectar vulnerabilidades que no aparecían en una rama individual.
- En industrias reguladas como las de pagos, realizar un chequeo al final puede servir como evidencia de un paso adicional de validación antes de desplegar a producción.
- El chequeo al final garantiza que la integración hasta ese punto no introdujo problemas, y cuando se tiene como requisito que la rama "main" esté libre de problemas de dependencia, se obliga a ejecutar un proceso dedicado para solucionarlos.
![](https://blog.fintech.works/content/images/2025/01/Screenshot-2025-01-28-at-3.31.43-PM.jpg)
Checkpoint 5: Continuous checks
Nuestro último checkpoint consiste en los checks continuos, que mantienen actualizadas nuestras librerías automáticamente y cuya ejecución no depende del ciclo de commits y pull-requests, esto es, se aplican automáticamente al detectarse versiones nuevas de las librerías que fueron configuradas en el watchlist.
![](https://blog.fintech.works/content/images/2025/01/Screenshot-2025-01-28-at-3.32.10-PM.jpg)
Para nuestro ejemplo nombramos a Dependabot, el cual ofrece 3 modos de funcionamiento:
- Dependabot alerts: solo informa sobre vulnerabilidades en las dependencias del repositorio.
- Dependabot security updates: crea automáticamente pull-requests para actualizar librerías con vulnerabilidades conocidas.
- Dependabot version updates: crea automáticamente pull-requests para mantener actualizadas las librerías, tengan o no vulnerabilidades conocidas.
Resumiendo el ciclo completo
Juntando todas las etapas y comparandola con el happy path, vemos como cada checkpoint añade capas adicionales de protección que no solo detectan problemas, sino que también mejoran la calidad del producto final:
1. White box lint: Actúa como la primera barrera, interceptando problemas directamente en el entorno de desarrollo antes de que lleguen al repositorio.
2. White box CI/CD: Valida los cambios en cada rama de feature mediante escaneos automáticos y correcciones sugeridas.
3. Black box testing: En un entorno desplegable, emula escenarios reales para identificar vulnerabilidades de configuración y seguridad externa.
4. Dependency checks: Cierra el ciclo verificando que las dependencias sean seguras antes de que los cambios lleguen a producción, reforzando la integridad del sistema.
5. Continuous checks: Se mantiene activo al margen del ciclo de desarrollo y ayuda a mantener actualizadas las librerías.
Este enfoque con "checkpoints" cubre escenarios reales, ofreciendo una línea de defensa fácil de entender y por ende fácil de implementar. Esto asegura que cada cambio pase no solo por validaciones funcionales, sino también por un estricto escrutinio de seguridad, lo que resulta esencial en industrias críticas como la de pagos.
Conclusión
Implementar checkpoints de seguridad en cada etapa del ciclo de desarrollo no solo mejora la calidad del software, sino que también fortalece la confianza en los sistemas que desarrollamos. Cada uno de los puntos de control descritos—desde los análisis de código en el IDE hasta los chequeos de dependencias finales—contribuye a garantizar que los estándares de seguridad no sean una barrera, sino un habilitador para un desarrollo ágil y seguro.
Al final del día, este enfoque no solo protege nuestros sistemas, sino que también refuerza nuestra reputación en la industria de pagos. La seguridad ya no es opcional; es un compromiso que todos los desarrolladores debemos asumir con responsabilidad y herramientas eficaces.