Files
devops 4aed9f6c5c feat(devsecops): agregar Semgrep SAST en modo auditoría al pipeline
Escanea workloads/ecommerce con rulesets públicos del registro de
Semgrep (p/typescript, p/react, p/nextjs, p/security-audit) vía la
imagen oficial semgrep/semgrep:1.173.0. Sin --error a propósito: siempre
termina en exit 0, solo reporta — primera vuelta para revisar juntos qué
reglas deberían pasar a bloquear más adelante.

Validado contra el código real: 0 hallazgos en 91 reglas / 72 archivos.
Documenta la herramienta en docs/devsecops/sast.md, incluyendo la
diferencia con gitleaks/trivy y qué significa (y qué no) un scan limpio.
2026-08-14 21:07:05 -05:00

5.3 KiB

SAST (Semgrep) — análisis estático de código

!!! info "Qué problema resuelve" SAST significa Static Application Security Testing: analizar el código fuente en busca de patrones de programación inseguros, sin ejecutar la aplicación. Semgrep lee cada archivo .ts/.tsx y lo compara contra un catálogo de reglas — cada regla describe una forma de escribir código que suele terminar en una vulnerabilidad conocida (inyección, XSS, uso inseguro de una API, etc.).

En qué se diferencia de Gitleaks y Trivy

Las tres herramientas ya integradas a este pipeline analizan cosas completamente distintas — vale la pena tenerlo claro porque a primera vista "escaneo de seguridad" suena como una sola categoría:

Herramienta Qué mira Pregunta que responde
Gitleaks El texto de los archivos y el historial de git "¿Hay una credencial commiteada?"
Trivy Paquetes instalados (imagen) y configuración (YAML) "¿Alguna dependencia tiene una CVE conocida? ¿El manifiesto de Kubernetes es inseguro?"
Semgrep (SAST) La lógica del código que escribimos nosotros "¿Esta función, tal como está escrita, abre una vulnerabilidad?"

Ninguna de las tres reemplaza a las otras. Una dependencia puede estar 100% al día (sin CVEs, Trivy contento) y aun así el código propio puede construir una URL con un string sin sanitizar y quedar abierto a SSRF — eso solo lo detecta un análisis de la lógica del código, que es exactamente lo que hace Semgrep.

Qué tipo de bugs detecta (ejemplos genéricos)

Los rulesets usados (p/typescript, p/react, p/nextjs, p/security-audit) cubren, entre otras cosas:

  • Inyección: construir queries, comandos de shell o URLs concatenando strings con datos que vienen del usuario, en vez de usar una API parametrizada.
  • XSS en React/Next.js: usar dangerouslySetInnerHTML con contenido que no pasó por un sanitizador.
  • SSRF: hacer un fetch()/request server-side hacia una URL que construye el propio usuario, sin validar el host de destino.
  • Criptografía insegura: algoritmos de hash débiles (md5, sha1) usados para contraseñas o tokens, en vez de un KDF diseñado para eso.
  • eval / new Function() sobre datos no confiables.
  • ReDoS: expresiones regulares con backtracking exponencial que un input malicioso puede usar para colgar el proceso.
  • Prototype pollution: merges/asignaciones dinámicas de objetos que permiten sobrescribir __proto__.

Resultado real de esta primera corrida

Scanning 72 files tracked by git with 292 Code rules:
  ts    87 rules   39 files
  js    81 rules    1 file
  json   1 rule     6 files

Ran 91 rules on 72 files: 0 findings.

workloads/ecommerce salió limpio con estos rulesets: 0 hallazgos.

!!! warning "0 hallazgos no significa 'código perfecto'" Significa que ningún patrón conocido de estos 91 rules hizo match — no es una garantía de ausencia de bugs, solo de ausencia de estos patrones específicos. SAST tiene falsos negativos por naturaleza (un bug de lógica de negocio nuevo, específico de esta app, no está en ningún ruleset genérico). El valor de correr esto en cada build no es "una vez limpio, siempre limpio" — es que si alguien introduce a futuro uno de estos patrones conocidos (por ejemplo, un dangerouslySetInnerHTML sin sanitizar en un componente nuevo), el pipeline lo va a marcar en ese mismo push.

Por qué modo auditoría (no bloquea) en esta primera integración

El step corre sin la flag --error a propósito — Semgrep siempre termina con exit 0, reporta lo que encuentra pero nunca frena el pipeline. Es la primera vez que esta herramienta corre sobre el repo: la idea es revisar juntos qué reglas de los 91 activos generan ruido (falsos positivos específicos de este código) antes de decidir cuáles deberían pasar a bloquear.

flowchart LR
    A[Semgrep scan] --> B{hallazgos?}
    B -- "sí" --> C["se reportan en el log<br/>+ artifact JSON"]
    B -- "no" --> C
    C --> D["✅ pipeline sigue<br/>(exit 0 siempre)"]

Una vez que se decida qué reglas son suficientemente confiables para esta app, el paso natural es agregar --error con un subconjunto de reglas (no las 91 completas) usando --config más específico o .semgrepignore / reglas individuales marcadas como bloqueantes — todavía no se hizo ese recorte.

Los rulesets elegidos

  • p/typescript — patrones generales de TypeScript/JavaScript.
  • p/react — específico de componentes React (hooks mal usados, XSS vía props/render, etc.).
  • p/nextjs — patrones propios del framework (App Router, API routes, middlewares).
  • p/security-audit — catálogo transversal de seguridad (inyección, criptografía débil, deserialización insegura) sin atarse a un framework específico.

Son rulesets públicos y gratuitos del registro de Semgrep — no requieren cuenta ni login (semgrep login solo hace falta para acceder a reglas adicionales de pago, que no se usan acá).

Dónde ver el resultado

El JSON completo (semgrep-report.json) se publica como artifact del pipeline (semgrep-report) en cada corrida, tenga o no hallazgos — mismo patrón que Gitleaks y Trivy.