From 57343cc281ac22c29d5058dc0985443aedb5220b Mon Sep 17 00:00:00 2001 From: Shalom Jamil Date: Wed, 29 Apr 2026 13:16:25 +0300 Subject: [PATCH] fixes --- .../guardrails/guardrail_hooks/ovalix/ovalix.py | 14 +++++++++----- .../guardrails/guardrail_hooks/test_ovalix.py | 16 ++++++++++++++-- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/litellm/proxy/guardrails/guardrail_hooks/ovalix/ovalix.py b/litellm/proxy/guardrails/guardrail_hooks/ovalix/ovalix.py index d7fa8a286bc..7fc4475ac95 100644 --- a/litellm/proxy/guardrails/guardrail_hooks/ovalix/ovalix.py +++ b/litellm/proxy/guardrails/guardrail_hooks/ovalix/ovalix.py @@ -178,11 +178,15 @@ class OvalixGuardrail(CustomGuardrail): return metadata["user_api_key_user_id"] return "unknown" + def _get_tracker_actor_id(self, data: dict) -> str: + """Opaque actor id for Tracker API payloads (hash of _get_actor; avoids sending PII).""" + return hashlib.sha256(self._get_actor(data).encode()).hexdigest()[:8] + def _get_session_id(self, data: dict) -> str: """Return a unique identifier for the chat/session (actor + date + application_id).""" - actor = hashlib.sha256(self._get_actor(data).encode()).hexdigest()[:8] + actor_hash = self._get_tracker_actor_id(data) today = datetime.datetime.now().strftime("%Y-%m-%d") - return f"{actor}_{today}_{self._application_id}" + return f"{actor_hash}_{today}_{self._application_id}" async def _call_checkpoint( self, @@ -236,7 +240,7 @@ class OvalixGuardrail(CustomGuardrail): if not self._pre_checkpoint_id and not self._post_checkpoint_id: return inputs - actor = self._get_actor(request_data) + tracker_actor_id = self._get_tracker_actor_id(request_data) session_id = self._get_session_id(request_data) texts = inputs.get("texts") or [] if not texts or not isinstance(texts, list): @@ -246,13 +250,13 @@ class OvalixGuardrail(CustomGuardrail): if not self._post_checkpoint_id: return inputs corrected_llm_responses = await self._generate_post_guardrail_llm_texts( - texts, actor, session_id, self._post_checkpoint_id + texts, tracker_actor_id, session_id, self._post_checkpoint_id ) return {**inputs, "texts": corrected_llm_responses} if self._pre_checkpoint_id: post_guardrail_texts = await self._generate_post_guardrail_llm_texts( - texts, actor, session_id, self._pre_checkpoint_id + texts, tracker_actor_id, session_id, self._pre_checkpoint_id ) return {**inputs, "texts": post_guardrail_texts} return inputs diff --git a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_ovalix.py b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_ovalix.py index cc2daedfb7f..4160a835ca4 100644 --- a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_ovalix.py +++ b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_ovalix.py @@ -2,6 +2,7 @@ Unit tests for Ovalix guardrail: config resolution and apply_guardrail behavior with mocked Tracker service responses (allow, anonymize, block). """ + import os from typing import Any, List from unittest.mock import AsyncMock, MagicMock, patch @@ -167,7 +168,7 @@ class TestOvalixGuardrail: result = await guardrail._call_checkpoint( content="hello", checkpoint_id="pre-1", - actor="user@test.com", + actor="a1b2c3d4", session_id="session-1", ) @@ -180,7 +181,7 @@ class TestOvalixGuardrail: body = call_args.kwargs["json"] assert body["application_id"] == "app-1" assert body["checkpoint_id"] == "pre-1" - assert body["actor"] == "user@test.com" + assert body["actor"] == "a1b2c3d4" assert body["session_id"] == "session-1" assert body["data_type"] == "TEXT" assert body["data"] == {"content": "hello"} @@ -579,6 +580,17 @@ class TestOvalixGuardrail: } assert guardrail._get_actor(data) == "primary@test.com" + def test_get_tracker_actor_id_is_hash_not_raw_pii(self, guardrail_with_env): + """Tracker API actor field uses a short hash of _get_actor, not email/user id.""" + guardrail = guardrail_with_env + data = {"metadata": {"user_api_key_user_email": "user@example.com"}} + raw = guardrail._get_actor(data) + hashed = guardrail._get_tracker_actor_id(data) + assert raw == "user@example.com" + assert hashed != raw + assert len(hashed) == 8 + assert all(c in "0123456789abcdef" for c in hashed) + def test_get_session_id_deterministic_and_includes_app_id(self, guardrail_with_env): """Session ID is stable for same actor/day and includes application_id.""" guardrail = guardrail_with_env