SAST (Semgrep) — análisis estático de código¶
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
dangerouslySetInnerHTMLcon 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.
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.