Skip to main content

Runtime & Network

Security and Network Configuration

These sections decide which clients can reach the model endpoints of the gateway: ip_allowlist limits source addresses, cors decides which browser origins can read responses, and size_limits rejects oversized payloads. They apply to the public proxy handlers only, not to every endpoint on the listener.

Keep the listener and the management endpoints behind your own network controls. CORS is a browser rule, not authentication: a server-side client can call the gateway without an Origin header.

Allow one browser application​

Do this only if a browser must call the gateway directly. Never put a provider key in browser code. Replace https://app.example.com with the exact origin of the application, including the scheme and any port:

Inside policy-config.yaml
cors:
  enabled: true
  allow_origins:
    - https://app.example.com
  allow_methods: [POST, OPTIONS]
  allow_headers: [Content-Type, Authorization]
  expose_headers: [X-Request-Id]
  allow_credentials: false
  max_age_seconds: 3600

Apply the configuration, then send a preflight request to the agent base URL from the quickstart:

curl -i -X OPTIONS "${VERDICTAN_BASE_URL}/chat/completions" \
  -H "Origin: https://app.example.com" \
  -H "Access-Control-Request-Method: POST" \
  -H "Access-Control-Request-Headers: authorization,content-type"

The allowed origin gets matching CORS headers. Send the preflight again with a different origin: it must not get permission. Finally, call the gateway from the browser application itself, because a successful curl does not prove browser access.

IP allowlist​

FieldTypeDefaultDescription
cidrsarray of strings[]Allowed IPv4 or IPv6 ranges
trusted_proxy_cidrsarray of strings[]Networks of proxies that can add X-Forwarded-For

IP allowlist scope​

  • The allowlist applies to the public proxy handlers. Health, configuration, and admin endpoints do not use it. Protect the whole listener with network controls.
  • The gateway ignores forwarding headers from a peer that is not trusted. For a trusted peer, it reads X-Forwarded-For from right to left and stops at the first address outside trusted_proxy_cidrs.
  • An empty trusted_proxy_cidrs trusts no proxy.

CORS​

FieldTypeDefaultDescription
enabledbooleanfalseTurns CORS headers on or off
allow_originsarray of stringsAll originsAllowed origins. An empty list allows every origin.
allow_methodsarray of stringsGET, POST, OPTIONSAllowed HTTP methods
allow_headersarray of stringsAllowed request headers
expose_headersarray of stringsResponse headers that browser JavaScript can read
allow_credentialsbooleanfalseAllows requests with credentials
max_age_secondsintegerHow long a browser can cache the preflight result

CORS rules​

  • With allow_credentials: true, list exact origins in allow_origins. Do not use * or an empty list.
  • The gateway ignores an origin, method, or header value that it cannot parse.

Size limits​

size_limits sets max_body_bytes, max_header_bytes, max_url_bytes, and max_response_bytes. Rate Limit Configuration describes each field.

Size limit scope​

  • The request body, header, and URL limits apply only to POST /v1/chat/completions. A request over a limit gets HTTP 413.
  • The response limit applies to buffered Chat Completions and Responses. An oversized response returns HTTP 502 with error code response_size_exceeded. An oversized stream ends with a final SSE error.
  • Other request families are not limited.

Bot detector​

The bot-detector control flags callers that send many requests with the same fingerprint, or prompts that are almost identical, in a short window. It compares recent prompts from all callers on the gateway, not only from one caller. Put it first in the chain to warn or block before other controls run.

Bot detector lint checks​

verdictan policy lint rejects a similarity_threshold outside 0.0 to 1.0, and a max_requests_per_window of 0.

Complete security example​

Replace the client address, proxy address, and origin before you apply this. Then test from an allowed client and from a denied one. A wrong allowlist locks authorized clients out.

policy-config.yaml
pack:
  name: secured-gateway
  version: 1.0.0
  enabled: true
providers:
  targets:
    - id: openai-prod
      provider: openai
      model: your-openai-model
      secret_key_ref:
        env: VERDICTAN_OPENAI_API_KEY
ip_allowlist:
  cidrs:
    - 192.0.2.20/32  # Replace with an approved client address
  trusted_proxy_cidrs:
    - 192.0.2.10/32  # Replace with the exact trusted proxy address
cors:
  enabled: true
  allow_origins:
    - https://app.example.com
  allow_methods:
    - POST
    - OPTIONS
  allow_headers:
    - Content-Type
    - Authorization
  allow_credentials: true
  max_age_seconds: 7200
size_limits:
  max_body_bytes: 2097152
  max_header_bytes: 16384
  max_url_bytes: 8192
  max_response_bytes: 15728640
policies:
  chain:
    - bot-detector
    - prompt-injection
    - pii-detector
policy:
  bot-detector:
    fingerprint_fields:
      - user-agent
      - authorization
    profile_window_seconds: 60
    similarity_threshold: 0.9
    max_requests_per_window: 25
    action: warn
  prompt-injection:
    response:
      action: block
  pii-detector:
    action: redact

Next steps​