Añadir scanners de SAST, dependencias, secretos e infraestructura a un pipeline lleva una tarde. El problema empieza la semana siguiente, cuando cada pull request muestra doscientos hallazgos, la mayoría de hace años, y el build falla por algo que el autor no tocó. Los desarrolladores aprenden a pasar de largo los comentarios, luego a relanzar hasta que se pone en verde, y después a pedir que la comprobación sea opcional.
Nuestra postura es simple: un escáner que se ignora da menos seguridad que un escáner más pequeño que se lee. El objetivo no es el máximo de hallazgos. Es los hallazgos correctos, ante la persona correcta, en el momento en que puede corregirlos.
Por qué los programas de escaneo se ahogan
Se repiten una y otra vez tres patrones:
- Historial en cada PR. Los hallazgos antiguos se reportan contra el trabajo nuevo, así que el autor paga una deuda que no creó.
- Todo bloquea. Los hallazgos medios y bajos rompen el build, así que la puerta no significa nada y se salta.
- Duplicados y código inalcanzable. La misma librería vulnerable se reporta por manifiesto, por imagen y por servicio, a menudo en rutas que nunca se ejecutan.
Ninguno de estos es un problema de herramientas. Son decisiones de política que nunca se tomaron.
Pon los hallazgos donde se arregla
Antes de afinar ningún scanner, decide dónde aterriza su salida. Un hallazgo en código modificado va como comentario en línea en la pull request, junto a la línea, redactado para que el autor pueda actuar sin abrir otra herramienta. Un hallazgo en código antiguo va al backlog del equipo propietario, agrupado por servicio. Un hallazgo sin propietario no va a ningún sitio hasta que lo tenga, lo cual es una señal para arreglar la propiedad en vez de abrir más tickets.
Deduplica antes de que nada llegue a una persona. Una librería vulnerable usada por diez servicios es una decisión sobre una actualización, no diez tickets. Prioriza la alcanzabilidad y la disponibilidad de corrección sobre la severidad bruta al ordenar el backlog, y dilo en el comentario para que los desarrolladores vean por qué un elemento está donde está.
Fija la línea base del backlog y hazte cargo de él
Haz una instantánea de lo que existe hoy y deja de reportarlo en las pull requests. Ese backlog no desaparece: se convierte en una lista con responsable y calendario, que se trabaja como cualquier otra deuda técnica. Mientras tanto, el código nuevo se juzga solo por lo que introduce.
# Gitleaks: record today's findings, then report only new ones
gitleaks git --report-path gitleaks-baseline.json
gitleaks git --baseline-path gitleaks-baseline.json
La línea base es una línea de salida, no una amnistía. Revísala, haz triage de lo peor en el primer mes y redúcela cada trimestre.
Escanea el diff, barre el resto
En las pull requests, reporta hallazgos solo en el código modificado. La mayoría de los escáneres open source lo soportan directamente:
# Semgrep: only findings not present on main
semgrep scan --config auto --baseline-commit origin/main --error
# Gitleaks: only commits in this branch
gitleaks git --log-opts="origin/main..HEAD"
Los escaneos del repositorio completo siguen ejecutándose, cada noche o cada semana, y alimentan el backlog en lugar de una pull request. Esa separación importa. La pull request es una conversación con un desarrollador sobre su cambio. El escaneo programado es una conversación con un equipo sobre su servicio.
Bloquea solo con un conjunto reducido
Acordad por escrito qué bloquea un merge. Mantén la lista lo bastante corta como para que cada bloqueo merezca parar:
| Scanner | Bloquea el merge | Solo informes |
|---|---|---|
| Secrets | Cualquier secreto nuevo verificado o de alta confianza | Fixtures de test, coincidencias de baja entropía |
| SAST | Reglas de alta confianza de inyección, autenticación o cripto | Reglas de estilo y de baja confianza |
| SCA | Crítica o alta, con corrección disponible | Sin corregir, baja, solo dev |
| IaC | Almacenamiento público, puertos de administración abiertos, IAM con comodines | Comprobaciones de etiquetado e higiene |
trivy fs --scanners vuln --severity HIGH,CRITICAL --ignore-unfixed --exit-code 1 .
trivy config --severity HIGH,CRITICAL --exit-code 1 ./infra
Cada supresión necesita un motivo y una fecha de caducidad en el código, para que sea revisable. Una supresión sin motivo es solo un bypass más discreto.
Qué haríamos
- Pon todos los escáneres en modo solo informe durante dos semanas y mide el volumen por pull request.
- Escribe la tabla de gates de arriba para tu organización y acuérdala con los responsables de ingeniería, no solo con seguridad.
- Fija una línea base de los hallazgos existentes, asigna el backlog de cada repositorio a su equipo propietario y define un objetivo trimestral.
- Pasa los escaneos de pull requests a solo diff y luego activa el bloqueo para las reglas acordadas.
- Revisa cada mes la tasa de falsos positivos y elimina las reglas a las que nadie hace caso.
La medida del éxito no es el número de hallazgos. Es si los desarrolladores leen el comentario, corrigen el problema y hacen merge, sin pedirle a seguridad que lo haga desaparecer.