Skip to content

Litellm oss staging 04 01 2026 - #24958

Closed
krrish-berri-2 wants to merge 10 commits into
litellm_internal_stagingfrom
litellm_oss_staging_04_01_2026
Closed

Litellm oss staging 04 01 2026#24958
krrish-berri-2 wants to merge 10 commits into
litellm_internal_stagingfrom
litellm_oss_staging_04_01_2026

Conversation

@krrish-berri-2

Copy link
Copy Markdown
Contributor

Relevant issues

Pre-Submission checklist

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

  • I have Added testing in the tests/test_litellm/ directory, Adding at least 1 test is a hard requirement - see details
  • 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
  • I have requested a Greptile review by commenting @greptileai and received a Confidence Score of at least 4/5 before requesting a maintainer review

Delays in PR merge?

If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).

CI (LiteLLM team)

CI status guideline:

  • 50-55 passing tests: main is stable with minor issues.
  • 45-49 passing tests: acceptable but needs attention
  • <= 40 passing tests: unstable; be careful with your merges and assess the risk.
  • Branch creation CI run
    Link:

  • CI run for the last commit
    Link:

  • Merge / cherry-pick CI run
    Links:

Type

🆕 New Feature
🐛 Bug Fix
🧹 Refactoring
📖 Documentation
🚄 Infrastructure
✅ Test

Changes

