fix(logging): redact Gemini/Vertex native input fields in request-body snapshots

This commit is contained in:
michelligabriele 2026-06-08 19:22:53 +02:00
parent 4d1c83ffc2
commit 11da9d0a4b
No known key found for this signature in database
2 changed files with 79 additions and 3 deletions

View file

@ -168,9 +168,11 @@ def _redact_standard_logging_object(model_call_details: dict):
# Input-bearing keys that show up in request-body snapshots
# (proxy_server_request.body and additional_args.complete_input_dict).
# "messages"/"prompt"/"input" are the OpenAI-style payload entry points;
# "contents" is the Gemini/Vertex native user-turn field.
# "system"/"system_prompt"/"instructions" are the provider-native top-level
# system-prompt fields (Anthropic `system`, Responses API `instructions`),
# which carry user content just as the messages do.
# system-prompt fields (Anthropic `system`, Responses API `instructions`);
# "system_instruction"/"systemInstruction" are the Gemini/Vertex equivalents.
# All carry user content just as the messages do.
def _redact_request_body_dict(body: dict):
"""Scrub the input/system-prompt keys on a materialised request-body dict."""
if "messages" in body:
@ -179,7 +181,17 @@ def _redact_request_body_dict(body: dict):
body["prompt"] = ""
if "input" in body:
body["input"] = ""
for key in ("system", "system_prompt", "instructions"):
if "contents" in body:
body["contents"] = [
{"role": "user", "parts": [{"text": "redacted-by-litellm"}]}
]
for key in (
"system",
"system_prompt",
"instructions",
"system_instruction",
"systemInstruction",
):
if key in body:
body[key] = "redacted-by-litellm"

View file

@ -592,3 +592,67 @@ class TestPerformRedaction:
assert cid["system"] == "redacted-by-litellm"
assert cid["system_prompt"] == "redacted-by-litellm"
assert cid["instructions"] == "redacted-by-litellm"
def test_redacts_gemini_native_fields_in_complete_input_dict(self):
"""Gemini/Vertex wire-format requests carry the user turn in `contents`
and the system prompt in `system_instruction` / `systemInstruction`,
not the OpenAI-style `messages` / `system` keys — these provider-native
fields must be scrubbed from the wire-format request snapshot too."""
details = {
"additional_args": {
"complete_input_dict": {
"model": "gemini-2.0-flash",
"contents": [
{
"role": "user",
"parts": [{"text": "CANARY_INPUT_should_be_redacted"}],
}
],
"system_instruction": {
"parts": [{"text": "CANARY_SYSTEM_should_be_redacted"}]
},
"systemInstruction": {
"parts": [{"text": "CANARY_SYSTEM_should_be_redacted"}]
},
}
}
}
perform_redaction(details, None)
cid = details["additional_args"]["complete_input_dict"]
assert cid["contents"] == [
{"role": "user", "parts": [{"text": "redacted-by-litellm"}]}
]
assert cid["system_instruction"] == "redacted-by-litellm"
assert cid["systemInstruction"] == "redacted-by-litellm"
def test_redacts_gemini_native_fields_in_proxy_server_request_body(self):
"""Same Gemini/Vertex native input fields can also land in the proxy
body snapshot — `contents` / `system_instruction` must be scrubbed."""
details = {
"litellm_params": {
"proxy_server_request": {
"body": {
"model": "gemini-2.0-flash",
"contents": [
{
"role": "user",
"parts": [{"text": "CANARY_INPUT_should_be_redacted"}],
}
],
"system_instruction": {
"parts": [{"text": "CANARY_SYSTEM_should_be_redacted"}]
},
}
}
},
}
perform_redaction(details, None)
body = details["litellm_params"]["proxy_server_request"]["body"]
assert body["contents"] == [
{"role": "user", "parts": [{"text": "redacted-by-litellm"}]}
]
assert body["system_instruction"] == "redacted-by-litellm"