mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-12 08:42:18 +00:00
security(proxy): keep team callback credentials out of the stored request body (#43217)
* security(proxy): keep team callback credentials out of the stored request body Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * ci: allow the security conventional commit type Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: oliver <oliver@berri.ai> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
6f5ad78a1f
commit
703eb4fa68
4 changed files with 34 additions and 3 deletions
|
|
@ -42,7 +42,7 @@ case "$subject" in
|
|||
;;
|
||||
esac
|
||||
|
||||
ALLOWED_TYPES="feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert"
|
||||
ALLOWED_TYPES="feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert|security"
|
||||
# Description must not start with an uppercase letter — kept in sync with the
|
||||
# subjectPattern in .github/workflows/conventional-commits.yml so the local
|
||||
# hook is the strictly tighter of the two gates. (Without this guard, a commit
|
||||
|
|
@ -61,7 +61,7 @@ cat >&2 <<EOF
|
|||
Expected: <type>(<scope>)!: <description>
|
||||
(description must start with a lowercase letter)
|
||||
|
||||
Allowed types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
|
||||
Allowed types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert, security
|
||||
Examples:
|
||||
feat(router): add weighted round-robin strategy
|
||||
fix(bedrock): decouple STS region from aws_region_name
|
||||
|
|
|
|||
1
.github/workflows/conventional-commits.yml
vendored
1
.github/workflows/conventional-commits.yml
vendored
|
|
@ -41,6 +41,7 @@ jobs:
|
|||
ci
|
||||
chore
|
||||
revert
|
||||
security
|
||||
requireScope: false
|
||||
subjectPattern: ^(?![A-Z]).+$
|
||||
subjectPatternError: |
|
||||
|
|
|
|||
|
|
@ -196,6 +196,9 @@ from litellm.types.utils import (
|
|||
SupportedCacheControls,
|
||||
)
|
||||
|
||||
_CALLBACK_CREDENTIAL_KEYS: Final = frozenset(StandardCallbackDynamicParams.__annotations__) | frozenset(
|
||||
{TRUSTED_CALLBACK_VARS_FIELD}
|
||||
)
|
||||
service_logger_obj: Final = ServiceLogging() # used for tracking latency on OTEL
|
||||
# Bounded dedup for stale-alias warnings (FIFO eviction when over cap).
|
||||
_MAX_STALE_ALIAS_WARNING_KEYS: Final = 10_000
|
||||
|
|
@ -1958,7 +1961,9 @@ def refresh_proxy_server_request_body_snapshot(
|
|||
if not isinstance(proxy_server_request, dict):
|
||||
return
|
||||
_body_snapshot_exclude: Final = (
|
||||
frozenset({"secret_fields", "proxy_server_request", "litellm_logging_obj"}) | _TRANSPORT_ONLY_CREDENTIAL_KEYS
|
||||
frozenset({"secret_fields", "proxy_server_request", "litellm_logging_obj"})
|
||||
| _TRANSPORT_ONLY_CREDENTIAL_KEYS
|
||||
| _CALLBACK_CREDENTIAL_KEYS
|
||||
)
|
||||
body: Final = { # mutable-ok: audit JSON serialization requires a dict with shared nested messages
|
||||
k: v for k, v in data.items() if k not in _body_snapshot_exclude
|
||||
|
|
|
|||
|
|
@ -870,6 +870,31 @@ def test_initial_snapshot_refresh_clears_a_previous_guardrail_checkpoint() -> No
|
|||
assert proxy_request == {"body": {"messages": [{"role": "user", "content": "new request"}]}}
|
||||
|
||||
|
||||
def test_body_snapshot_excludes_team_callback_credentials() -> None:
|
||||
from litellm.proxy.litellm_pre_call_utils import refresh_proxy_server_request_body_snapshot
|
||||
from litellm.types.litellm_params import TRUSTED_CALLBACK_VARS_FIELD
|
||||
|
||||
callback_vars: Final = {
|
||||
"langfuse_public_key": "pk-lf-team",
|
||||
"langfuse_secret_key": "sk-lf-team-secret",
|
||||
"langfuse_host": "https://cloud.langfuse.com",
|
||||
}
|
||||
proxy_request: Final = {"body": None}
|
||||
data: Final = {
|
||||
"messages": [{"role": "user", "content": "hi"}],
|
||||
"proxy_server_request": proxy_request,
|
||||
"success_callback": ["langfuse"],
|
||||
**callback_vars,
|
||||
TRUSTED_CALLBACK_VARS_FIELD: callback_vars,
|
||||
}
|
||||
|
||||
refresh_proxy_server_request_body_snapshot(data)
|
||||
|
||||
assert proxy_request == {
|
||||
"body": {"messages": [{"role": "user", "content": "hi"}], "success_callback": ["langfuse"]}
|
||||
}, proxy_request
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("pre_call_ran", [False, True])
|
||||
async def test_post_guardrail_snapshot_preserves_logging_only_masking_in_spend_logs(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue