OpenWAF Egress
Tus agentes de IA nunca tienen la clave del proveedor.
OpenWAF Egress se coloca entre tus agentes y los proveedores de modelos a los que llaman. El agente solo recibe un token de marcador. Cada petición se revisa contra inyección de prompt, fugas de datos y SSRF, y solo entonces la pasarela lee la clave real de OpenBao o HashiCorp Vault, la inyecta y reenvía la petición sin romper el streaming.
27 detectores, sin llamar a ningún modelo
84 µs por una petición de chat de 4 KB
Un binario de Go, imagen para amd64 y arm64
Cómo funciona
Cinco comprobaciones antes de que la clave salga del almacén
El agente sigue usando su SDK de siempre. Solo cambian la URL base y la clave.
URL base http://127.0.0.1:8070/v1/agent/<agente>/proxy/<destino> · clave OWE_TOKEN_…
- 1
Token del agente
401El agente envía su marcador en
Authorization: Bearer. Si falta o no coincide, la petición acaba aquí. - 2
Destinos permitidos
403 egress_blockedEl destino de la URL tiene que estar en los
allowed_targetsdel agente. - 3
Comprobación de SSRF
403 ssrf_blockedEl host del destino solo puede resolver a direcciones públicas.
- 4
Inspección del cuerpo
403 injection_detected · data_leak_blockedLos detectores de inyección de prompt y los patrones de fuga de datos revisan el cuerpo, sin llamar a ningún modelo.
- 5
Clave desde OpenBao
→ proveedorLa clave real se lee de KV v2 y se pone en la petición de salida; la respuesta vuelve al agente en streaming.
Inyección de prompt
27 detectores deterministas, en inglés y en español
Expresiones regulares que buscan órdenes dirigidas a un modelo, no temas: hablar de prompts, de la terminal o de secretos no salta. Una petición bloqueada recibe 403 injection_detected con el id, la etiqueta y el texto encontrado de cada detección.
21 detectores de patrones
Anulaciones, jailbreaks, mensajes falsificados, abuso de herramientas y órdenes de exfiltración.
pi.override.enAnulación de instrucciones (en inglés)pi.override.esAnulación de instrucciones (en español)pi.sysprompt.enExtracción del prompt de sistema (en inglés)pi.sysprompt.esExtracción del prompt de sistema (en español)pi.jailbreak.personaPersonaje de jailbreakpi.jailbreak.modeModo jailbreakpi.fake_systemMensaje de sistema falsopi.compliance_noticeAviso de cumplimiento falsopi.concealOcultación al usuariopi.chat_templateTokens de plantilla de chatpi.fake_toolLlamada o resultado de herramienta falsificadopi.fake_turnTurnos de conversación falsificadospi.memoryEnvenenamiento de la memoria persistentepi.tool_invokeOrden de invocar una herramientapi.no_confirmSaltarse la aprobaciónagent.destructiveOrden de comando destructivoexfil.pipe_shellScript remoto pasado a una shellexfil.env_secretsRecolección de secretosexfil.host_dataExfiltración de datos de la máquinaexfil.markdown_imageExfiltración con un enlace o una imagen renderizadoscost.amplificationOrden de multiplicar el gasto (se informa, no se rechaza)
6 detectores de texto oculto o codificado
Órdenes que una persona no ve al leer. Los comentarios, los elementos ocultos con CSS y los bloques codificados se decodifican y se revisan con los detectores de patrones.
hidden.zero_widthTexto oculto de ancho cerohidden.tag_charsCaracteres de etiqueta Unicode ocultospi.html_commentÓrdenes en un comentario HTMLhidden.css_textÓrdenes en texto oculto con CSSpi.base64Órdenes codificadas (base64)pi.encodedÓrdenes codificadas (%xx o hexadecimal)
La detección es por patrones: frena formas conocidas de inyección y exfiltración, no demuestra que una petición sea segura. La pasarela rechaza cualquier detección salvo cost.amplification, que ignora. El mismo juego de detectores protege los endpoints de IA en el borde de OpenWAF.
Protecciones
Claves, datos y destinos
Cada comprobación se activa por agente. Cada rechazo es un error JSON que el agente puede leer.
- Claves inyectadas desde OpenBao o Vault
El agente lleva un marcador
OWE_TOKEN_…. Tras las comprobaciones, la pasarela entra con AppRole, lee la clave de KV v2 (en caché 5 minutos) y la pone solo en la petición de salida. - Destinos permitidos por agente
Cada agente enumera en
allowed_targetslos destinos a los que puede llegar. Cualquier otro destino configurado recibe403 egress_blockedantes de leer el cuerpo. - Prevención de fugas de datos
Con
block_dlp, un cuerpo con un número de tarjeta válido por Luhn, una clave privada PEM, un identificador de clave de AWS, una clavesk-al estilo de OpenAI o un token de GitHub recibe403 data_leak_blocked. - Protección contra SSRF
Loopback, RFC 1918, CGNAT, enlace local (169.254.169.254 incluida), multidifusión, rangos reservados y sus equivalentes IPv6 se rechazan con
403 ssrf_blocked. - Sin seguir redirecciones
Un
3xxdel proveedor vuelve al agente tal cual, así que la clave inyectada nunca sigue una redirección hacia un host fuera de la lista. - Cuerpos enteros o nada
Las imágenes, audios y vídeos en base64 en línea (URI
data:y los campos"data"de OpenAI, Gemini y Anthropic) no cuentan como texto inspeccionado. El resto debe caber en la ventana de 1 MiB o la petición recibe413; nada se reenvía sin inspeccionar ni recortado. El cuerpo tiene un tope de 8 MiB.
Rendimiento
La detección, medida en microsegundos
Lo que tarda en pasar todos los detectores por el cuerpo de una petición, según las pruebas de rendimiento del repositorio.
- 84 µsPetición de chat de 4 KB
- 1,3 msPetición de chat de 64 KB
- 97 ms64 KB preparados para activar todos los detectores (el peor caso)
Medido con go test -bench . ./pkg/aiagents/ en un Mac con Apple Silicon (darwin/arm64). 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.
Inicio rápido
En marcha en dos pasos
Escribe un config.json con tus destinos y tus agentes, arranca el contenedor y cambia la URL base del agente.
- 1
Arranca el contenedor en loopback
Dentro del contenedor la imagen escucha en 0.0.0.0:8070. Publícala solo en 127.0.0.1 o en una red privada.
docker run -d --name openwaf-egress -p 127.0.0.1:8070:8070 \ -v "$PWD/config.json:/app/config.json:ro" \ ghcr.io/openwaf-dev/egress:0.1.1 - 2
Apunta el SDK a la pasarela
Sirve cualquier SDK compatible con OpenAI: cambia la URL base y dale el token de marcador.
import OpenAI from "openai"; const client = new OpenAI({ baseURL: "http://127.0.0.1:8070/v1/agent/my-support-agent/proxy/openrouter", // placeholder; the real key never reaches the agent apiKey: "OWE_TOKEN_SUPPORT_AGENT", });
Después: el inicio rápido (el secreto en OpenBao, la configuración y una primera petición) y todos los campos de la configuración.
Notas de seguridad
Hasta dónde llega
Qué hacer al desplegarla y qué no promete.
Antes de desplegar
- La pasarela habla HTTP sin cifrar y los tokens de los agentes son fijos: mantenla en loopback o en una red privada, o pon TLS delante. Nunca la expongas a internet.
- Cambia el token de ejemplo
OWE_TOKEN_SUPPORT_AGENTpor un valor largo y aleatorio para cada agente: el de ejemplo es público. - Da al AppRole de la pasarela permiso de lectura solo sobre las claves de los agentes.
- La detección encarece las formas conocidas de inyección de prompt y de exfiltración; no demuestra que una petición sea segura.
- Comunica vulnerabilidades a [email protected].
Enlaces
Preguntas
Preguntas sobre OpenWAF Egress
¿Llega a ver el agente la clave del proveedor?
No. El agente solo tiene su marcador OWE_TOKEN_…. La pasarela lee la clave real de OpenBao o Vault cuando la petición ha pasado las comprobaciones y la pone en la petición de salida. Al agente vuelve la respuesta del proveedor, no la clave.
¿Llama a un modelo para detectar la inyección de prompt?
No. Los detectores son expresiones regulares deterministas en inglés y español, y cada uno solo se ejecuta si aparece alguna de sus palabras clave. La detección tarda 84 µs en una petición de chat de 4 KB en un Mac con Apple Silicon.
¿Con qué proveedores funciona?
Con cualquier API HTTP que definas como destino: una URL base, un host y la cabecera que recibe la clave. Los ejemplos cubren OpenRouter, OpenAI, Anthropic (x-api-key), Gemini (x-goog-api-key) y Hugging Face.
¿Sigue funcionando el streaming?
Sí. La respuesta se copia al agente según llega y se vacía tras cada lectura, así que los tokens en streaming le llegan según los envía el proveedor.
¿Qué pasa con las peticiones grandes con imágenes?
Las imágenes, audios y vídeos en base64 en línea, como URI data: o como los campos JSON data de OpenAI, Gemini y Anthropic, quedan fuera del texto inspeccionado y se reenvían sin cambios. El resto del texto tiene que caber en 1 MiB o la petición recibe un 413, y ningún cuerpo puede pasar de 8 MiB.
¿Forma parte de OpenWAF Cloud?
Es un proyecto de código abierto aparte, con licencia Apache-2.0, que ejecutas tú junto a tus agentes. Usa el mismo juego de detectores que la protección de endpoints de IA del borde de OpenWAF.
Quítales las claves a tus agentes.
OpenWAF Egress es gratuito y de código abierto con licencia Apache-2.0. Arranca el contenedor junto a tus agentes y apunta su SDK a él.