krrish-berri-2 and others added 7 commits April 1, 2026 19:32
…error traces (#24943)

* fix(proxy): use actual request start_time for failed spend logs

async_post_call_failure_hook was calling datetime.now() for both
start_time and end_time, making every failed request show Duration: 0.000s.

litellm_logging_obj (already fetched in the same method for trace ID
propagation) carries the real request start_time — use it as
actual_start_time with a datetime.now() fallback when absent.

Add two regression tests covering the fix and the fallback path.

Fixes #24888

* fix(llm translation): redact Gemini API key from URL query params in error traces

Gemini API requests authenticate via a ?key=<api_key> URL query param.
When a provider call fails, httpx.Response.raise_for_status() embeds the full
URL in the error message, leaking the key in exception traces and logs.

Changes:
- Extract secret-redaction logic from litellm/_logging.py into a new public
  utility module litellm/litellm_core_utils/secret_redaction.py, exposing
  redact_string() as a proper public API instead of a private helper
- Add (?<=[?&])key=[^\s&'"]{8,} pattern to _SECRET_RE so ?key=VALUE and
  &key=VALUE fragments are caught by the existing SecretRedactionFilter
- Apply redact_string() to error_str in exception_mapping_utils.py so the
  key is also stripped from the mapped exception message surfaced to callers
- Add 5 regression tests covering: ?key=, &key=, short-value no-op, httpx
  raise_for_status path, and end-to-end logger output
- Keep _redact_string = redact_string alias in _logging.py for backward compat

Fixes #24902

* revert: undo start_time fix for failed spend logs

* fix: gate exception redaction on _ENABLE_SECRET_REDACTION opt-out flag

- Apply redact_string() conditionally in exception_mapping_utils.py,
  matching the same _ENABLE_SECRET_REDACTION guard used by SecretRedactionFilter
  so that LITELLM_DISABLE_REDACT_SECRETS=true is honoured for exception messages
- Rewrite test_redact_string_applied_to_httpx_error_message to use pytest.raises
  so assertions cannot be silently skipped if raise_for_status() doesn't raise
- Add test_exception_mapping_respects_redaction_opt_out to verify the flag is
  respected end-to-end through exception_type()
* feat: added Qohash Nexus guardrail hook

* fix: ui_friendly_name of Qostodian Nexus

* Update litellm/proxy/guardrails/guardrail_hooks/qohash/qohash.py

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Update litellm/proxy/guardrails/guardrail_hooks/qohash/qohash.py

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
…ion (#24926)

service_tier (priority/flex) was not forwarded to generic_cost_per_token
for azure and azure_ai providers, so tier-specific pricing was ignored
and standard pricing was always returned. Other providers (openai,
bedrock, gemini, vertex_ai) already pass it correctly.
…PM (#24925)

Join LiteLLM_BudgetTable as b_tm on team membership budget_id and select
team_member_tpm_limit / team_member_rpm_limit so virtual key auth populates
limits for parallel_request_limiter_v3.

Add test_team_member_rate_limits_v3_raises_429_when_over_limit mirroring
existing key-level OVER_LIMIT / HTTP 429 coverage.

Made-with: Cursor
* fix(gemini): handle Gemini Files API URIs without fetching

Fixes #24907

When a file is uploaded via the Gemini Files API, the returned URI
(https://generativelanguage.googleapis.com/v1beta/files/...) starts
with 'https://' and hits the generic HTTPS handler in
_process_gemini_media(). That handler calls
_get_image_mime_type_from_url() which tries to fetch the URL — but
Gemini Files API URLs return 403 when accessed directly, causing:
  'Unable to determine mime type for file_id: ...'

Fix: add an early elif that matches Gemini Files API URLs and passes
them through as file_data without trying to fetch the URL. When an
explicit format is provided it's included; otherwise the Gemini API
infers the MIME type from its stored metadata.

Exactly matches the fix direction suggested by the issue reporter
(rodriciru).

* fix: anchor Gemini Files API URL check with startswith

Address greptile P2: replace `in` substring check with `startswith`
to prevent query-string injection bypass (e.g.
`https://evil.com/?ref=https://generativelanguage...`).

Also adds trailing slash to match only valid file URIs.

---------

Co-authored-by: voidborne-d <voidborne-d@users.noreply.github.com>
…v1 endpoints (#24911)

When aembedding=True, api_version was not passed to self.aembedding(), causing
get_azure_openai_client() to receive None instead of "v1". This made
_is_azure_v1_api_version() return False, so AsyncAzureOpenAI was selected
instead of AsyncOpenAI, constructing the wrong request URL and returning 404.

Fixes #24848

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel

vercel Bot commented Apr 2, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
litellm Ready Ready Preview, Comment Apr 16, 2026 1:11pm

Request Review

@CLAassistant

CLAassistant commented Apr 2, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
6 out of 8 committers have signed the CLA.

✅ michelligabriele
✅ mats852
✅ Vedanshu7
✅ yuneng-berri
✅ milan-berri
✅ Sameerlite
❌ krrish-berri-2
❌ voidborne-d
You have signed the CLA already but the status is still pending? Let us recheck it.

@codspeed-hq

codspeed-hq Bot commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 16 untouched benchmarks


Comparing litellm_oss_staging_04_01_2026 (012f470) with main (d1df4e8)

Open in CodSpeed

Comment on lines +20 to +21
r"(?:aws_secret_access_key|aws_session_token|aws_access_key_id)"
r"\s*[:=]\s*[A-Za-z0-9/+=]{20,}",

Check warning

Code scanning / CodeQL

Implicit string concatenation in a list Warning

Implicit string concatenation. Maybe missing a comma?

Copilot Autofix

AI 5 months ago

In general, to fix this type of issue, any place where two adjacent string literals are meant to be concatenated should use an explicit + operator (or other explicit joining, like ''.join([...])). This preserves the runtime string value but makes the intention clear and avoids confusion with missing commas in lists or tuples.

For this specific case in litellm/litellm_core_utils/secret_redaction.py, we want to keep the regex pattern as a single element in the patterns list, but make its multi-line nature explicit. On lines 20–21, we should add a trailing + at the end of the first line so it reads like:

r"(?:aws_secret_access_key|aws_session_token|aws_access_key_id)" +
r"\s*[:=]\s*[A-Za-z0-9/+=]{20,}",

This leaves the compiled regex unchanged, avoids any missing-comma confusion, and satisfies the CodeQL recommendation. No additional imports, methods, or definitions are required, and no other parts of the file need modification.

Suggested changeset 1
litellm/litellm_core_utils/secret_redaction.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/litellm_core_utils/secret_redaction.py b/litellm/litellm_core_utils/secret_redaction.py
--- a/litellm/litellm_core_utils/secret_redaction.py
+++ b/litellm/litellm_core_utils/secret_redaction.py
@@ -17,7 +17,7 @@
         # AWS access key IDs
         r"(?:AKIA|ASIA)[0-9A-Z]{16}",
         # AWS secrets / session tokens / access key IDs (key=value)
-        r"(?:aws_secret_access_key|aws_session_token|aws_access_key_id)"
+        r"(?:aws_secret_access_key|aws_session_token|aws_access_key_id)" +
         r"\s*[:=]\s*[A-Za-z0-9/+=]{20,}",
         # Bearer tokens (OAuth, JWT, etc.)
         r"Bearer\s+[A-Za-z0-9\-._~+/]{10,}=*",
EOF
@@ -17,7 +17,7 @@
# AWS access key IDs
r"(?:AKIA|ASIA)[0-9A-Z]{16}",
# AWS secrets / session tokens / access key IDs (key=value)
r"(?:aws_secret_access_key|aws_session_token|aws_access_key_id)"
r"(?:aws_secret_access_key|aws_session_token|aws_access_key_id)" +
r"\s*[:=]\s*[A-Za-z0-9/+=]{20,}",
# Bearer tokens (OAuth, JWT, etc.)
r"Bearer\s+[A-Za-z0-9\-._~+/]{10,}=*",
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Comment on lines +40 to +41
r"\w*(?:password|passwd|client_secret|secret_key|_secret)"
r"['\"]?\s*[:=]\s*['\"]?[^\s,'\"})\]{}>]+",

Check warning

Code scanning / CodeQL

Implicit string concatenation in a list Warning

Implicit string concatenation. Maybe missing a comma?

Copilot Autofix

AI 4 months ago

Use explicit concatenation (+) for intentionally split string literals inside the patterns list.

Best fix here: in litellm/litellm_core_utils/secret_redaction.py, update the pattern at lines 40–41 so the two raw string literals are joined with +. This preserves exact functionality while making intent explicit and removing the CodeQL finding. No imports, methods, or new definitions are needed.

Suggested changeset 1
litellm/litellm_core_utils/secret_redaction.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/litellm_core_utils/secret_redaction.py b/litellm/litellm_core_utils/secret_redaction.py
--- a/litellm/litellm_core_utils/secret_redaction.py
+++ b/litellm/litellm_core_utils/secret_redaction.py
@@ -37,7 +37,7 @@
         # full "key=<secret>" fragment so the value is redacted regardless of format.
         r"(?<=[?&])key=[^\s&'\"]{8,}",
         # Password / secret params (handles key=value and 'key': 'value')
-        r"\w*(?:password|passwd|client_secret|secret_key|_secret)"
+        r"\w*(?:password|passwd|client_secret|secret_key|_secret)" +
         r"['\"]?\s*[:=]\s*['\"]?[^\s,'\"})\]{}>]+",
         # Database connection string credentials (scheme://user:pass@host)
         r"(?<=://)[^\s'\"]*:[^\s'\"@]+(?=@)",
EOF
@@ -37,7 +37,7 @@
# full "key=<secret>" fragment so the value is redacted regardless of format.
r"(?<=[?&])key=[^\s&'\"]{8,}",
# Password / secret params (handles key=value and 'key': 'value')
r"\w*(?:password|passwd|client_secret|secret_key|_secret)"
r"\w*(?:password|passwd|client_secret|secret_key|_secret)" +
r"['\"]?\s*[:=]\s*['\"]?[^\s,'\"})\]{}>]+",
# Database connection string credentials (scheme://user:pass@host)
r"(?<=://)[^\s'\"]*:[^\s'\"@]+(?=@)",
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Comment on lines +50 to +56
r"(?:master_key|database_url|db_url|connection_string|"
r"private_key|signing_key|encryption_key|"
r"auth_token|access_token|refresh_token|"
r"slack_webhook_url|webhook_url|"
r"database_connection_string|"
r"huggingface_token|jwt_secret)"
r"""['\"]?\s*[:=]\s*['\"]?[^\s,'\"})\]{}>]+""",

Check warning

Code scanning / CodeQL

Implicit string concatenation in a list Warning

Implicit string concatenation. Maybe missing a comma?

Copilot Autofix

AI 5 months ago

In general, to fix “implicit string concatenation in a list” when the concatenation is intentional, explicitly join the string literals with + so it’s clear that they form one element, rather than being separate elements accidentally merged by omission of a comma. If the concatenation is not intended, instead insert the missing comma to create distinct list elements.

For this specific case in litellm/litellm_core_utils/secret_redaction.py, the long regex for key-name-based redaction (lines 50–56) is meant to be a single pattern. To retain behavior while satisfying the recommendation and avoiding ambiguity, we should convert the multiple adjacent raw string literals into a single concatenated expression using +, optionally keeping line breaks for readability. We must preserve the exact pattern text, including the closing parenthesis and subsequent character-class portion starting at line 56. The change is confined to the patterns list in _build_secret_patterns; no new imports, methods, or external dependencies are needed.

Concretely, replace the current block:

  • from line 50: r"(?:master_key|database_url|db_url|connection_string|"
  • through line 56: r"""['\"]?\s*[:=]\s*['\"]?[^\s,'\"})\]{}>]+""",

with a single expression where each part is joined by +, keeping the exact same regex content, e.g.:

r"(?:master_key|database_url|db_url|connection_string|"
+ r"private_key|signing_key|encryption_key|"
+ r"auth_token|access_token|refresh_token|"
+ r"slack_webhook_url|webhook_url|"
+ r"database_connection_string|"
+ r"huggingface_token|jwt_secret)"
+ r"""['\"]?\s*[:=]\s*['\"]?[^\s,'\"})\]{}>]+""",

No other lines in the file need adjustment.

Suggested changeset 1
litellm/litellm_core_utils/secret_redaction.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/litellm_core_utils/secret_redaction.py b/litellm/litellm_core_utils/secret_redaction.py
--- a/litellm/litellm_core_utils/secret_redaction.py
+++ b/litellm/litellm_core_utils/secret_redaction.py
@@ -48,12 +48,12 @@
         # regardless of what the value looks like.
         # e.g. 'master_key': 'any-value-here', "database_url": "postgres://..."
         r"(?:master_key|database_url|db_url|connection_string|"
-        r"private_key|signing_key|encryption_key|"
-        r"auth_token|access_token|refresh_token|"
-        r"slack_webhook_url|webhook_url|"
-        r"database_connection_string|"
-        r"huggingface_token|jwt_secret)"
-        r"""['\"]?\s*[:=]\s*['\"]?[^\s,'\"})\]{}>]+""",
+        + r"private_key|signing_key|encryption_key|"
+        + r"auth_token|access_token|refresh_token|"
+        + r"slack_webhook_url|webhook_url|"
+        + r"database_connection_string|"
+        + r"huggingface_token|jwt_secret)"
+        + r"""['\"]?\s*[:=]\s*['\"]?[^\s,'\"})\]{}>]+""",
     ]
     return re.compile("|".join(patterns), re.IGNORECASE)
 
EOF
@@ -48,12 +48,12 @@
# regardless of what the value looks like.
# e.g. 'master_key': 'any-value-here', "database_url": "postgres://..."
r"(?:master_key|database_url|db_url|connection_string|"
r"private_key|signing_key|encryption_key|"
r"auth_token|access_token|refresh_token|"
r"slack_webhook_url|webhook_url|"
r"database_connection_string|"
r"huggingface_token|jwt_secret)"
r"""['\"]?\s*[:=]\s*['\"]?[^\s,'\"})\]{}>]+""",
+ r"private_key|signing_key|encryption_key|"
+ r"auth_token|access_token|refresh_token|"
+ r"slack_webhook_url|webhook_url|"
+ r"database_connection_string|"
+ r"huggingface_token|jwt_secret)"
+ r"""['\"]?\s*[:=]\s*['\"]?[^\s,'\"})\]{}>]+""",
]
return re.compile("|".join(patterns), re.IGNORECASE)

Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
@greptile-apps

greptile-apps Bot commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR bundles several fixes and a new Qostodian Nexus guardrail integration: Gemini Files API 403 fix, Azure AI Foundry embedding api_version forwarding, service_tier cost propagation, team-member rate limit data in the key-lookup SQL join, and a new standalone secret-redaction module that scrubs API keys from exception messages.

  • P0: litellm/types/guardrails.py line 35 — missing ) in the qohash import block causes SyntaxError: '(' was never closed, preventing the module from loading.
  • P0: litellm/_logging.py line 27 — import re was removed but _build_secret_patterns() still references re.Pattern in its annotation and calls re.compile(), causing a NameError that crashes LiteLLM at startup.

Confidence Score: 4/5

Not safe to merge — two P0 bugs prevent LiteLLM from starting up.

Two P0 findings: a SyntaxError in guardrails.py (unclosed parenthesis in import) and a NameError in _logging.py (import re removed but still used at definition time). Both are confirmed to crash module loading. The fixes are one-liners each, but must be applied before this can ship.

litellm/types/guardrails.py (line 35, SyntaxError) and litellm/_logging.py (line 27, NameError on missing import re)

Important Files Changed

Filename Overview
litellm/types/guardrails.py P0 SyntaxError: missing ) in qohash import on line 35-37 prevents the module from loading entirely.
litellm/_logging.py P0: import re removed but _build_secret_patterns() still references re.Pattern (return annotation) and re.compile() (body), causing NameError at module load; redact_string imported from secret_redaction but unused.
litellm/litellm_core_utils/secret_redaction.py New standalone redaction utility module; adds URL query-param key pattern to fix Gemini API key exposure in httpx error messages.
litellm/proxy/guardrails/guardrail_hooks/qohash/qohash.py New Qostodian Nexus guardrail wrapping GenericGuardrailAPI; defaults to HTTP for the API base; pass-through apply_guardrail override needed for proxy/utils.py detection is well-commented.
litellm/llms/vertex_ai/gemini/transformation.py Adds early-exit branch for Gemini Files API URIs to avoid 403 HTTP fetch; correctly passes file_uri with optional mime_type through to the Gemini API.
litellm/proxy/utils.py Extends existing raw SQL to LEFT JOIN LiteLLM_BudgetTable for team-member TPM/RPM limits; JOIN condition matches schema (budget_id exists on LiteLLM_TeamMembership).
litellm/llms/azure/cost_calculation.py Adds service_tier parameter to enable priority/flex pricing tiers; threaded through from cost_calculator.py correctly.
litellm/llms/azure/azure.py Fixes missing api_version forwarding to aembedding() call for Azure AI Foundry v1 endpoints.
litellm/litellm_core_utils/exception_mapping_utils.py Applies redact_string() to exception messages when secret redaction is enabled, fixing the Gemini API key leak via raised exceptions.

Class Diagram

%%{init: {'theme': 'neutral'}}%%
classDiagram
    class GenericGuardrailAPI {
        +api_base: str
        +extra_headers: list
        +apply_guardrail(inputs, request_data, input_type, logging_obj)
        +get_config_model() Type
    }

    class QostodianNexus {
        +GUARDRAIL_NAME: str
        +__init__(api_base, **kwargs)
        +apply_guardrail(inputs, request_data, input_type, logging_obj)
        +get_config_model() QostodianNexusConfigModel
    }

    class QostodianNexusConfigModel {
        +api_base: Optional[str]
        +ui_friendly_name() str
    }

    class GuardrailConfigModel {
        <<base>>
    }

    class SupportedGuardrailIntegrations {
        <<enum>>
        QOSTODIAN_NEXUS
    }

    GenericGuardrailAPI <|-- QostodianNexus
    GuardrailConfigModel <|-- QostodianNexusConfigModel
    QostodianNexus ..> QostodianNexusConfigModel : get_config_model()
    QostodianNexus ..> SupportedGuardrailIntegrations : registered as
Loading

Comments Outside Diff (1)

  1. litellm/_logging.py, line 27 (link)

    P0 NameError at module load — import re removed but still used

    This PR removes import re from _logging.py, but _build_secret_patterns() still uses re.Pattern in the return-type annotation (line 27) and re.compile / re.IGNORECASE in the body (line 82). In Python 3.11, function annotations are evaluated eagerly at definition time, so the module will crash with NameError: name 're' is not defined the moment Python processes line 27 — before any LiteLLM code can run.

    Verified with exec:

    def foo() -> re.Pattern:
        pass
    # → NameError: name 're' is not defined

    The fix is simply to restore the removed import, or quote the annotation:

    Or add import re back to the imports section. The redact_string import from secret_redaction (added on line 11) is currently unused in this module — if the intent was to delegate to that function, the existing _redact_string / _SECRET_RE must also be removed or kept alongside the restored import re.

Reviews (3): Last reviewed commit: "Merge branch 'main' into litellm_oss_sta..." | Re-trigger Greptile

api_base: Optional[str] = None,
**kwargs,
):
api_base = api_base or os.environ.get("QOSTODIAN_NEXUS_API_BASE", "http://nexus:8800")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Plaintext HTTP as default API base

The default URL http://nexus:8800 uses unencrypted HTTP. Even for an internal service, plaintext HTTP exposes the full request body (which may contain user prompts and LLM responses) to network observers on the path between LiteLLM and the Nexus container.

Consider defaulting to https:// and documenting that HTTP may be used for local/container deployments where TLS is terminated at a higher layer.

Suggested change
api_base = api_base or os.environ.get("QOSTODIAN_NEXUS_API_BASE", "http://nexus:8800")
api_base = api_base or os.environ.get("QOSTODIAN_NEXUS_API_BASE", "https://nexus:8800")

Comment on lines +48 to +63
self,
inputs: GenericGuardrailAPIInputs,
request_data: dict,
input_type: Literal["request", "response"],
logging_obj: Optional["LiteLLMLoggingObj"] = None,
) -> GenericGuardrailAPIInputs:
"""
Apply Qostodian Nexus to the given inputs.

NOTE: This override is intentionally a pass-through. It must be present
directly in this class's __dict__ so that LiteLLM's unified guardrail
routing check (`"apply_guardrail" in type(callback).__dict__` in
litellm/proxy/utils.py) routes calls correctly. Do not remove.
"""
return await super().apply_guardrail(
inputs=inputs,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Pass-through override tightly couples to internal detection logic

The apply_guardrail override is a no-op pass-through that exists solely to ensure the method appears in type(callback).__dict__, satisfying the detection check at litellm/proxy/utils.py:868:

use_unified = "apply_guardrail" in type(callback).__dict__

The comment documents this correctly, but the class now has a hidden dependency on an implementation detail deep in proxy/utils.py. If that detection logic ever changes (e.g. using hasattr or getattr instead), this override becomes dead weight silently, with no compiler error.

Consider converting the detection check to use hasattr() or a registry-based approach to remove this coupling entirely. Alternatively, a class-level marker attribute (e.g. _uses_unified_guardrail = True) would be a more explicit and fragile-proof contract.

@mats852

mats852 commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

Hi @krrish-berri-2, just saw more recent staging branches merged recently. Just wanted to make sure this one was not forgotten 😁 Thanks!

@gitguardian

gitguardian Bot commented Apr 15, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
29203053 Triggered Generic Password e6fb699 .circleci/config.yml View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@veria-ai veria-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

High: Syntax error disables all guardrail enforcement

This PR adds a Qostodian Nexus guardrail integration, secret redaction improvements, cost calculation fixes, and SQL query enhancements. However, a missing closing parenthesis in litellm/types/guardrails.py introduces a SyntaxError that prevents the guardrails type module from loading, which would silently disable every configured guardrail (content filtering, PII detection, prompt injection blocking, etc.) at proxy startup.

ToolPermissionGuardrailConfigModel,
)
from litellm.types.proxy.guardrails.guardrail_hooks.qohash import (
QostodianNexusConfigModel,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

High: Guardrail bypass via import failure

The import of QostodianNexusConfigModel is missing its closing ). This causes a SyntaxError on this module, which is imported by every guardrail hook in the proxy. At startup, all guardrails (PII masking, prompt injection detection, content filtering, etc.) will fail to load. An attacker who knows the proxy is running this version can send requests that bypass all configured guardrails.

Suggested change
QostodianNexusConfigModel,
QostodianNexusConfigModel,
)
from litellm.types.proxy.guardrails.guardrail_hooks.hiddenlayer import (

Comment thread litellm/_logging.py

from litellm.litellm_core_utils.safe_json_dumps import safe_dumps
from litellm.litellm_core_utils.safe_json_loads import safe_json_loads
from litellm.litellm_core_utils.secret_redaction import redact_string

Check notice

Code scanning / CodeQL

Unused import Note

Import of 'redact_string' is not used.

Copilot Autofix

AI 4 months ago

The best fix is to remove the unused import line from litellm/_logging.py and leave behavior unchanged.

  • General approach: delete imports that are not referenced.
  • Specific change: in the import block at the top of litellm/_logging.py, remove:
    • from litellm.litellm_core_utils.secret_redaction import redact_string
  • No additional methods, definitions, or dependency changes are required.
Suggested changeset 1
litellm/_logging.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/_logging.py b/litellm/_logging.py
--- a/litellm/_logging.py
+++ b/litellm/_logging.py
@@ -8,7 +8,6 @@
 
 from litellm.litellm_core_utils.safe_json_dumps import safe_dumps
 from litellm.litellm_core_utils.safe_json_loads import safe_json_loads
-from litellm.litellm_core_utils.secret_redaction import redact_string
 
 set_verbose = False
 
EOF
@@ -8,7 +8,6 @@

from litellm.litellm_core_utils.safe_json_dumps import safe_dumps
from litellm.litellm_core_utils.safe_json_loads import safe_json_loads
from litellm.litellm_core_utils.secret_redaction import redact_string

set_verbose = False

Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Comment on lines +35 to 39
from litellm.types.proxy.guardrails.guardrail_hooks.qohash import (
QostodianNexusConfigModel,
from litellm.types.proxy.guardrails.guardrail_hooks.hiddenlayer import (
HiddenlayerGuardrailConfigModel
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0 SyntaxError — ( was never closed

The opening parenthesis on line 35 is never closed before the next from statement starts on line 37. Python will raise SyntaxError: '(' was never closed when loading the module, breaking every import of litellm.types.guardrails (and therefore the entire proxy).

Confirmed with ast.parse:

SyntaxError: '(' was never closed
  File "litellm/types/guardrails.py", line 35
    from litellm.types.proxy.guardrails.guardrail_hooks.qohash import (

Fix — add the missing ) and reorder the HiddenlayerGuardrailConfigModel import:

Suggested change
from litellm.types.proxy.guardrails.guardrail_hooks.qohash import (
QostodianNexusConfigModel,
from litellm.types.proxy.guardrails.guardrail_hooks.hiddenlayer import (
HiddenlayerGuardrailConfigModel
)
from litellm.types.proxy.guardrails.guardrail_hooks.qohash import (
QostodianNexusConfigModel,
)
from litellm.types.proxy.guardrails.guardrail_hooks.hiddenlayer import (
HiddenlayerGuardrailConfigModel,
)

@Sameerlite
Sameerlite changed the base branch from main to litellm_internal_staging April 16, 2026 13:01
@Sameerlite
Sameerlite temporarily deployed to integration-postgres April 16, 2026 13:04 — with GitHub Actions Inactive
@Sameerlite
Sameerlite temporarily deployed to integration-redis-postgres April 16, 2026 13:04 — with GitHub Actions Inactive
@Sameerlite
Sameerlite temporarily deployed to integration-postgres April 16, 2026 13:04 — with GitHub Actions Inactive
@Sameerlite
Sameerlite temporarily deployed to integration-postgres April 16, 2026 13:04 — with GitHub Actions Inactive
@Sameerlite
Sameerlite temporarily deployed to integration-postgres April 16, 2026 13:04 — with GitHub Actions Inactive
@greptile-apps

greptile-apps Bot commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

Too many files changed for review. (1328 files found, 100 file limit)

@Sameerlite

Copy link
Copy Markdown
Contributor

clean PR: #25856

@Sameerlite Sameerlite closed this Apr 16, 2026
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.

9 participants