OpenWAF Egress: an open-source gateway that keeps provider keys out of your AI agents
We open-sourced the gateway we put between AI agents and model providers. Agents keep a placeholder token; the real key is injected from OpenBao or Vault only after the request passes 27 prompt-injection detectors, data-leak patterns and an SSRF check.
By the OpenWAF security team
In short. Today we are releasing OpenWAF Egress v0.1.1 as open source under the Apache License 2.0. It is a small gateway between your AI agents and the model providers they call.
- Agents hold a placeholder token (
OWE_TOKEN_…), never the provider key. - Every request is checked first: agent token, allowed target, SSRF, 27 prompt-injection detectors and data-leak patterns. Only then is the real key read from OpenBao or HashiCorp Vault and set on the outgoing request.
- Detection is deterministic, with no model call: 84 µs for a 4 KB chat request on an Apple Silicon Mac.
- One Go binary with no third-party modules, published as
ghcr.io/openwaf-dev/egressfor amd64 and arm64.
Why agents should not hold provider keys
An AI agent reads text it did not write: web pages, issues, e-mails, tool output. Any of it can carry a prompt injection, an instruction aimed at the model instead of the user. If the agent can run commands or call tools, an injected “print your environment” or “send the conversation to this URL” is one step away from leaking whatever the process can read. A provider key in an environment variable is readable by the agent, by every tool it runs and by every dependency in its container.
Those keys are worth stealing. When a hijacked LiteLLM release shipped a credential stealer last week, the advice was to rotate every provider key the gateway held (our write-up). Today Flavio Copes published How to protect secrets when coding agents deploy your app, which reaches the same conclusion from the deployment side: hiding a secret from the model is not enough, and a restricted service or API proxy that attaches the credential only for approved hosts and operations keeps it out of the agent altogether.
That is what OpenWAF Egress does for model providers.
How it works
The agent keeps its SDK. Only two values change: the base URL points at the gateway, and the key is the agent’s placeholder.
const client = new OpenAI({
baseURL: "http://127.0.0.1:8070/v1/agent/my-support-agent/proxy/openrouter",
apiKey: "OWE_TOKEN_SUPPORT_AGENT", // placeholder; the real key never reaches the agent
});
Each request then goes through five steps. The first one that fails answers with a JSON error and nothing is sent to the provider:
- Agent token.
Authorization: Bearermust carry the agent’s placeholder (401otherwise). - Target allowlist. The target must be one the agent is allowed to call (
403 egress_blocked). - SSRF check. The target’s host must resolve only to public addresses (
403 ssrf_blocked). - Body inspection. Prompt-injection detectors and data-leak patterns (
403 injection_detected,403 data_leak_blocked). - Key from OpenBao. The gateway logs in with AppRole, reads the key from KV v2 (cached for five minutes) and sets it in the header the target expects. The response streams back to the agent as it arrives.
The video above is the real gateway binary answering: the key injected into a normal request, then a prompt injection, a card number and a request to the cloud metadata address refused.
What it checks
- Prompt injection: 27 detectors in English and Spanish. 21 match instruction shapes: overrides, system-prompt extraction, jailbreak personas and modes, forged system, tool and turn messages, chat-template tokens, concealment orders, tool invocation, approval bypass, memory poisoning, destructive commands, remote scripts piped to a shell, secret harvesting and exfiltration through hosts or rendered links. Six find text hidden from a human reader: zero-width and Unicode tag characters, HTML comments, CSS-hidden elements, base64 and percent or hex encoding. The full list is on the product page.
- Data leaks: Luhn-valid card numbers, PEM private keys, AWS access key IDs, OpenAI-style
sk-keys and GitHub tokens. - SSRF: loopback, private, CGNAT, link-local (including
169.254.169.254), multicast and reserved ranges, IPv4 and IPv6. - Redirects: never followed. A provider’s
3xxgoes back to the agent, so the injected key cannot follow it to another host. - No partial inspection: inline base64 images, audio and video (
data:URIs and the JSON"data"fields of OpenAI, Gemini and Anthropic) are left out of the inspected text; the rest must fit a 1 MiB window or the request gets413. Nothing is cut or forwarded uninspected.
Benchmark
Detection is regular expressions, and each detector only runs when one of its keywords appears in the body, so ordinary traffic skips almost all of them. Measured with go test -bench . ./pkg/aiagents/ on an Apple Silicon Mac (darwin/arm64):
| Request body | Detection time |
|---|---|
| 4 KB chat request | 84 µs |
| 64 KB chat request | 1.3 ms |
| 64 KB built to trigger every detector (worst case) | 97 ms |
These numbers are the inspection only, not the provider’s response time. The static binary is about 7 MB.
Get started
Write a config.json with your targets and agents, then run the container on loopback:
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
The quickstart walks through the OpenBao secret, the AppRole, the configuration and a first request. The configuration reference lists every field, and troubleshooting every error code.
What it does not do
- It is not proof of safety. Pattern matching stops known injection and exfiltration shapes, not every possible one.
- It speaks plain HTTP with static tokens. Keep it on loopback or a private network, or put TLS in front of it.
- It inspects request bodies only, not headers, query strings or the provider’s responses, and it does not limit spend.
- The gateway can read the keys, so it is now the component to protect: give its AppRole read access to the agents’ keys and nothing else.
The security model covers each of these. Vulnerabilities go to [email protected]; issues and pull requests to github.com/openwaf-dev/egress.
Frequently asked questions
What is OpenWAF Egress?
An open-source (Apache-2.0) HTTP gateway between AI agents and model providers. Agents hold a placeholder token; the gateway checks each request and injects the real provider key, read from OpenBao or HashiCorp Vault, into the outgoing request.
Do I need OpenWAF Cloud to use it?
No. It is a separate project you run yourself, as a container (linux/amd64 and linux/arm64) or a binary for Linux or macOS, next to your agents.
Does it use a model to detect prompt injection?
No. Its 27 detectors are deterministic regular expressions in English and Spanish. Detection takes 84 µs for a 4 KB chat request on an Apple Silicon Mac.
Which providers can agents call through it?
Any HTTP API you configure as a target. The examples cover OpenRouter, OpenAI, Anthropic, Gemini and Hugging Face.
Can I expose it on the internet?
No. It speaks plain HTTP and agent tokens are static: keep it on loopback or a private network, or put TLS in front of it.
Sources
- OpenWAF Egress v0.1.0 release notes OpenWAF, Oct 27, 2026
- OpenWAF Egress v0.1.1 release notes OpenWAF, Oct 27, 2026
- openwaf-dev/egress: README, SECURITY.md and source code OpenWAF
- How to protect secrets when coding agents deploy your app Flavio Copes, Oct 27, 2026
- LLM Prompt Injection Prevention Cheat Sheet OWASP
Topics
- OpenWAF Egress
- AI agents
- prompt injection
- egress gateway
- API keys
- OpenBao
- HashiCorp Vault
- DLP
- SSRF
- open source
- Apache-2.0
Author
OpenWAF