# OpenWAF Egress

> Una pasarela de salida de confianza cero para agentes de IA que revisa cada petición e inyecta la clave del proveedor, en tu equipo o alojada en OpenWAF Cloud.

OpenWAF Egress es una pasarela entre tus agentes de IA y los proveedores de modelos a los que llaman. El agente tiene un token de marcador (`OWE_TOKEN_…`) en lugar de la clave del proveedor. La pasarela revisa cada petición y solo entonces lee la clave real de OpenBao o HashiCorp Vault, la pone en la petición de salida y la reenvía, sin romper el streaming.

Es código abierto con licencia Apache 2.0: [github.com/openwaf-dev/egress](https://github.com/openwaf-dev/egress). La imagen `ghcr.io/openwaf-dev/egress` se publica para linux/amd64 y linux/arm64, y cada versión trae además binarios para Linux y macOS con sus `SHA256SUMS`.

## En tu equipo o alojada

La misma pasarela funciona de dos formas:

- **En tu equipo:** arrancas el contenedor junto a tus agentes, con tu propio fichero de configuración y tu propio OpenBao o Vault. El [inicio rápido](https://developers.openwaf.dev/es/egress/quickstart/) y las páginas que lo siguen describen este modo.
- **Alojada en OpenWAF Cloud:** tus agentes llaman a `https://egress.openwaf.dev`; gestionas los agentes, las claves de los proveedores y las peticiones bloqueadas desde el panel, la API o el servidor MCP, y OpenWAF guarda las claves. Está en acceso anticipado. Mira [empezar con el egress alojado](https://developers.openwaf.dev/es/egress/cloud/get-started/).

## Por qué una pasarela

Un agente que tiene la clave de un proveedor puede filtrarla: por una inyección de prompt que le pide imprimir su entorno, por una llamada a una herramienta que saca datos o por una dependencia comprometida en su contenedor. Con OpenWAF Egress la clave nunca entra en el proceso del agente. Un marcador robado solo sirve a través de la pasarela, para los destinos que ese agente tiene permitidos y para peticiones que pasen las comprobaciones.

## El recorrido de una petición

El agente sigue con su SDK. Solo cambian la URL base y la clave:

```text
baseURL = http://127.0.0.1:8070/v1/agent/<agente>/proxy/<destino>
apiKey  = OWE_TOKEN_…
```

Cada petición pasa por cinco pasos, en este orden. El primero que falla responde con un error y no se envía nada al proveedor.

| Paso | Comprobación | Si falla |
|---|---|---|
| 1 | Token del agente: `Authorization: Bearer <marcador>` tiene que coincidir con el `token` del agente | `401` |
| 2 | Destinos permitidos: el destino tiene que estar en los `allowed_targets` del agente | `403 egress_blocked` |
| 3 | SSRF: el `host` del destino solo puede resolver a direcciones públicas | `403 ssrf_blocked` |
| 4 | Inspección del cuerpo: detectores de inyección de prompt (`enforce_injection`) y patrones de fuga de datos (`block_dlp`) | `403 injection_detected`, `403 data_leak_blocked`, `413 body_too_large` |
| 5 | Clave desde OpenBao: se lee de KV v2 y se pone en la `auth_header` del destino | `502 credential_resolution_failed` |

Después la pasarela reenvía la petición a la `base_url` del destino y devuelve la respuesta en streaming. Nunca sigue una redirección del proveedor: el `3xx` vuelve al agente tal cual.

## Rutas

- `/v1/agent/<agente>/proxy/<destino>/<ruta>`: el agente va en la URL. Es la ruta que conviene usar.
- `/v1/proxy/<destino>/<ruta>`: el agente es aquel cuyo `token` coincide con la cabecera `Authorization`, o el que nombra la cabecera `X-OpenWAF-Agent` (la pasarela la quita antes de reenviar).
- `/health` y `/v1/health`: estado de la pasarela y de su conexión con OpenBao, en JSON.

`<ruta>` y la cadena de consulta se añaden a la `base_url` del destino. Con la `base_url` `https://openrouter.ai/api/v1`, una petición a `/v1/agent/my-support-agent/proxy/openrouter/chat/completions` va a `https://openrouter.ai/api/v1/chat/completions`.

## Qué detecta

- **Inyección de prompt**: 27 detectores deterministas en inglés y español, 21 de patrones y 6 de texto oculto o codificado. Sin llamar a ningún modelo. La lista completa está en la [página del producto](https://openwaf.dev/es/egress/#detectors).
- **Fugas de datos**: números de tarjeta válidos por Luhn, claves privadas PEM, identificadores de clave de AWS, claves `sk-` al estilo de OpenAI y tokens de GitHub.
- **SSRF**: loopback, RFC 1918, CGNAT, enlace local (169.254.169.254 incluida), multidifusión, rangos reservados y sus equivalentes IPv6.

La detección es por patrones: frena formas conocidas de inyección y de exfiltración, no demuestra que una petición sea segura. El [modelo de seguridad](https://developers.openwaf.dev/es/egress/security-model/) cuenta qué cubre y qué no.

## Rendimiento

Medido con `go test -bench . ./pkg/aiagents/` en un Mac con Apple Silicon (darwin/arm64):

| Cuerpo | Tiempo de detección por petición |
|---|---|
| Petición de chat de 4 KB | 84 µs |
| Petición de chat de 64 KB | 1,3 ms |
| 64 KB preparados para activar todos los detectores (el peor caso) | 97 ms |

Cada detector solo se ejecuta si aparece alguna de sus palabras clave, así que el tráfico normal se salta casi todos. El binario estático ocupa unos 7 MB.

## Siguientes pasos

- [Inicio rápido](https://developers.openwaf.dev/es/egress/quickstart/): guarda una clave en OpenBao, escribe la configuración, arranca el contenedor y envía una primera petición.
- [Referencia de configuración](https://developers.openwaf.dev/es/egress/configuration/): todos los campos de la pasarela en tu equipo y sus valores por defecto.
- [Solución de problemas](https://developers.openwaf.dev/es/egress/troubleshooting/): cada error que devuelve la pasarela.
- [Egress alojado](https://developers.openwaf.dev/es/egress/cloud/get-started/): crea un agente en egress.openwaf.dev desde el panel, la API o MCP.


Escrito a partir de [github.com/openwaf-dev/egress@v0.1.1](https://github.com/openwaf-dev/egress/tree/v0.1.1).
