Skip to content

Guardrails silently skipped on /v1/completions, /v1/images, /v1/rerank (same bypass class as #719) #545

Description

@moonming

Summary

#719 closed the guardrail-bypass on /v1/responses and /v1/embeddings (input) + /v1/responses (output). While auditing inbound surfaces for #719, three more text-bearing surfaces were found to invoke no guardrails at all — the same content-block bypass class:

Surface Scannable user text Guardrail invocation (origin/main)
/v1/completions prompt none (completions.rs: 0 guardrail refs)
/v1/images prompt none (images.rs: 0 guardrail refs)
/v1/rerank query + documents none (rerank.rs: 0 guardrail refs)

A customer who configures an input content/DLP block on /v1/chat/completions can still bypass it by sending the same text to any of these surfaces. This is the gap #379's checklist anticipated ("All inbound API surfaces … each runs configured guardrail").

Scope to verify / fix

  • /v1/completions runs input guardrails on prompt
  • /v1/images runs input guardrails on prompt
  • /v1/rerank runs input guardrails on query + documents
  • output guardrails where the surface returns scannable text (/v1/completions text, /v1/rerank is scores — likely N/A; /v1/images returns image data — N/A)

Approach

Same pattern as the #719 fix: resolve the per-request chain (RequestContext { model_id, api_key_id, team_id }), synthesize a ChatFormat from the surface's text fields, run check_input before dispatch; Block → 422 content_filter. /v1/messages, /v1/chat/completions, /v1/responses, /v1/embeddings already do this after the #719 PRs (#541, #544).

audio.rs (audio input, not text), count_tokens.rs (no model call), and passthrough.rs (generic) are excluded.

Surfaced while implementing #719. Refs #719, #379.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions