From 879ae4542104689a3ba94d292a127f7d8c63efe4 Mon Sep 17 00:00:00 2001 From: yuneng-jiang Date: Tue, 9 Dec 2025 13:36:40 -0800 Subject: [PATCH] Change credential encryption to only affect db credentials --- .../proxy/credential_endpoints/endpoints.py | 12 +++++++++--- .../proxy/client/test_credentials.py | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/litellm/proxy/credential_endpoints/endpoints.py b/litellm/proxy/credential_endpoints/endpoints.py index d774c1e765..647abb7364 100644 --- a/litellm/proxy/credential_endpoints/endpoints.py +++ b/litellm/proxy/credential_endpoints/endpoints.py @@ -24,10 +24,16 @@ class CredentialHelperUtils: def encrypt_credential_values(credential: CredentialItem) -> CredentialItem: """Encrypt values in credential.credential_values and add to DB""" encrypted_credential_values = {} - for key, value in credential.credential_values.items(): + for key, value in (credential.credential_values or {}).items(): encrypted_credential_values[key] = encrypt_value_helper(value) - credential.credential_values = encrypted_credential_values - return credential + + # Return a new object to avoid mutating the caller's credential, which + # is kept in memory and should remain unencrypted. + return CredentialItem( + credential_name=credential.credential_name, + credential_values=encrypted_credential_values, + credential_info=credential.credential_info or {}, + ) @router.post( diff --git a/tests/test_litellm/proxy/client/test_credentials.py b/tests/test_litellm/proxy/client/test_credentials.py index 580bbb39dc..72c643467b 100644 --- a/tests/test_litellm/proxy/client/test_credentials.py +++ b/tests/test_litellm/proxy/client/test_credentials.py @@ -13,6 +13,8 @@ import responses from litellm.proxy.client.credentials import CredentialsManagementClient from litellm.proxy.client.exceptions import UnauthorizedError +from litellm.proxy.credential_endpoints.endpoints import CredentialHelperUtils +from litellm.types.utils import CredentialItem @pytest.fixture @@ -263,3 +265,19 @@ def test_get_unauthorized_error(client): with pytest.raises(UnauthorizedError): client.get(credential_name="azure1") + + +def test_encrypt_credential_values_does_not_mutate_original(monkeypatch): + """Ensure encrypt_credential_values returns a new encrypted object""" + monkeypatch.setenv("LITELLM_SALT_KEY", "test-key") + credential = CredentialItem( + credential_name="azure1", + credential_values={"api_key": "sk-123"}, + credential_info={"api_type": "azure"}, + ) + + encrypted = CredentialHelperUtils.encrypt_credential_values(credential) + + assert encrypted.credential_values["api_key"] != "sk-123" + assert credential.credential_values["api_key"] == "sk-123" + assert encrypted.credential_name == credential.credential_name