|

Hackearon Trivy en GitHub Actions: 75 Tags Comprometidos

Actualizado el 05/05/2026 — Este artículo fue actualizado con información reciente y configuraciones actualizadas para Trivy en GitHub Actions.

En 30 segundos

  • Trivy es un escáner de vulnerabilidades de código abierto que detecta CVEs en dependencias, imágenes Docker, y secretos expuestos en tu repositorio
  • Integrado en GitHub Actions, corre automáticamente en cada push, tag o pull request sin necesidad de infraestructura adicional
  • El escáner de secretos detecta credenciales, API keys y tokens antes de que lleguen a producción
  • Funciona en múltiples lenguajes: Java, Python, JavaScript, Go, Rust, C# y otros, identificando vulnerabilidades específicas del lenguaje
  • Los resultados aparecen directamente en el tab de “Security” de GitHub, bloqueando merges si configurás status checks

Trivy: tu guardaespaldas de seguridad en CI/CD

Cada push a un repositorio es una oportunidad para que vulnerabilidades se cuelan. Una dependencia con una CVE sin parchear, un secreto hardcodeado accidentalmente, una configuración permisiva en una imagen Docker. La mayoría de los equipos no se enterar hasta que explota en producción. Trivy cambia eso corriendo automáticamente en tu pipeline y vetando cambios inseguros antes de que lleguen al main.

Es una herramienta de seguridad estilo “automatiza o muere”. No requiere servidor, no requiere tokens especiales (aunque podés configurar un token de GitHub para aumentar rate limits), y se integra en 5 minutos con GitHub Actions. Detecta vulnerabilidades en dependencias, imágenes, y secretos. Cuando algo da positivo, aparece en el security tab de tu repositorio y podés bloquear el merge automáticamente.

Cómo funciona Trivy: escaneo en múltiples capas

Trivy no es un escáner genérico. Es muy específico por lenguaje. Cuando analizás un repositorio Java, Trivy inspecciona tus dependencias Maven (pom.xml) y Gradle (build.gradle), les asigna CVE IDs, y te dice exactamente cuál es vulnerable, en qué versión, y cuál es el fix. Lo mismo con Python (requirements.txt, Pipfile), Node.js (package.json, package-lock.json), Go (go.mod), C# (.csproj), Rust (Cargo.lock). No te da falsos positivos viendo dependencias donde no hay.

El escaneo de secretos es el motor extra que la mayoría de los equipos no saben que tienen. Trivy busca patrones conocidos: AWS keys, GitHub tokens, credenciales de bases de datos, API keys privadas. No es perfecto (puede tener falsos positivos), pero atrapa el 95% de los secretos que alguien commiteó por accidente. Y eso es suficiente para evitar que esos secretos lleguen a GitHub público.

Lo fundamental: Trivy corre en segundos, no en minutos. Analizar un repositorio de 500 dependencias toma típicamente 10-20 segundos. Escanear una imagen Docker más grande puede tomar más tiempo, pero sigue siendo rápido. Eso significa que no ralentiza tu pipeline.

Integración en GitHub Actions: setup básico en 3 pasos

Agregás el action a tu workflow y listo. GitHub tiene el action oficial (aquaproject/trivy-action) que es mantenido activamente. Acá te muestro la configuración mínima que funciona:

name: Security Scan with Trivy
on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  trivy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Run Trivy scan
        uses: aquaproject/trivy-action@master
        with:
          scan-type: 'fs'
          scan-ref: '.'
          format: 'sarif'
          output: 'trivy-results.sarif'
      
      - name: Upload to GitHub Security tab
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: 'trivy-results.sarif'

Esto corre Trivy en modo “filesystem scan” (analiza tu repo), genera un reporte SARIF (formato que GitHub entiende), y lo sube al tab de Security. Los resultados aparecen dentro de GitHub automáticamente, sin que tengas que hacer nada más.

Paso 1: agregar el escáner de secretos

El escáner de vulnerabilidades en dependencias es el default. Si querés que Trivy detecte secretos también, agregás una línea:

- name: Run Trivy scan
        uses: aquaproject/trivy-action@master
        with:
          scan-type: 'fs'
          scan-ref: '.'
          format: 'sarif'
          output: 'trivy-results.sarif'
          severity: 'MEDIUM,HIGH,CRITICAL'
          scanners: 'vuln,secret,config'

El parámetro `scanners` indica qué tipos de problemas buscar. “vuln” = vulnerabilidades, “secret” = secretos hardcodeados, “config” = misconfigurations (permisos excesivos en archivos, configuraciones inseguras, etc.). Con eso cubrís el 99% de los problemas de seguridad en CI/CD.

Paso 2: bloquear merges si hay vulnerabilidades críticas

En GitHub, vas a Settings → Branches → “Add rule” → seleccionás main, habilitás “Require status checks to pass”, y agregás “Trivy” a la lista. Si Trivy encuentra una vulnerabilidad CRITICAL, el merge se bloquea automáticamente hasta que alguien la resuelva.

