Skip to main content
Browse docs
By Audience
Getting Started
Configuration
Use Cases
IDE Integration
Third-Party Integrations
Engineering Cache
Console
API Reference
Gateway
Workflow Guides
Templates
Providers and SDKs
Industry Guides
Advanced Guides
Browse by Role
Deployment Guides
In-Depth Guides
Tutorials
FAQ

CORS & IP Allowlist

Keeptrusts provides built-in CORS, IP allowlisting, and request size controls to protect the gateway endpoint from unauthorized origins, untrusted networks, and oversized payloads. These controls are applied at the incoming-request layer before any policy evaluation or upstream forwarding takes place.

Use this page when

  • You need the exact command, config, API, or integration details for CORS & IP Allowlist.
  • You are wiring automation or AI retrieval and need canonical names, examples, and constraints.
  • If you want a guided rollout instead of a reference page, use the linked workflow pages in Next steps.

Primary audience

  • Primary: AI Agents, Technical Engineers
  • Secondary: Technical Leaders

CORS Configuration

Cross-Origin Resource Sharing (CORS) controls which browser origins are permitted to call your Keeptrusts gateway endpoint. When cors.enabled is true, the gateway injects the appropriate Access-Control-* headers on every response and handles OPTIONS preflight requests automatically.

Configuration Fields

FieldTypeDefaultDescription
enabledboolfalseEnable CORS header injection and preflight handling.
allow_originslist of strings[]Permitted origins. Supports exact URLs or "*" (wildcard).
allow_methodslist of strings["GET","POST","OPTIONS"]HTTP methods the browser may send cross-origin.
allow_headerslist of strings["Content-Type","Authorization"]Request headers the browser may include cross-origin.
expose_headerslist of strings[]Response headers the browser may read. Useful for custom trace or rate-limit headers.
allow_credentialsboolfalseWhether to include Access-Control-Allow-Credentials: true. Must be false when allow_origins contains "*".
max_age_secondsinteger86400How long the browser caches preflight results (seconds).

Production Example

Restrict cross-origin access to a single application domain:

cors:
enabled: true
allow_origins:
- "https://app.example.com"
allow_methods:
- POST
- OPTIONS
allow_headers:
- Content-Type
- Authorization
- X-Request-Id
expose_headers:
- X-KT-Request-Id
- X-KT-Policy-Action
allow_credentials: true
max_age_seconds: 3600

Development / Wildcard Example

cors:
enabled: true
allow_origins:
- "*"
allow_methods:
- GET
- POST
- OPTIONS
allow_headers:
- "*"
allow_credentials: false # MUST be false when allow_origins contains "*"
max_age_seconds: 300
Security Warning

Never use allow_origins: ["*"] in a production deployment. Wildcard origins allow any website to send requests to your gateway endpoint directly from a visitor's browser. In production, always enumerate the exact origins that should have cross-origin access.

Multiple Allowed Origins

When your application is served from multiple subdomains or environments, list each origin explicitly:

cors:
enabled: true
allow_origins:
- "https://app.example.com"
- "https://staging.example.com"
- "https://admin.example.com"
allow_credentials: true

Keeptrusts reflects only the matching origin back in the Access-Control-Allow-Origin header rather than echoing an arbitrary Origin header, so each individual response carries exactly the origin that matched.

Preflight Handling

Preflight OPTIONS requests are handled automatically when cors.enabled: true. The gateway returns a 204 No Content response with the appropriate Access-Control-* headers and does not forward OPTIONS requests upstream to the LLM provider. You do not need to add any application-level OPTIONS handler.


IP Allowlist

The IP allowlist controls which source IP addresses are permitted to send requests to the gateway. Requests from addresses that do not match the allow list, or that explicitly match the deny list, are rejected with 403 Forbidden before any request body is read.

Configuration Fields

FieldTypeDefaultDescription
enabledboolfalseEnable IP-based filtering.
allowlist of CIDR strings[]Permitted source address ranges. Empty list with enabled: true denies all traffic.
denylist of CIDR strings[]Explicitly denied ranges. Evaluated after allow; a match in deny overrides a match in allow.
trust_proxy_headersboolfalseWhen true, reads the source IP from a gateway forwarding header rather than the TCP connection source.
ip_headerstring"X-Forwarded-For"Which header to read when trust_proxy_headers: true. Common values: "X-Forwarded-For", "X-Real-IP", "CF-Connecting-IP".

Private Network Only Example

Allow only RFC 1918 private address space (suitable for an on-premises or VPC-only deployment):

