diff --git a/agent/redact.py b/agent/redact.py index 421319a38f..ebca1ae75f 100644 --- a/agent/redact.py +++ b/agent/redact.py @@ -436,7 +436,7 @@ def _canonical_url_param_name(name: str) -> str: if next_value == decoded: break decoded = next_value - return decoded.casefold() + return decoded.casefold().replace("-", "_") def _redact_strict_url_credentials(text: str) -> str: diff --git a/tests/agent/test_pre_compress_memory_context.py b/tests/agent/test_pre_compress_memory_context.py index 98daee9ee3..14f8addb42 100644 --- a/tests/agent/test_pre_compress_memory_context.py +++ b/tests/agent/test_pre_compress_memory_context.py @@ -96,6 +96,10 @@ def test_memory_context_is_strictly_redacted_before_summary_llm(monkeypatch): prefix_secret = "sk-" + "b" * 30 query_secret = "opaque-query-secret" userinfo_value = "opaque-userinfo-value" + hyphen_client_secret = "HYPHEN_CLIENT_SECRET" + hyphen_access_secret = "HYPHEN_ACCESS_SECRET" + hyphen_api_secret = "HYPHEN_API_SECRET" + encoded_hyphen_secret = "ENCODED_HYPHEN_SECRET" prompts = [] def mock_call_llm(**kwargs): @@ -109,7 +113,11 @@ def test_memory_context_is_strictly_redacted_before_summary_llm(monkeypatch): memory_context=( f"api key: {prefix_secret}\n" f"callback: https://example.test/cb?token={query_secret}\n" - f"endpoint: https://user:{userinfo_value}@example.test/private" + f"endpoint: https://user:{userinfo_value}@example.test/private\n" + f"hyphen-client: /resume?client-secret={hyphen_client_secret}\n" + f"hyphen-access: /resume?Access-Token={hyphen_access_secret}\n" + f"hyphen-api: /resume?api-key={hyphen_api_secret}\n" + f"encoded-hyphen: /resume?client%2Dsecret={encoded_hyphen_secret}" ), ) @@ -118,8 +126,16 @@ def test_memory_context_is_strictly_redacted_before_summary_llm(monkeypatch): assert prefix_secret not in prompt assert query_secret not in prompt assert userinfo_value not in prompt + assert hyphen_client_secret not in prompt + assert hyphen_access_secret not in prompt + assert hyphen_api_secret not in prompt + assert encoded_hyphen_secret not in prompt assert "token=***" in prompt assert "https://user:***@example.test/private" in prompt + assert "client-secret=***" in prompt + assert "Access-Token=***" in prompt + assert "api-key=***" in prompt + assert "client%2Dsecret=***" in prompt def test_memory_context_reserved_markers_cannot_escape_data_frame(): diff --git a/tests/run_agent/test_pre_compress_memory_context.py b/tests/run_agent/test_pre_compress_memory_context.py index 6704807e86..b5a33fa8c2 100644 --- a/tests/run_agent/test_pre_compress_memory_context.py +++ b/tests/run_agent/test_pre_compress_memory_context.py @@ -119,6 +119,10 @@ def test_provider_context_is_strictly_sanitized_before_plugin_engine(monkeypatch fragment_secret = "FRAG_SECRET" relative_secret = "REL_SECRET" encoded_key_secret = "ENC_SECRET" + hyphen_client_secret = "HYPHEN_CLIENT_SECRET" + hyphen_access_secret = "HYPHEN_ACCESS_SECRET" + hyphen_api_secret = "HYPHEN_API_SECRET" + encoded_hyphen_secret = "ENCODED_HYPHEN_SECRET" network_userinfo_secret = "NET_SECRET" manager = MagicMock() manager.on_pre_compress.return_value = ( @@ -128,6 +132,10 @@ def test_provider_context_is_strictly_sanitized_before_plugin_engine(monkeypatch f"fragment: https://x.test/#access_token={fragment_secret}&view=public\n" f"relative: /resume?token={relative_secret}&view=public\n" f"encoded: https://x.test/cb?client%5Fsecret={encoded_key_secret}&view=public\n" + f"hyphen-client: /resume?client-secret={hyphen_client_secret}&view=public\n" + f"hyphen-access: /resume?Access-Token={hyphen_access_secret}&view=public\n" + f"hyphen-api: /resume?api-key={hyphen_api_secret}&view=public\n" + f"encoded-hyphen: /resume?client%2Dsecret={encoded_hyphen_secret}&view=public\n" f"network: //user:{network_userinfo_secret}@x.test/path" ) received = [] @@ -154,12 +162,20 @@ def test_provider_context_is_strictly_sanitized_before_plugin_engine(monkeypatch assert fragment_secret not in context assert relative_secret not in context assert encoded_key_secret not in context + assert hyphen_client_secret not in context + assert hyphen_access_secret not in context + assert hyphen_api_secret not in context + assert encoded_hyphen_secret not in context assert network_userinfo_secret not in context assert "access_token=***" in context assert "https://user:***@example.test/private" in context assert "https://x.test/#access_token=***&view=public" in context assert "/resume?token=***&view=public" in context assert "client%5Fsecret=***&view=public" in context + assert "client-secret=***&view=public" in context + assert "Access-Token=***&view=public" in context + assert "api-key=***&view=public" in context + assert "client%2Dsecret=***&view=public" in context assert "//user:***@x.test/path" in context