Found in the cross-endpoint parity audit following AISIX-Cloud#947 (see ai-gateway#695).
Every typed handler gates on dispatch::check_ip_access (chat.rs:838, messages.rs:436, responses.rs:333, completions.rs:230, embeddings.rs:265, rerank.rs:206, images.rs:187, audio.rs:376/567, count_tokens.rs:165). passthrough.rs resolves the model entry (which can carry allowed_cidrs) at ~221-234 but never calls check_ip_access and never resolves a client IP — so the raw credential-lending tunnel bypasses the IP allowlist the typed surfaces enforce for the same model.
Fix shape: extract ClientContext in the passthrough handler and call check_ip_access(&model_entry.value, &client.source_ip) before dispatch, same as the typed handlers. (MCP has no per-model allowlist to enforce — requests there don't resolve a Model — so it's out of scope.)
Found in the cross-endpoint parity audit following AISIX-Cloud#947 (see ai-gateway#695).
Every typed handler gates on
dispatch::check_ip_access(chat.rs:838, messages.rs:436, responses.rs:333, completions.rs:230, embeddings.rs:265, rerank.rs:206, images.rs:187, audio.rs:376/567, count_tokens.rs:165). passthrough.rs resolves the model entry (which can carryallowed_cidrs) at ~221-234 but never callscheck_ip_accessand never resolves a client IP — so the raw credential-lending tunnel bypasses the IP allowlist the typed surfaces enforce for the same model.Fix shape: extract
ClientContextin the passthrough handler and callcheck_ip_access(&model_entry.value, &client.source_ip)before dispatch, same as the typed handlers. (MCP has no per-model allowlist to enforce — requests there don't resolve a Model — so it's out of scope.)