ip_allowlist:
enabled: true
allow:
- "10.0.0.0/8"
- "172.16.0.0/12"
- "192.168.0.0/16"
- "127.0.0.1/32" # localhost for health checks
deny: []
trust_proxy_headers: false

Deny Specific Ranges

Allow your internal network but explicitly deny a known-problematic subnet:

ip_allowlist:
enabled: true
allow:
- "10.0.0.0/8"
deny:
- "10.99.0.0/16" # quarantine subnet
trust_proxy_headers: false

Evaluation order: if an address matches both allow and deny, the deny rule wins and the request is rejected.

Load-Balanced Deployments

When Keeptrusts runs behind a load balancer or reverse proxy (AWS ALB, Nginx, Cloudflare, etc.), the TCP source IP is the load balancer's IP rather than the actual client IP. Enable trust_proxy_headers and set ip_header to the header your load balancer injects:

ip_allowlist:
enabled: true
allow:
- "10.0.0.0/8"
trust_proxy_headers: true
ip_header: "X-Forwarded-For"
Only enable trust_proxy_headers: true when your deployment topology guarantees that the gateway-forwarding header cannot be forged by an external client. On a public internet endpoint without a fronting load balancer, an attacker can set X-Forwarded-For to any value. In that case, leave trust_proxy_headers: false so the real TCP source IP is used.

IPv6 Support

CIDR ranges for IPv6 are fully supported:

ip_allowlist:
enabled: true
allow:
- "10.0.0.0/8"
- "::1/128" # IPv6 localhost
- "fd00::/8" # IPv6 unique local

Request Size Limits

Size limits prevent runaway payloads from exhausting memory or creating denial-of-service conditions on the gateway.

Configuration Fields

FieldTypeDefaultDescription
max_request_body_bytesinteger10485760 (10 MB)Maximum allowed request body size in bytes. Requests exceeding this limit receive 413 Content Too Large.
max_response_body_bytesinteger33554432 (32 MB)Maximum response body size buffered in memory.

Notes on Streaming

Streaming responses (Server-Sent Events) bypass the max_response_body_bytes limit because the response is not buffered — it is chunked directly to the client as tokens arrive. The limit applies only to non-streaming (buffered) responses.

Configuration Example

size_limits:
max_request_body_bytes: 5242880 # 5 MB
max_response_body_bytes: 16777216 # 16 MB

To calculate common byte thresholds:

LimitBytes
1 MB1048576
5 MB5242880
10 MB10485760
32 MB33554432
64 MB67108864

Full Security Config Example

The following configuration combines CORS, IP allowlisting, and request size controls for a production deployment behind an internal load balancer:

pack:
name: cors-ip-allowlist-providers-9
version: 1.0.0
enabled: true
providers:
targets:
- id: primary
provider: openai:chat:gpt-4o
secret_key_ref:
env: OPENAI_API_KEY
policies:
chain:
- audit-logger
policy:
audit-logger:
immutable: true
retention_days: 365
log_all_access: true

Best Practices

  1. Never use wildcard CORS origins in production. allow_origins: ["*"] exposes your gateway to cross-site request forgery and credential theft from any site a user visits. Always enumerate exact origins.

  2. Pair allow_credentials: true with exact origins. The CORS specification prohibits returning Access-Control-Allow-Credentials: true alongside Access-Control-Allow-Origin: *. Keeptrusts will reject this configuration at startup with a clear error, but it is best to understand the rule before configuring it.

  3. Set IP allowlists even in private networks. Defense in depth means assuming any host in your internal network could be compromised. Restricting the gateway to only the CIDRs that legitimately call it limits blast radius if another internal service is breached.

  4. Only trust gateway headers when the forwarding layer is under your control. On a public-internet endpoint, forged X-Forwarded-For headers bypass IP allowlisting entirely. Prefer to enforce IP restrictions at the network layer (security groups, firewall rules) in addition to the gateway-level allowlist.

  5. Keep request body limits as low as your workload permits. Most LLM requests — even those with long system prompts — fit comfortably within 1–5 MB. Setting an unnecessarily high limit (e.g., 100 MB) increases exposure to memory-exhaustion attacks. Start conservative and raise the limit only if you have a documented need.

  6. Expose only the headers your clients actually read. Every header listed in expose_headers is readable by browser JavaScript on the listed origins. Limit exposure to headers that your frontend application actively consumes (e.g., trace IDs for error reporting) rather than exposing all gateway-internal headers.


CORS Header Reference

