# 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](gitleaks.md) | El texto de los archivos y el historial de git | "¿Hay una credencial commiteada?" |
| [Trivy](trivy.md) | 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

```text
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.

```mermaid
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.
