mirror of
https://github.com/lukaszraczylo/traefik-llmgateway.git
synced 2026-10-21 05:57:53 +00:00
fix(security): bound fan-out and method surface and scrub relayed text
- Add a process-wide gate on MCP tools/list backend connections. The per-request limit alone let N callers open N times as many. - Reject CONNECT and TRACE on native passthrough and on MCP and A2A targets with 405. - Scrub URL query strings and the target URL from a backend JSON-RPC error message before it reaches the caller. - Replace the value of redis.address in GET /admin/api/config. The users file path stays visible by design. - Escape line breaks in every log line so an upstream string cannot forge log entries. - Add stripClientAnthropicBeta. When true, POST /v1/messages does not forward the client anthropic-beta header. The default stays false.
This commit is contained in:
+17
-1
@@ -423,8 +423,8 @@ func hasTraversalSegment(rest string) bool {
|
||||
// parse afterward. truncated records whether the cap was hit, so the
|
||||
// caller knows a parse would only fail on cut-off JSON and skips it.
|
||||
type cappedAccountingBuffer struct {
|
||||
buf bytes.Buffer
|
||||
budget *teeBudget
|
||||
buf bytes.Buffer
|
||||
reserved int64
|
||||
truncated bool
|
||||
}
|
||||
@@ -1225,6 +1225,9 @@ func (g *Gateway) handlePassthrough(w http.ResponseWriter, r *http.Request, u *u
|
||||
}
|
||||
}
|
||||
|
||||
if !proxyMethodAllowed(w, r) {
|
||||
return
|
||||
}
|
||||
if r.Header.Get("Upgrade") != "" {
|
||||
writeOAIError(w, http.StatusNotImplemented, "invalid_request_error", "websocket/upgrade passthrough not supported")
|
||||
return
|
||||
@@ -1798,3 +1801,16 @@ func (g *Gateway) proxyUpstream(w http.ResponseWriter, r *http.Request, upstream
|
||||
}
|
||||
return proxyResult{isJSON: isJSON, isSSE: isSSE, tee: tee, sseTee: sseTee, status: resp.StatusCode, requestBytes: requestBytes}, true
|
||||
}
|
||||
|
||||
// proxyMethodAllowed rejects the methods a reverse proxy to a configured
|
||||
// backend must never relay. CONNECT opens a tunnel and TRACE echoes the
|
||||
// request back, and no supported provider or target needs either.
|
||||
func proxyMethodAllowed(w http.ResponseWriter, r *http.Request) bool {
|
||||
switch r.Method {
|
||||
case http.MethodConnect, http.MethodTrace:
|
||||
w.Header().Set("Allow", "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS")
|
||||
writeOAIError(w, http.StatusMethodNotAllowed, "invalid_request_error", "method not allowed")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user