Skip to content

Guardrail API V2 - user api key metadata, session id, specify input type (request/response), image support - #17338

Merged
10 commits merged into
mainfrom
litellm_dev_12_01_2025_p1
Dec 2, 2025
Merged

Guardrail API V2 - user api key metadata, session id, specify input type (request/response), image support #17338
10 commits merged into
mainfrom
litellm_dev_12_01_2025_p1

Conversation

@ghost

@ghost ghost commented Dec 2, 2025

Copy link
Copy Markdown

Title

Guardrail API V2 - user api key metadata, session id, specify input type (request/response), image support

curl -X POST https://your-guardrail-api.com/beta/litellm_basic_guardrail_api \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "texts": [
      "Hello, can you help me with this task?"
    ],
    "images": null,
    "request_data": {
      "user_api_key_hash": "88dc28d0f030c55ed4ab77ed8faf098196cb1c05df778539800c9f1243fe6b4b",
      "user_api_key_alias": "production-key",
      "user_api_key_user_id": "user_12345",
      "user_api_key_user_email": "user@example.com",
      "user_api_key_team_id": "team_67890",
      "user_api_key_team_alias": "engineering-team",
      "user_api_key_end_user_id": "end_user_abc",
      "user_api_key_org_id": "org_xyz"
    },
    "input_type": "request",
    "litellm_call_id": "chatcmpl-123456789",
    "litellm_trace_id": "trace-abc-def-ghi",
    "additional_provider_specific_params": {
      "threshold": 0.8,
      "language": "en"
    }
  }'

Example Response (NONE):

{
  "action": "NONE"
}

Relevant issues

Make Guardrail API more useful for integration providers

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have Added testing in the tests/litellm/ directory, Adding at least 1 test is a hard requirement - see details
  • I have added a screenshot of my new test passing locally
  • My PR passes all unit tests on make test-unit
  • My PR's scope is as isolated as possible, it only solves 1 specific problem

Type

🆕 New Feature

Changes

@vercel

vercel Bot commented Dec 2, 2025

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
litellm Ready Ready Preview Comment Dec 2, 2025 4:13am


verbose_proxy_logger.debug(
"Generic Guardrail API: Extracted user metadata: %s",
{k: v for k, v in result_metadata.items() if v is not None},

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This expression logs
sensitive data (password)
as clear text.

Copilot Autofix

AI 9 months ago

To address the issue, only non-sensitive fields should be included in logging. This can be achieved by constructing a filtered dictionary excluding sensitive keys from the log output. Sensitive fields commonly include "user_api_key_hash", "user_api_key_token", "user_api_key" and any other fields related to authentication secrets, including all values in the "GenericGuardrailAPIMetadata" that could be used for authentication or authorization.

Key changes:

  • In the log statement (line 140), instead of logging all key-values, construct a dictionary excluding sensitive keys such as "user_api_key_hash", "user_api_key_token" and similar.
  • Ideally, define a list of sensitive keys, and filter them out from the logged dictionary.
  • Only modify the specific lines responsible for logging (lines 138–141).
  • No outside dependencies are needed; standard Python is sufficient.
  • You may need to add a helper in the function to perform the filtering.

Suggested changeset 1
litellm/proxy/guardrails/guardrail_hooks/generic_guardrail_api/generic_guardrail_api.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/litellm/proxy/guardrails/guardrail_hooks/generic_guardrail_api/generic_guardrail_api.py b/litellm/proxy/guardrails/guardrail_hooks/generic_guardrail_api/generic_guardrail_api.py
--- a/litellm/proxy/guardrails/guardrail_hooks/generic_guardrail_api/generic_guardrail_api.py
+++ b/litellm/proxy/guardrails/guardrail_hooks/generic_guardrail_api/generic_guardrail_api.py
@@ -135,9 +135,16 @@
                 "user_api_key_token"
             )
 
+        # Define sensitive fields to mask or filter out from logging
+        SENSITIVE_KEYS = {
+            "user_api_key_hash",
+            "user_api_key_token",
+            "user_api_key",
+        }
+        safe_metadata = {k: v for k, v in result_metadata.items() if v is not None and k not in SENSITIVE_KEYS}
         verbose_proxy_logger.debug(
-            "Generic Guardrail API: Extracted user metadata: %s",
-            {k: v for k, v in result_metadata.items() if v is not None},
+            "Generic Guardrail API: Extracted user metadata (non-sensitive fields only): %s",
+            safe_metadata,
         )
 
         return result_metadata
EOF
@@ -135,9 +135,16 @@
"user_api_key_token"
)

# Define sensitive fields to mask or filter out from logging
SENSITIVE_KEYS = {
"user_api_key_hash",
"user_api_key_token",
"user_api_key",
}
safe_metadata = {k: v for k, v in result_metadata.items() if v is not None and k not in SENSITIVE_KEYS}
verbose_proxy_logger.debug(
"Generic Guardrail API: Extracted user metadata: %s",
{k: v for k, v in result_metadata.items() if v is not None},
"Generic Guardrail API: Extracted user metadata (non-sensitive fields only): %s",
safe_metadata,
)

return result_metadata
Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines +53 to +55
f"""send_user_api_key_alias: {self.send_user_api_key_alias},
send_user_api_key_user_id:{self.send_user_api_key_user_id},
send_user_api_key_team_id:{self.send_user_api_key_team_id}'''
send_user_api_key_team_id:{self.send_user_api_key_team_id}"""

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (password)
as clear text.

Copilot Autofix

AI 9 months ago