Si no querés bloquear por MEDIUM (a veces tenés 100 mediums antiguos sin resolver), podés configurar el severity mínimo en el action:

        severity: 'HIGH,CRITICAL'

De esa forma ignoras los MEDIUM y solo bloqueás si hay HIGH o CRITICAL.

Paso 3: escanear imágenes Docker

Si estás deployando Docker, probablemente quieras escanear la imagen final antes de pushearla a tu registry. Trivy puede hacer eso en el mismo workflow:

      - name: Build Docker image
        run: docker build -t myapp:latest .
      
      - name: Scan Docker image with Trivy
        uses: aquaproject/trivy-action@master
        with:
          input: 'myapp:latest'
          format: 'sarif'
          output: 'trivy-docker-results.sarif'

Eso escanea la imagen Docker completa (SO + dependencias + todo) y te reporta qué CVEs encontró. Crucial si estás usando una imagen base antigua.

Caso real: detectar la vulnerabilidad antes de que explote

Escenario: trabajás en un proyecto Java y sin saber tenés una versión desactualizada de Log4j que es vulnerable al ataque Log4Shell (CVE-2021-44228). Es crítica. Tu aplicación en producción está expuesta a RCE (ejecución remota de código).

Sin Trivy: alguien hace un push, se mergeá a main, deployeás, y te enteras recién cuando ves anomalías en logs o cuando alguien te reporta. Tardás horas en darte cuenta.

Con Trivy: hacés un pull request, GitHub Actions dispara el workflow, Trivy escanea tu pom.xml, encuentra que log4j 2.14.1 tiene CVE-2021-44228 con score CVSS 10.0 (máximo crítico), y rechaza el merge. Vos recibís notificación, updateás la dependencia a 2.17.0, pusheas nuevamente, Trivy vuelve a pasar, y recién ahí podés mergear. El ciclo completo: 5 minutos. Sin Trivy, descubrís el problema cuando estás en pijamas a las 3am.

Trivy y null safety en Java: complemento natural

Si estás usando Java y le importa la calidad, probablemente estés usando nullability annotations (@NonNull, @Nullable) o frameworks como Kotlin que tienen null safety built-in. Trivy no verifica eso (no es un linter estático), pero lo complementa.

¿Por qué? Porque una NullPointerException causada por null safety débil es un bug interno tuyo. Pero una NullPointerException causada por una dependencia vulnerable es un bug que te heredaron. Trivy atrapa lo segundo. Para lo primero, usás SpotBugs, Checker Framework, o simplemente escribís código defesivo.

En la práctica: Trivy te asegura que tus dependencias son seguras. Los tests y linters estáticos te aseguran que tu código es correcto (incluyendo null handling). Juntos, no dejas nada al azar.

Problemas que atrapa Trivy (y que la mayoría de los equipos desconoce)

Más allá de CVEs obvias, Trivy atrapa cosas sneaky que nadie piensa:

Secretos heredados en el histórico

Alguien commiteó un .env con API keys hace 2 años. Lo sacaron en el siguiente commit, pero la historia de Git la mantiene. Si tu repo es público, esa API key está expuesta. Trivy escanea el histórico entero (si le pasás `–git-commit`) y encuentra esos secretos. Entonces rotás la key, y nadie se enteró que estuvo expuesta.

Dependencias transitivas vulnerables

Instalás biblioteca-A, que depende de biblioteca-B v1.0, que depende de biblioteca-C v0.5. Vos solo especificaste biblioteca-A. Trivy descubre que biblioteca-C v0.5 tiene una CVE y te lo reporta. Sin Trivy no te enteras porque tu árbol de dependencias es implícito.

Configuraciones inseguras en CI/CD

En un Dockerfile tenés `RUN npm install` sin verificar integridad de paquetes. En tu workflow de Actions tenés un job que corre cualquier script sin sandbox. Trivy con `scanners: ‘config’` atrapa esos problemas de infraestructura.

Limitaciones: qué Trivy no puede hacer

Trivy es potente, pero no es omnisciente. Hay categorías enteras de vulnerabilidades que no detecta:

  • Vulnerabilidades de lógica en tu código. Si escribiste SQL injection sin querer, Trivy no lo ve. Solo ve si una biblioteca SQL tiene CVE.
  • Problemas de arquitectura. Si tu app no tiene rate limiting y es vulnerable a DDoS, Trivy no te lo dice. Eso es un problema de diseño, no de vulnerabilidades conocidas.
  • Secretos en variables de entorno durante runtime. Si alguien pone un secreto en una variable de GitHub Actions secret, eso no se expone (está cifrado), pero tampoco Trivy lo ve como un problema.
  • Vulnerabilidades zero-day. Si sale una CVE hoy, la base de datos de Trivy se actualiza al día siguiente, pero hasta ahí estás en el aire.

Mejores prácticas: cómo sacarle el máximo a Trivy

1. Ejecutá Trivy en PRs, no solo en main

Configurá el workflow para que corra en `pull_request` además de `push`. Eso significa que antes de que alguien merge algo, ya sabés si hay CVEs. Es un breakpoint automático.

2. No ignorés todos los MEDIUM

Es tentador poner `severity: ‘CRITICAL’` y dormir tranquilo. Pero MEDIUM vulnerabilities aún son problemas. Lo correcto es revisarlas, evaluarlas según tu contexto (¿usás esa función vulnerable?), y si no son relevantes, marcalas como “false positive” en el reporte. No las ignores sistemáticamente.

3. Mantené Trivy actualizado

La base de datos de CVEs de Trivy se actualiza constantemente. Si tu workflow usa una versión viejita, te perderás vulnerabilidades nuevas. Configurá tu action para que use `@master` o `@latest`, no una versión fija.

4. Combiná con otras herramientas

Trivy es excelente para vulnerabilidades y secretos. Pero agregale un linter estático (ESLint, Pylint, RuboCop) para problemas de código, un test framework para funcionalidad, y SAST tools (SonarQube, Semgrep) para patrones inseguros. No es uno u otro, es todos juntos.

5. Reportá resultados a tu equipo

Los resultados en GitHub Security tab están bien, pero si querés tracking centralizado, podés exportar a CSV y feedar un tablero. O si usás Slack, agregá notificaciones cuando Trivy encuentra algo CRITICAL. Mantené a todos informados.

Comparación: Trivy vs. otras herramientas de escaneo

HerramientaPrecioLenguajesEscaneo de secretosMejor para
TrivyGratis + opcional cloudTodosEquipos que quieren escaneo rápido y automatizado en CI/CD
SnykFreemium (limitado)TodosEquipos que quieren dashboard + remediation suggestions inteligentes
Dependabot (GitHub nativo)GratisLenguajes selectosNoEquipos que usan GitHub y solo necesitan alertas de dependencias
WhiteSource/MendPagoTodosEmpresas grandes con requirements de compliance strict
OWASP Dependency-CheckGratisTodosNoEquipos con poco presupuesto, sin interfaz web

Trivy gana en velocidad, gratuidad, y facilidad de integración. Snyk gana en UX y sugerencias inteligentes. Dependabot es más simple si no querés secretos. No hay mejor o peor, depende de tu escala y presupuesto.

Casos de vulnerabilidades reales que Trivy hubiera atrapado

En 2024, múltiples incidentes hubieran sido evitables con Trivy:

  • XZ Utils backdoor (CVE-2024-3156): Una dependencia muy profunda fue comprometida. Trivy lo detectaría en el escaneo transitivo.
  • Secretos en repositorios públicos: Decenas de AWS keys y GitHub tokens expostos cada mes. Trivy atrapa eso automáticamente si habilitás `scanners: ‘secret’`.
  • Imágenes Docker viejas: Equipos que no actualizan su imagen base en 2 años acumulan 100+ CVEs. Trivy scanning de imágenes lo detectaría en el pipeline.

Próximos pasos: implementá Trivy hoy

Si todavía no tenés scanning automático, la mejor hora para empezar fue hace 6 meses. La segunda mejor hora es ahora. Trivy es gratis, es rápido, y se integra en minutos. No hay excusa.

Copiate el workflow de arriba, adaptálo a tu contexto (si usás Docker, agregá el escaneo de imágenes; si usás Terraform, agregá `scanners: ‘config’`), pusheá a una rama, y dejá que GitHub Actions lo ejecute. En 5 minutos sabés cuáles vulnerabilidades tenés. De ahí, es un problema técnico normal: actualizar dependencias, rotación de secretos, parches aplicados.

Tu equipo estará más seguro. Tu deploy estará más seguro. Y vos dormirás mejor sabiendo que las CVEs no llegan a producción sin que alguien se entere.

¿Trivy ralentiza tu pipeline de GitHub Actions?

No. Trivy analiza repositorios completos en 10-20 segundos típicamente, por lo que no suma latencia significativa al workflow. Aunque escanear imágenes Docker puede tomar más tiempo, sigue siendo rápido y no bloquea el ciclo de desarrollo.

¿Qué tan precisión tiene el detector de secretos de Trivy?

Trivy atrapa alrededor del 95% de los secretos reales (AWS keys, tokens de GitHub, credenciales de BD). Puede haber falsos positivos ocasionales, pero en la práctica evita que la mayoría de las credenciales accidentales lleguen a GitHub.

¿Trivy detecta vulnerabilidades en dependencias transitivas?

Sí. Trivy escanea el árbol completo de dependencias, incluyendo librerías indirectas que instalaste sin saber. Si una dependencia que usas depende de otra vulnerable, Trivy te lo reporta inmediatamente.

¿Puedo escanear solo los archivos cambiados en un pull request con Trivy?

Trivy no tiene una opción nativa para escanear solo cambios diferenciales, pero podés combinar el action con un paso de git diff para pasar archivos específicos al escaneo. Lo recomendado es escanear todo el repositorio, porque las dependencias transitivas pueden estar en archivos no modificados.

¿Cómo excluyo directorios o archivos del escaneo de Trivy?

Usá el flag `–skip-dirs` o `–skip-files` en los parámetros del action, o creá un archivo `.trivyignore` en la raíz del repo para ignorar vulnerabilidades específicas por ID.

Te puede interesar...