You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
security(plugins): fix auth/access bypasses and fail-open controls (#7)
Hardens the plugin layer per the security review. All touched plugins
build and pass their tests; the SDK and workspace pass the clippy gate.
- sdk: add `resolve_client_ip(req, trusted_proxies)` so security
middlewares share one trusted-proxy-aware client-IP resolver instead
of independently spoofable implementations.
- ip-restriction: support IPv6 (std::net::IpAddr) so an IPv6 client is
no longer silently allowed past a denylist; honor X-Forwarded-For only
behind configured `trusted_proxies`; fail closed on an unparseable IP
when restrictions exist.
- cors: a literal `*` with credentials no longer allows arbitrary
origins (Fetch-spec violation); reflect the validated origin with
`Vary: Origin` on responses via request context.
- rate-limit / ai-token-limit: fail CLOSED (503) when the host limiter
is unavailable by default (`fail_open` to opt out); partition by the
trusted-proxy-aware client IP so rotating XFF can't mint fresh buckets;
ai-token-limit logs (instead of silently zeroing) an unparseable token
count.
- ai-prompt-guard: fail CLOSED on an unparseable body or non-array
`messages` (`fail_open` to opt out) so the guard can't be bypassed
with a malformed body.
- dispatchers (kafka, nats, lambda, s3, http-upstream, oauth2-auth,
oidc-auth, ws-upstream): clamp the host-returned read length to the
buffer before slicing, removing a panic vector.
- ai-proxy: schema guidance to use secret references for api_key (keys
are not logged anywhere; verified).
New config: `trusted_proxies` (ip-restriction, rate-limit,
ai-token-limit), `fail_open` (rate-limit, ai-token-limit,
ai-prompt-guard).
"description": "When the request body can't be inspected (unparseable JSON or a non-array 'messages'), allow it through instead of rejecting. Defaults to false (fail closed) so the guard can't be bypassed with a malformed body."
Copy file name to clipboardExpand all lines: plugins/ai-proxy/config-schema.json
+3-3Lines changed: 3 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -23,7 +23,7 @@
23
23
},
24
24
"api_key": {
25
25
"type": "string",
26
-
"description": "Provider API key. Supports `env://VAR` substitution. Omit for Ollama (unauthenticated local endpoint)."
26
+
"description": "Provider API key. Use a secret reference (`env://VAR` or `file://...`) rather than a literal value, so the key is resolved at runtime and never baked into the compiled artifact. Omit for Ollama (unauthenticated local endpoint)."
27
27
},
28
28
"base_url": {
29
29
"type": "string",
@@ -58,7 +58,7 @@
58
58
},
59
59
"api_key": {
60
60
"type": "string",
61
-
"description": "Provider API key. Supports `env://VAR` substitution."
61
+
"description": "Provider API key. Use a secret reference (`env://VAR` or `file://...`) rather than a literal value, so the key is resolved at runtime and never baked into the compiled artifact."
62
62
},
63
63
"base_url": {
64
64
"type": "string",
@@ -84,7 +84,7 @@
84
84
},
85
85
"api_key": {
86
86
"type": "string",
87
-
"description": "API key for the flat config. Supports `env://VAR` substitution."
87
+
"description": "API key for the flat config. Use a secret reference (`env://VAR` or `file://...`) rather than a literal value, so the key is resolved at runtime and never baked into the compiled artifact."
Copy file name to clipboardExpand all lines: plugins/ai-token-limit/config-schema.json
+11Lines changed: 11 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -51,6 +51,17 @@
51
51
"description": "Source of the per-consumer partition key. Accepted forms: `client_ip`, `header:<name>`, `context:<key>`, or a literal string (shared budget across all requests). Matches the `rate-limit` plugin's semantics.",
52
52
"default": "client_ip"
53
53
},
54
+
"trusted_proxies": {
55
+
"type": "array",
56
+
"items": { "type": "string" },
57
+
"default": [],
58
+
"description": "Exact IPs of trusted reverse proxies. With partition_key 'client_ip', X-Forwarded-For / X-Real-IP are honored only behind these; otherwise the observed peer IP is used so clients cannot rotate XFF to evade their budget."
59
+
},
60
+
"fail_open": {
61
+
"type": "boolean",
62
+
"default": false,
63
+
"description": "When the host rate limiter is unavailable, allow the request (fail open) instead of rejecting with 503. Defaults to false (fail closed)."
0 commit comments