Reported issues for AISIX AI Gateway
Pod holds 14 of 14 GitHub reports that passed its relevance review. This can include external user reports, maintainer-confirmed bugs, and concrete feature gaps. Treat them as evidence to inspect, not a count of distinct defects.
Back to AISIX AI Gateway.
Most discussed
Upstream TLS trust: no config surface for a private CA, and no verification override
Description
Outbound TLS trust has no configuration surface. There is no ssl_verify-style switch and no way to point the gateway at a private CA bundle from config:
- no
tls/ca_file/verifyfield in theupstream:config section, which otherwise carries the connection-layer settings (timeouts, keepalive, pool, retries); - no TLS field on any resource in
schemas/resources/— in particularprovider_key, which is where an upstream endpoint (api_base) is declared; -…
Read the thread · 2026-07-31 · closed · 2 comments
/v1/completions emits an empty applied_guardrails while its chain does run
Found by the independent pre-merge audit of #1028.
/v1/completions resolves a guardrail chain (crates/aisix-proxy/src/completions.rs, state.guardrail_index.resolve(&guardrail_ctx)) and runs both the non-segment check and the segment pass over the prompt — but never snapshots resolved_chain.applied(), and emit_usage_event never sets applied_guardrails. The emitted event leaves the field empty.
Every sibling handler fills it: chat, messages, responses, embeddings, rerank, images,…
Read the thread · 2026-08-22 · open · outside contributor · 1 comment
bug: on /mcp the guardrail scan text and the mask surface are different texts — block, would_mask and mask disagree
Summary
On /mcp the guardrail scan (which decides block, and which monitor mode
previews as would_mask) and the guardrail rewrite (which actually masks)
run over different texts, in three different shapes. So a rule can block
without ever masking, mask without ever being able to block, and preview as
would-mask while enforcement does nothing — with no error and no signal in
telemetry.
The three texts
| what | text handed to the rules | source |
|---|---|---|
| input… |
Read the thread · 2026-08-22 · open · outside contributor · 1 comment
bug: field-name-anchored guardrail rules never fire for action=block on the /mcp output hook
Summary
On /mcp, a guardrail rule anchored on a JSON field name now works for
action: mask but silently never fires for action: block on the output
hook. Block is the stricter action, so the gap is fail-open.
Why the two hooks differ
| surface | code | key visible to the rule |
|---|---|---|
| input scan (block) | crates/aisix-proxy/src/mcp.rs — args.to_string() |
yes, compact "version":"12.1" |
| input + output mask | crates/aisix-proxy/src/redact.rs —… |
Read the thread · 2026-08-22 · closed · outside contributor · 1 comment
files surface: the batch-input blob is scanned lossy but forwarded verbatim — same skip-vs-forward asymmetry class as #1016
Surfaced by the #1020 audit (LOW, pre-existing, out of #1016's prompt-field scope).
/v1/files (jobs.rs): scan_input_blob runs the guardrail scan over String::from_utf8_lossy(&file_bytes), while create_file forwards the original bytes verbatim. The scan always runs (unlike the pre-#1020 prompt skip), but the same evasion argument applies: a keyword in a foreign encoding never appears in the lossy text, yet the original bytes still leave the boundary to the provider. A DLP block…
Read the thread · 2026-08-21 · closed · 1 comment
Harden MCP upstream transport: credentialed cleartext URLs and redirect policy
Surfaced by automated review on #875 (the finding anchors on new code, but the behavior is the long-standing shared bridge path used by both /mcp and /mcp/{server}).
Today RmcpBridge::connect accepts http:// upstream URLs for credentialed MCP servers, and the underlying HTTP client follows redirects. reqwest strips Authorization on cross-origin redirects, but custom credential headers (e.g. an api_key auth header) are not in its sensitive-header set, so a compromised/misconfigured…
Read the thread · 2026-08-04 · closed · outside contributor · 1 comment
bug: output guardrail error message echoes the matched forbidden literal back to caller
Summary
When an output guardrail with kind: "keyword" and hook_point: "output" blocks an upstream response containing a forbidden literal, the gateway's caller-visible error message includes the matched literal verbatim — defeating the purpose of an output guardrail (which exists precisely to keep forbidden content from reaching the caller).
Repro
E2E test attached: drafted as tests/e2e/src/cases/guardrail-output-e2e.test.ts (held back from #151 batch 2 PR pending this fix).…
Read the thread · 2026-05-09 · closed · 1 comment
guardrails: scan batch input files per record, not as one lossy text blob
Single record for guardrail coverage on the files surface. The issues that led here stay closed; this is the one place the decision lives.
Where it stands
Guardrails no longer apply to /v1/files at all — neither the upload nor the download, and neither does the refusal that was briefly built on top of them. Removed in #1121.
What still scans: the JSON request bodies of /v1/batches and /v1/fine_tuning/jobs. Those are structured requests the gateway understands, not user-uploaded…
Read the thread · 2026-09-03 · open · outside contributor · 0 comments
Most recent
guardrails: thinking and reasoning content is out of scope by comment only — mask never redacts it, and scan coverage differs per route
Found while documenting the buffered-scan behaviour for #1103, and verified separately against origin/main @ 45f4c327. This is not the parsing-boundary class #1103 tracks: these events are modelled and parsed. The text is deliberately not extracted.
Masking never touches thinking or reasoning content, on any route or mode. Four sites decide and all four omit it: redact_anthropic_content (redact.rs:426-457, _ => {} drops thinking), redact_chat_response (redact.rs:697),…
Read the thread · 2026-09-02 · closed · outside contributor · 0 comments
A stream aborted by the guardrail buffer cap reports guardrail_blocked with no policy named
Found by the independent pre-merge audit of #1028.
The gap
When a streamed response exceeds a guardrail's max_buffer_bytes and the row is configured on_buffer_exceeded: fail_closed, the gateway refuses the request — but no chain member ever returned a verdict, because the abort happens in the relay loop rather than in the fold:
crates/aisix-proxy/src/chat.rs(StreamOutputPolicy::BufferFull, theelsearm) setsguard.comp().guardrail_blocked = truedirectly; -…
Read the thread · 2026-08-22 · open · outside contributor · 0 comments
realtime: post-auth error usage events carry no caller attribution (api_key_id, jwt identity)
The realtime handler authenticates inside prepare() (WebSocket subprotocol auth, not the AuthenticatedKey extractor), so ClientContext never carries the resolved identity. When a request fails AFTER authentication succeeds (model forbidden, rate limited, …), the error-path usage event is emitted with an empty api_key_id — and, since #931, also without the new jwt_subject / jwt_provider / jwt_claim_mapping attribution fields. The success path attributes correctly from the resolved…
Read the thread · 2026-08-11 · closed · outside contributor · 0 comments
passthrough emits no UsageEvent at all (success or failure) — invisible to Logs, budget ledger and exporters
Found in the cross-endpoint parity audit following AISIX-Cloud#947 (see ai-gateway#695).
passthrough.rs records only AccessLog + record_request (~143-190). Passthrough traffic — success or failure — never appears in the UsageEvent stream, OTLP fan-out, budget ledger or per-PK telemetry. Token accounting absence is by design (raw tunnel, nothing parsed), but the complete absence of usage/failure events breaks the #655 convention every typed handler follows…
Read the thread · 2026-07-02 · closed · outside contributor · 0 comments
MCP: usage events never reach OTLP exporters; no access log / request metrics; no upstream timeout
Found in the cross-endpoint parity audit following AISIX-Cloud#947 (see ai-gateway#695).
Three parity gaps in mcp.rs relative to every other handler:
emit_tool_call_usagewrites only to the CP usage sink (state.usage_sink.try_emit(\"mcp\", event)at mcp.rs:310) — nootlp_fan_out.fan_out, so MCP usage never reaches any OTLP/SLS/Datadog exporter (every other emitter fans out, e.g. usage_attr.rs:137).- No
AccessLogand nometrics.record_requestanywhere in mcp.rs — /mcp…
Read the thread · 2026-07-02 · closed · outside contributor · 0 comments
P1-9: MCP gateway (registration, transports, auth, access control, cost tracking)
Problem
LiteLLM ships a full MCP (Model Context Protocol) gateway: register MCP servers, multiple transports (HTTP-streamable / SSE / stdio), auth methods (OAuth2 client-creds / AWS SigV4 for Bedrock AgentCore / API key / Bearer / Basic / static-headers), per-request `x-mcp-{server}-{header}` injection, access control by Key/Team/Org, server aliases, access groups, end-user attribution, semantic tool filtering, MCP cost tracking, MCP-specific guardrails, and auto-tool-execution…
Read the thread · 2026-04-26 · open · 0 comments
The remaining reports are on the project's issue tracker.