Skip to content

bug: ai-prompt-guard returns an empty 200 instead of proxying when no content is selected for checking #13944

Description

@Santoshkumarpuppala

Raised on #13731 at the maintainers' request, split out from that docs PR.

Current Behavior

When the set of messages selected for checking is empty, ai-prompt-guard returns 200 from _M.access (apisix/plugins/ai-prompt-guard.lua:162-164). plugin.lua:1406-1419 hands any non-nil code to core.response.exit, and core/response.lua:126-134 calls ngx_exit(code) for any code — the >= 400 branch only adds tracing. The client gets an empty 200 and the upstream is never called.

Two ordinary requests reach it:

  • match_all_roles left at its default false (ai-prompt-guard.lua:38-41) and no user message in the request, e.g. only a system message. Non-user messages are filtered out (:152-154), the list is empty, and the request is answered with an empty 200. No non-default configuration is needed to reach this.
  • Embeddings with input as an array of strings. ai-protocols/openai-embeddings.lua:109-117 only collects a string input, so an array yields {}.

The repo already uses both meanings of the return value: cors.lua:338-339 returns 200 deliberately to end an OPTIONS preflight, and ai-lakera-guard.lua:104-105 uses a bare return for the same "no messages" condition and lets the request continue.

Nothing is logged: the warn at plugin.lua:1408-1409 only fires for codes >= 400.

Expected Behavior

Nothing to check should mean pass through to the upstream, as ai-lakera-guard does. The fix is return instead of return 200.

The tests don't catch this. t/plugin/ai-prompt-guard.t TEST 9 (line 243, "send request with bad word and it will pass for non user") is exactly the first case — its route, from TEST 8, sets only allow_patterns and leaves match_all_roles at the default — and it asserts neither --- response_body nor --- error_code, so it passes whether the request was proxied or cut off. TESTs 3, 6, 14, 20, 23 and 26 have the same gap. Adding --- response_body / hello world (t/lib/server.lua:74-79) would make them discriminate, following t/plugin/ai-lakera-guard.t, which already asserts --- error_code: 200 with --- response_body_like on its allow paths.

Error Logs

None — see the note on logging above.

Steps to Reproduce

  1. Use the route from TEST 8 in t/plugin/ai-prompt-guard.t (only allow_patterns set; match_all_roles at its default).
  2. Add --- response_body with hello world to TEST 9.
  3. Run prove t/plugin/ai-prompt-guard.t — TEST 9 should fail on current master, and pass once return 200 becomes return.

Environment

master at d13105e17 (2026-09-14). Traced from source, not run — I don't have an APISIX test environment set up, so treat the reproduction above as the expected result rather than an observed one.

Happy to open the PR with the one-line fix and the test assertions.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions