From d62ce07faceafedd4b10d60704db2b9d89d0afff Mon Sep 17 00:00:00 2001 From: rupak Date: Wed, 7 Oct 2026 16:20:38 +0530 Subject: [PATCH] fix(vector-store): stop writing service account private key to DEBUG logs in GoogleMatchingEngine (#7506) Co-authored-by: rupak-eng --- mem0/vector_stores/vertex_ai_vector_search.py | 4 +-- .../test_vertex_ai_vector_search.py | 33 +++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/mem0/vector_stores/vertex_ai_vector_search.py b/mem0/vector_stores/vertex_ai_vector_search.py index 0954bf90c..417e1cc00 100644 --- a/mem0/vector_stores/vertex_ai_vector_search.py +++ b/mem0/vector_stores/vertex_ai_vector_search.py @@ -34,7 +34,7 @@ class OutputData(BaseModel): class GoogleMatchingEngine(VectorStoreBase): def __init__(self, **kwargs): """Initialize Google Matching Engine client.""" - logger.debug("Initializing Google Matching Engine with kwargs: %s", kwargs) + logger.debug("Initializing Google Matching Engine with config keys: %s", sorted(kwargs)) # If collection_name is passed, use it as deployment_index_id if deployment_index_id is not provided if "collection_name" in kwargs and "deployment_index_id" not in kwargs: @@ -46,7 +46,7 @@ class GoogleMatchingEngine(VectorStoreBase): try: config = GoogleMatchingEngineConfig(**kwargs) - logger.debug("Config created: %s", config.model_dump()) + logger.debug("Config created with fields: %s", sorted(config.model_dump())) logger.debug("Config collection_name: %s", getattr(config, "collection_name", None)) except Exception as e: logger.error("Failed to validate config: %s", str(e)) diff --git a/tests/vector_stores/test_vertex_ai_vector_search.py b/tests/vector_stores/test_vertex_ai_vector_search.py index 7ef994332..12dc1e0be 100644 --- a/tests/vector_stores/test_vertex_ai_vector_search.py +++ b/tests/vector_stores/test_vertex_ai_vector_search.py @@ -1,3 +1,4 @@ +import logging from unittest.mock import Mock, patch import pytest @@ -165,3 +166,35 @@ def test_error_handling(vector_store, mock_vertex_ai): assert isinstance(exc_info.value, exceptions.InvalidArgument) assert "Invalid request" in str(exc_info.value) + + +def test_debug_logs_never_carry_service_account_key(caplog): + """Regression for #7503: constructor DEBUG lines must not log the inline credential. + + The constructor emits the whole kwargs dict and the validated config dump at + DEBUG; when ``service_account_json`` is passed inline that writes the PEM + private key to the log sink. Constructor diagnostics should name the fields, + never their values. + """ + private_key = "-----BEGIN PRIVATE KEY-----\nFAKE-KEY-MATERIAL-FOR-TEST\n-----END PRIVATE KEY-----\n" + kwargs = { + "project_id": "test-project", + "project_number": "123456789", + "region": "us-central1", + "endpoint_id": "test-endpoint", + "index_id": "test-index", + "deployment_index_id": "test-deployment", + "service_account_json": {"type": "service_account", "private_key": private_key}, + } + + with caplog.at_level(logging.DEBUG, logger="mem0.vector_stores.vertex_ai_vector_search"): + # Fails later at credential load (no network, no valid key); the two + # DEBUG statements under test run before that. + with pytest.raises(Exception): + GoogleMatchingEngine(**kwargs) + + logged = caplog.text + assert private_key not in logged + assert "FAKE-KEY-MATERIAL-FOR-TEST" not in logged + # The diagnostics must stay useful: field names are still logged. + assert "service_account_json" in logged