This is the model we design and test against. It is as much about what Penweir does not cover as about what it does.
What is protected
- Sensitive values in requests (identifiers, credentials, customer data), so they do not reach LLM providers the policy does not allow.
- Request and response content at rest, which must not exist anywhere.
- Provider credentials and the master key.
- Control of the gateway’s configuration: who can change what passes.
- The audit trail: who used which model and when.
Who it is protected from
| Actor | Can | Penweir’s answer |
|---|---|---|
| LLM provider | Sees everything a request sends. | Redaction and blocking before the call, plus routing restricted to allowed providers. Tests against a fake provider prove the values never left. |
| Application with a valid key | Sends anything. | Its pipeline applies, and it cannot choose another one. Unknown fields are rejected, and request size is limited. |
| Anyone who can reach the gateway port | Guesses keys and sends junk. | Keys are 43 random characters, stored as digests and compared in constant time. Unauthenticated requests are not processed or audited. |
| Anyone who can reach the admin port | Guesses passwords, CSRF, XSS. | argon2id, account lockout, a per-address rate limit, optional TOTP, __Host- HttpOnly SameSite=Strict cookies, CSRF tokens with an origin check, a strict CSP, and no third-party assets. Keep the port internal. |
| Someone with a copy of the database or a backup | Reads it. | No payload is stored. Secrets are encrypted with a master key that is not in the database. Keys and session tokens are stored as digests. |
| Someone with the logs | Reads them. | Logs are content-free by construction and tested with canaries. |
| An operator writing a config | Points a provider at an internal service (SSRF). | Link-local and metadata addresses are refused unless allowed. Credentials in URLs are refused, and redirects are not followed. |
| The supply chain | Ships malicious code. | Every dependency is pinned with hashes and justified. Image bases are pinned by digest, CI actions by commit, and npm packages by integrity hash. Vulnerability scans run in CI, and a CycloneDX SBOM ships with every release. The dashboard is static, with no Node in production. |
What is out of scope
- A compromised host or container runtime: it can read process memory.
- Model behaviour: what a provider does with what it legitimately receives.
- Detection of unstructured personal data such as names (see what Penweir guarantees).
- Availability attacks beyond request size limits and timeouts. Rate, token and concurrency limits count in memory for one process, so put a proxy with limits in front if the port is reachable by untrusted clients.
Notable design choices
- Memory-only request scope. The token vault cannot be pickled, copied or printed, and it is wiped on success, error and cancellation.
- Failing closed. A pipeline that names an unknown detector, or a provider without its key, makes the gateway not ready rather than running without the step. An invalid licence or master key stops startup.
- Separate ports. The admin API and dashboard can be firewalled separately from the gateway.
- Synchronous logging to stdout. If nothing drains stdout, the gateway blocks. Container runtimes always drain it.
- SSRF check behind a proxy. Without a proxy, the connection goes to the address that was checked. Through
proxy_url, the proxy resolves the name again. Use network egress rules as the hard boundary.