The best way to fix this is to avoid logging the specific values of the flags associated with user API key handling (send_user_api_key_alias, send_user_api_key_user_id, and send_user_api_key_team_id). Instead, you can log that these flags are set (e.g., "Configured", "Not configured") without disclosing exact values, or simply avoid logging them altogether. The code to change is within the constructor (__init__) of ZscalerAIGuard, specifically the call to verbose_proxy_logger.debug on line 52-56.
Recommended fix: Replace the f-string logging statement with a generic message such as "User API key flags configured" or remove it altogether.
No additional imports or definitions are required; just change or remove the problematic debug log in the constructor.

Suggested changeset 1
litellm/proxy/guardrails/guardrail_hooks/zscaler_ai_guard/zscaler_ai_guard.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/litellm/proxy/guardrails/guardrail_hooks/zscaler_ai_guard/zscaler_ai_guard.py b/litellm/proxy/guardrails/guardrail_hooks/zscaler_ai_guard/zscaler_ai_guard.py
--- a/litellm/proxy/guardrails/guardrail_hooks/zscaler_ai_guard/zscaler_ai_guard.py
+++ b/litellm/proxy/guardrails/guardrail_hooks/zscaler_ai_guard/zscaler_ai_guard.py
@@ -50,9 +50,7 @@
         ).lower() in ("true", "1")
 
         verbose_proxy_logger.debug(
-            f"""send_user_api_key_alias: {self.send_user_api_key_alias}, 
-            send_user_api_key_user_id:{self.send_user_api_key_user_id}, 
-            send_user_api_key_team_id:{self.send_user_api_key_team_id}"""
+            "User API key flags are set; not displaying their values for security."
         )
 
         super().__init__(default_on=True)
EOF
@@ -50,9 +50,7 @@
).lower() in ("true", "1")

verbose_proxy_logger.debug(
f"""send_user_api_key_alias: {self.send_user_api_key_alias},
send_user_api_key_user_id:{self.send_user_api_key_user_id},
send_user_api_key_team_id:{self.send_user_api_key_team_id}"""
"User API key flags are set; not displaying their values for security."
)

super().__init__(default_on=True)
Copilot is powered by AI and may make mistakes. Always verify output.
verbose_proxy_logger.debug(
f"extra_headers: {extra_headers}"
)
verbose_proxy_logger.debug(f"extra_headers: {extra_headers}")

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (password)
as clear text.

Copilot Autofix

AI 9 months ago

The best way to fix the problem is to ensure that when logging extra_headers, any header values that are sensitive (such as Authorization or any headers that may contain user API keys) are masked or excluded before logging. We will create a sanitized/shallow-copied version of extra_headers for logging purposes.
Steps:

  • In _prepare_headers, before logging extra_headers, create a copy of the dict where the values for sensitive keys (like "Authorization") are replaced with a safe placeholder, e.g., "****".
  • Only log this sanitized dict instead of the full one.
  • This involves adding a small helper/snippet directly before the log line in _prepare_headers.
  • No external imports are required, only built-in features.
Suggested changeset 1
litellm/proxy/guardrails/guardrail_hooks/zscaler_ai_guard/zscaler_ai_guard.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/litellm/proxy/guardrails/guardrail_hooks/zscaler_ai_guard/zscaler_ai_guard.py b/litellm/proxy/guardrails/guardrail_hooks/zscaler_ai_guard/zscaler_ai_guard.py
--- a/litellm/proxy/guardrails/guardrail_hooks/zscaler_ai_guard/zscaler_ai_guard.py
+++ b/litellm/proxy/guardrails/guardrail_hooks/zscaler_ai_guard/zscaler_ai_guard.py
@@ -194,7 +194,12 @@
             user_api_key_user_id = kwargs.get("user-api-key-user-id", "N/A")
             extra_headers.update({"user-api-key-user-id": user_api_key_user_id})
 
-        verbose_proxy_logger.debug(f"extra_headers: {extra_headers}")
+        # Log a sanitized version of extra_headers with sensitive headers masked
+        sanitized_headers = extra_headers.copy()
+        for key in sanitized_headers:
+            if key.lower() == "authorization":
+                sanitized_headers[key] = "***"
+        verbose_proxy_logger.debug(f"extra_headers: {sanitized_headers}")
         return extra_headers
 
     async def _send_request(self, url, headers, data):
EOF
@@ -194,7 +194,12 @@
user_api_key_user_id = kwargs.get("user-api-key-user-id", "N/A")
extra_headers.update({"user-api-key-user-id": user_api_key_user_id})

verbose_proxy_logger.debug(f"extra_headers: {extra_headers}")
# Log a sanitized version of extra_headers with sensitive headers masked
sanitized_headers = extra_headers.copy()
for key in sanitized_headers:
if key.lower() == "authorization":
sanitized_headers[key] = "***"
verbose_proxy_logger.debug(f"extra_headers: {sanitized_headers}")
return extra_headers

async def _send_request(self, url, headers, data):
Copilot is powered by AI and may make mistakes. Always verify output.
@ghost
ghost merged commit 4c7a988 into main Dec 2, 2025
8 of 11 checks passed
@ghost
ghost deleted the litellm_dev_12_01_2025_p1 branch December 2, 2025 04:12
fzowl pushed a commit to fzowl/litellm that referenced this pull request Jun 24, 2026
…ype (request/response), image support (BerriAI#17338)

* refactor(generic_guardrail_api.py): refactor to update to new guardrail api logic

* refactor: refactor llm api integrations to support passing in text as a list[str] instead of one at a time

* refactor: fix linting errors

* refactor: pass request type to guardrail api

allows request vs. response processing to occur

* feat: pass user api key dict information to the guardrail api

* fix: pass user api key dict information to the guardrail api

* feat: pass litellm call id + trace id, if present

* docs: update docs
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant