mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-09 22:31:41 +00:00
fix(datadog): read team callback dd_* params from kwargs instead of blocked dynamic params (#35115)
Some checks failed
Unit Tests: Security / security (push) Has been cancelled
Unit Tests: Proxy DB Operations / assert-shard-coverage (push) Has been cancelled
Unit Tests: Proxy DB Operations / auth-checks (push) Has been cancelled
Unit Tests: Proxy DB Operations / key-generation (push) Has been cancelled
Unit Tests: Proxy DB Operations / logging-misc (push) Has been cancelled
Unit Tests: Proxy DB Operations / budgets (push) Has been cancelled
Unit Tests: Proxy DB Operations / custom-logging (push) Has been cancelled
Unit Tests: Proxy DB Operations / db-and-spend (push) Has been cancelled
Unit Tests: Proxy DB Operations / endpoints-and-responses (push) Has been cancelled
Unit Tests: Proxy DB Operations / guardrails-hooks (push) Has been cancelled
Unit Tests: Proxy DB Operations / jwt-and-keys (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-runtime (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-server-core (push) Has been cancelled
Unit Tests: Proxy DB Operations / schema-migration (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-utils (push) Has been cancelled
Some checks failed
Unit Tests: Security / security (push) Has been cancelled
Unit Tests: Proxy DB Operations / assert-shard-coverage (push) Has been cancelled
Unit Tests: Proxy DB Operations / auth-checks (push) Has been cancelled
Unit Tests: Proxy DB Operations / key-generation (push) Has been cancelled
Unit Tests: Proxy DB Operations / logging-misc (push) Has been cancelled
Unit Tests: Proxy DB Operations / budgets (push) Has been cancelled
Unit Tests: Proxy DB Operations / custom-logging (push) Has been cancelled
Unit Tests: Proxy DB Operations / db-and-spend (push) Has been cancelled
Unit Tests: Proxy DB Operations / endpoints-and-responses (push) Has been cancelled
Unit Tests: Proxy DB Operations / guardrails-hooks (push) Has been cancelled
Unit Tests: Proxy DB Operations / jwt-and-keys (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-runtime (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-server-core (push) Has been cancelled
Unit Tests: Proxy DB Operations / schema-migration (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-utils (push) Has been cancelled
Team-scoped DD credentials (dd_api_key, dd_site) set via POST /team/{id}/callback were silently dropped because _request_blocked_callback_params blocks them from standard_callback_dynamic_params. The security block is correct for request-level injection, but team callback_vars are admin-configured and trusted.
Store the raw init kwargs on the Logging instance and read dd_* params from there in _process_dynamic_callback_list instead of from standard_callback_dynamic_params.
Adds an integration test that exercises the full Logging.__init__ flow with team callback_vars to prevent regression.
This commit is contained in:
parent
ac7c2dc0d7
commit
a5164fe210
3 changed files with 70 additions and 3 deletions
|
|
@ -380,6 +380,7 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
self.standard_callback_dynamic_params: StandardCallbackDynamicParams = (
|
||||
self.initialize_standard_callback_dynamic_params(kwargs)
|
||||
)
|
||||
self._init_kwargs = kwargs
|
||||
|
||||
# Process dynamic callbacks (after standard_callback_dynamic_params is initialized,
|
||||
# so team-scoped credentials are available for callback initialization)
|
||||
|
|
@ -482,10 +483,12 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
# pass only the relevant dynamic params as custom_logger_init_args.
|
||||
_custom_logger_init_args: Optional[dict] = None
|
||||
if callback == "datadog":
|
||||
# dd_* params are blocked from standard_callback_dynamic_params
|
||||
# (request-level security), but team callback_vars in kwargs
|
||||
# are admin-configured and trusted.
|
||||
_source = self._init_kwargs or {}
|
||||
_custom_logger_init_args = {
|
||||
k: v
|
||||
for k, v in self.standard_callback_dynamic_params.items()
|
||||
if k.startswith("dd_")
|
||||
k: v for k, v in _source.items() if k.startswith("dd_")
|
||||
}
|
||||
|
||||
callback_class = _init_custom_logger_compatible_class(
|
||||
|
|
|
|||
|
|
@ -504,10 +504,22 @@ def _get_dynamic_logging_metadata(
|
|||
# Key-based callbacks
|
||||
#########################################################################################
|
||||
if key_dynamic_logging_settings is not None:
|
||||
from litellm.litellm_core_utils.initialize_dynamic_callback_params import (
|
||||
_request_blocked_callback_params,
|
||||
)
|
||||
|
||||
for item in key_dynamic_logging_settings:
|
||||
callback = _get_validated_callback_metadata(item=item, source="key-level")
|
||||
if callback is None:
|
||||
continue
|
||||
# Strip params that could redirect traffic to attacker-controlled
|
||||
# destinations (e.g. dd_site, dd_agent_host). Key metadata is
|
||||
# user-configurable; only team-level callbacks are admin-trusted.
|
||||
callback.callback_vars = {
|
||||
k: v
|
||||
for k, v in callback.callback_vars.items()
|
||||
if k not in _request_blocked_callback_params
|
||||
}
|
||||
callback_settings_obj = convert_key_logging_metadata_to_callback(
|
||||
data=callback,
|
||||
team_callback_settings_obj=callback_settings_obj,
|
||||
|
|
|
|||
|
|
@ -192,3 +192,55 @@ class TestStandardCallbackDynamicParamsIncludesDatadog:
|
|||
assert "dd_site" in annotations
|
||||
assert "dd_agent_host" in annotations
|
||||
assert "dd_agent_port" in annotations
|
||||
|
||||
|
||||
class TestTeamCallbackFlowPassesDDCredentials:
|
||||
"""
|
||||
Integration test for the full team callback flow.
|
||||
|
||||
Verifies that DD credentials configured via team callback_vars
|
||||
actually reach DataDogHandler when a request is processed.
|
||||
The dd_* params are in _request_blocked_callback_params (to prevent
|
||||
request-level injection), but team callback_vars are admin-configured
|
||||
and must pass through.
|
||||
"""
|
||||
|
||||
def test_process_dynamic_callbacks_passes_dd_params_from_kwargs(self):
|
||||
"""
|
||||
Simulates the Logging.__init__ flow where team callback_vars
|
||||
(dd_api_key, dd_site) are unpacked into kwargs. Verifies that
|
||||
_process_dynamic_callback_list picks them up and passes them
|
||||
to DataDogHandler despite _request_blocked_callback_params.
|
||||
"""
|
||||
from litellm.litellm_core_utils.litellm_logging import Logging
|
||||
|
||||
kwargs = {
|
||||
"dd_api_key": "team-dd-key-123",
|
||||
"dd_site": "us5.datadoghq.com",
|
||||
"model": "gpt-4",
|
||||
"litellm_params": {"metadata": {}},
|
||||
}
|
||||
|
||||
with patch("asyncio.create_task"):
|
||||
logging_obj = Logging(
|
||||
model="gpt-4",
|
||||
messages=[{"role": "user", "content": "hi"}],
|
||||
stream=False,
|
||||
call_type="completion",
|
||||
start_time="2026-01-01",
|
||||
litellm_call_id="test-call-id",
|
||||
function_id="test-func",
|
||||
dynamic_success_callbacks=["datadog"],
|
||||
kwargs=kwargs,
|
||||
)
|
||||
|
||||
dd_loggers = [
|
||||
cb
|
||||
for cb in (logging_obj.dynamic_success_callbacks or [])
|
||||
if isinstance(cb, DataDogLogger)
|
||||
]
|
||||
assert (
|
||||
len(dd_loggers) == 1
|
||||
), "DataDogLogger should be initialized from team callback_vars"
|
||||
assert dd_loggers[0].DD_API_KEY == "team-dd-key-123"
|
||||
assert "us5.datadoghq.com" in dd_loggers[0].intake_url
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue