Auditoría con un agente LLM

Por: Artiko
owaspseguridadsecure-by-defaultauditoriallmagente

Auditoría con un agente LLM

Los capítulos anteriores explican qué significa Secure by Default y cómo se ve cada control en la práctica. Este capítulo cierra el ciclo: convierte todo ese checklist en un briefing ejecutable que le pasas a un agente LLM con acceso a tu repositorio para que audite la aplicación real, punto por punto, con evidencia concreta.

La idea no es que el agente opine “se ve seguro”. Es que recorra el checklist consolidado, busque en el código la evidencia de cada control, y emita un veredicto CUMPLE / PARCIAL / NO CUMPLE con el archivo y la línea que lo respaldan.

Cómo usar este capítulo

  1. Abre una sesión limpia de tu agente (Claude Code, Cursor, Copilot, etc.) en la raíz del proyecto que quieres auditar.
  2. Copia el bloque “Briefing para el agente” completo y pégalo como primer mensaje.
  3. El agente ejecuta las cuatro fases (reconocimiento → diagnóstico → plan → reporte) y devuelve un informe estructurado.
  4. Regla de oro: el agente audita y reporta, pero no modifica nada sin que apruebes primero el plan de remediación.
flowchart LR
    A[Reconocimiento] --> B[Diagnóstico<br/>por control]
    B --> C[Plan priorizado]
    C --> D[Reporte con<br/>evidencia]
    D -.aprobación.-> E[Remediación]

Escala de evaluación

El agente debe usar una escala de tres estados, nunca respuestas binarias sin matiz:

EstadoSignificado
CUMPLEEl control está implementado y hay evidencia verificable en el código o la configuración
PARCIALExiste una mitigación pero es incompleta, inconsistente o depende de configuración manual
NO CUMPLEEl control está ausente, o hay evidencia activa de la vulnerabilidad
N/AEl control no aplica a este stack (debe justificarse por qué)

Cada hallazgo lleva además una severidad: CRÍTICO (exposición explotable ya presente) · ALTO · MEDIO · BAJO.

Briefing para el agente

Copia todo lo que sigue en este bloque y pégalo a tu agente.

# MISIÓN: Auditoría Secure by Default

Eres un auditor de seguridad de aplicaciones. Tu misión es determinar si ESTA
aplicación cumple el principio "Secure by Default" de OWASP: que el estado inicial
del sistema —tal como sale de un build, un `docker build` o un `terraform apply`
sea ya el más seguro posible, sin configuración manual adicional.

REGLA DE ORO: NO modifiques ningún archivo. Solo lees, diagnosticas y reportas.
Toda remediación se propone como plan y espera mi aprobación explícita.

## FASE 1 — Reconocimiento

Lee, sin implementar nada, para entender el stack y la superficie de exposición:

- README / documentación de arranque y despliegue
- Manifiesto de dependencias (package.json, go.mod, Cargo.toml, pyproject.toml, pom.xml)
- Dockerfile, docker-compose.yml, .dockerignore
- Infraestructura como código (Terraform, Pulumi, CloudFormation, k8s manifests, Helm)
- Config del servidor web / framework (headers, métodos HTTP, static file serving)
- Archivos de entorno y de configuración (.env*, config/, settings)
- .gitignore y qué NO está ignorado que debería estarlo
- Pipeline de CI/CD (.github/workflows, .gitlab-ci.yml, etc.)

Resume en 5-8 líneas: lenguaje, framework, cómo se despliega, si es servicio
público o interno, y qué backing services usa.

## FASE 2 — Diagnóstico por control

Evalúa CADA ítem del checklist. Para cada uno responde con este formato exacto:

  - **[ID] Control**: CUMPLE | PARCIAL | NO CUMPLE | N/A — severidad
    - Evidencia: `ruta/archivo.ext:línea` (cita el fragmento relevante)
    - Nota: por qué ese veredicto

### Configuración de sistema (SC)
- [SC1] Procesos y cuentas de servicio corren con MÍNIMO PRIVILEGIO
      (Dockerfile con USER no-root; sin sudo; roles IaC acotados; no correr como root)
- [SC2] El código de infraestructura (IaC) también sigue mínimo privilegio
      (políticas IAM sin `*`, sin `AdministratorAccess`, sin `0.0.0.0/0` innecesario)
- [SC3] Se eliminó funcionalidad innecesaria: archivos demo, cuentas default,
      software y endpoints de ejemplo que no van a producción
- [SC4] No queda código de prueba / debug / mocks activables en producción
      (rutas /debug, flags de test, `DEBUG=true` por defecto)
- [SC5] La configuración de seguridad es legible por humanos y auditable
- [SC6] Entornos dev y prod están AISLADOS, con acceso restringido
- [SC7] Existe control de cambios que registra modificaciones (IaC versionado, CI)
- [SC8] Páginas sensibles NO indexables (robots.txt, X-Robots-Tag, meta robots)
- [SC9] Métodos HTTP innecesarios deshabilitados (PUT, DELETE, TRACE, WebDAV sin uso)
- [SC10] Los headers HTTP NO revelan SO, versión de servidor ni framework
      (sin `X-Powered-By`, sin `Server: nginx/1.x`, sin `X-AspNet-Version`)
- [SC11] `.git`, `.svn` y metadata de VCS NO accesibles desde la web
- [SC12] SIN contraseñas, secretos ni claves en texto plano en código,
      artefactos, historial de git ni bundle del cliente
- [SC13] Documentación interna y APIs internas NO accesibles públicamente

### Gestión de archivos (FM)
- [FM1] Listado de directorios DESACTIVADO
- [FM2] Archivos subidos por usuarios fuera del contexto web de la app
- [FM3] Directorios de carga SIN privilegios de ejecución
- [FM4] Archivos y recursos de la app en SOLO LECTURA en producción
- [FM5] Acceso a archivos vía listas de PERMITIDOS, no de bloqueados

### Seguridad en la nube (CS)
- [CS1] Gestión de acceso Just-In-Time (JIT), sin credenciales de larga vida
- [CS2] Imágenes de contenedor escaneadas y desde un registro privado confiable
      (base image con tag fijo/digest, no `latest`; escaneo en CI)
- [CS3] Infraestructura aprovisionada mediante Infrastructure as Code
- [CS4] Políticas de seguridad aplicadas mediante Policy as Code
      (OPA, Sentinel, Kyverno, tfsec/checkov en CI)

Si un control no aplica al stack, márcalo N/A y explica por qué (ej: "no hay
uploads de usuario", "es CLI, no expone HTTP").

## FASE 3 — Plan priorizado

Ordena SOLO los hallazgos PARCIAL y NO CUMPLE en un plan accionable:

  ### CRÍTICO (exposición explotable ya presente)
  - [ ] [ID] Descripción — archivo — remediación en una línea
  ### ALTO
  - [ ] ...
  ### MEDIO / BAJO
  - [ ] ...

Orden de ataque sugerido: secretos expuestos y `.git` público primero, luego
mínimo privilegio, luego headers/métodos, luego hardening de nube.

## FASE 4 — Reporte

Entrega:
1. Tabla resumen: control | estado | severidad
2. Score: nº de CUMPLE / total aplicable (excluye N/A)
3. Los 3 hallazgos más urgentes con su evidencia
4. El plan priorizado de la Fase 3

Espera mi aprobación antes de tocar cualquier archivo.

Qué evidencia debe buscar el agente (guía rápida)

Para que el agente no se quede en lo superficial, estas son las señales concretas que delatan cada tipo de incumplimiento. Sirven también como criterio para revisar su reporte:

ControlDónde mirarSeñal de NO CUMPLE
Mínimo privilegio (SC1)DockerfileAusencia de USER, o USER root
IaC privilegiado (SC2)Terraform / IAM"Action": "*", AdministratorAccess, 0.0.0.0/0 en SG
Debug en prod (SC4)config, envDEBUG=True por defecto, NODE_ENV sin fijar
Headers reveladores (SC10)server/middlewareX-Powered-By, Server: nginx/1.25.3, stack traces al cliente
.git expuesto (SC11)server static configwebroot = raíz del repo, sin bloqueo de /.git
Secretos en claro (SC12)todo el árbol + git logclaves API, password=, tokens; .env versionado
Directory listing (FM1)nginx/apache/frameworkautoindex on, Options +Indexes
Uploads ejecutables (FM3)dir de uploadsdentro del webroot y sin X-Content-Type-Options/exec off
Imagen no confiable (CS2)Dockerfile, CIFROM node:latest, sin escaneo (trivy/grype) en pipeline

Detectar secretos requiere revisar el historial de git, no solo el árbol actual. Un secreto borrado en el último commit sigue vivo en git log -p. Pídele al agente que lo verifique explícitamente (git log, o herramientas como gitleaks/trufflehog si están disponibles).

Formato de reporte esperado

El resultado del agente debería verse así (ejemplo abreviado):

## Auditoría Secure by Default — mi-app

**Score: 11 / 17 controles aplicables**

| ID | Control | Estado | Severidad |
|----|---------|--------|-----------|
| SC1 | Mínimo privilegio | NO CUMPLE | CRÍTICO |
| SC10 | Headers no reveladores | PARCIAL | MEDIO |
| SC12 | Sin secretos en claro | NO CUMPLE | CRÍTICO |
| CS2 | Imágenes confiables | PARCIAL | ALTO |
| ... | ... | ... | ... |

### Hallazgos más urgentes
1. **SC12**`docker-compose.yml:14` define `POSTGRES_PASSWORD=admin123` en claro.
2. **SC1**`Dockerfile` no declara `USER`; el contenedor corre como root.
3. **SC11** — El webroot sirve la raíz del repo; `/.git/config` es accesible.

Automatizar la auditoría en CI

Un agente da profundidad, pero varios de estos controles se prestan a gates automáticos que corren en cada Pull Request, sin esperar una auditoría manual:

La combinación ideal: CI atrapa las regresiones conocidas en cada commit, y la auditoría con agente descubre lo que ningún linter tiene regla (aislamiento de entornos, control de cambios, funcionalidad de prueba olvidada).

Cierre

Este capítulo transforma el checklist de un documento que se revisa “una vez al año” en un procedimiento repetible: un briefing que cualquier miembro del equipo puede pegar en su agente para obtener, en minutos, un diagnóstico evidenciado del estado real de la aplicación frente a Secure by Default. El agente no reemplaza el criterio humano —especialmente en severidad y contexto de negocio— pero elimina la parte tediosa: recorrer el árbol buscando la evidencia de cada control.

Recursos