When a cross-origin request is received, Keeptrusts injects the following response headers based on your configuration:

HeaderSource Config FieldNotes
Access-Control-Allow-Originallow_originsReflects the matched origin; never echoes arbitrary input. "*" only when wildcard is configured.
Access-Control-Allow-Methodsallow_methodsReturned on preflight OPTIONS responses.
Access-Control-Allow-Headersallow_headersReturned on preflight OPTIONS responses.
Access-Control-Expose-Headersexpose_headersPresent on all responses, not just preflight.
Access-Control-Allow-Credentialsallow_credentialsOmitted entirely when false.
Access-Control-Max-Agemax_age_secondsReturned on preflight OPTIONS responses.
VaryAutomaticAlways set to Origin when CORS is enabled, to prevent incorrect caching.

IP Allowlist Event Log

Every request rejected by the IP allowlist produces an event in the Keeptrusts event log:

{
"event_type": "ip_denied",
"source_ip": "203.0.113.42",
"matched_rule": "deny",
"deny_range": "203.0.113.0/24",
"request_path": "/v1/chat/completions",
"timestamp": "2026-03-15T14:22:31Z"
}

You can query these events to identify unexpected traffic sources or to audit allowlist effectiveness:

curl -s "https://api.keeptrusts.com/v1/events?event_type=ip_denied&limit=100" \
-H "Authorization: Bearer $KEEPTRUSTS_API_TOKEN" \
| jq '[.events[] | {ip:.source_ip, rule:.matched_rule, path:.request_path}]'

Testing Your CORS Configuration

After deploying, verify CORS headers are being returned correctly with curl:

# Check preflight response
curl -si -X OPTIONS "http://localhost:41002/v1/chat/completions" \
-H "Origin: https://app.example.com" \
-H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Headers: Content-Type, Authorization" \
| grep -i "access-control"

Expected output:

Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 3600
Access-Control-Allow-Credentials: true

To test IP allowlist rejection:

# Verify a blocked IP receives 403 (requires spoofed header in test, not production)
curl -si -X POST "http://localhost:41002/v1/chat/completions" \
-H "X-Forwarded-For: 203.0.113.42" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-4o","messages":[{"role":"user","content":"hello"}]}'
# Expect: HTTP 403 Forbidden

For AI systems

  • Canonical terms: Keeptrusts CORS, IP Allowlist, request size limits, preflight handling.
  • Config keys: cors.enabled, cors.allow_origins, cors.allow_methods, cors.allow_headers, cors.expose_headers, cors.allow_credentials, cors.max_age_seconds, ip_allowlist.enabled, ip_allowlist.allow (CIDR), ip_allowlist.deny (CIDR), ip_allowlist.trust_proxy_headers, ip_allowlist.ip_header, size_limits.max_request_body_bytes, size_limits.max_response_body_bytes.
  • Response headers: Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers, Access-Control-Expose-Headers, Access-Control-Allow-Credentials, Access-Control-Max-Age, Vary: Origin.
  • Error responses: 403 Forbidden for IP deny, 413 Content Too Large for oversized payloads.
  • Event type: ip_denied with fields source_ip, matched_rule, deny_range.
  • Best next pages: Rate Limiting, Consumer Groups, Custom Routes.

For engineers

  • Prerequisites: know your deployment topology — if behind a load balancer, set trust_proxy_headers: true and ip_header to the correct forwarding header.
  • Never use allow_origins: ["*"] in production; Keeptrusts rejects allow_credentials: true with wildcard origins at startup.
  • Test CORS: curl -si -X OPTIONS <gateway>/v1/chat/completions -H "Origin: https://app.example.com" -H "Access-Control-Request-Method: POST" | grep -i access-control.
  • Test IP deny: query GET /v1/events?event_type=ip_denied to audit rejected traffic.
  • Streaming responses bypass max_response_body_bytes — only buffered responses are limited.
  • Whitelist health-check IPs (127.0.0.1/32) and internal service CIDRs in the IP allowlist.

For leaders

  • Security posture: CORS and IP allowlists are the gateway’s first line of defense, applied before any policy evaluation or upstream forwarding.
  • Compliance: IP allowlists enforce network perimeter controls required by SOC 2, HIPAA, and PCI DSS environments.
  • Risk: wildcard CORS origins expose the gateway to cross-site request forgery from any website; enumerate exact origins in production.
  • Operational: trust_proxy_headers must only be enabled when the forwarding layer is under your control — otherwise attackers can bypass IP restrictions by forging headers.

Next steps