From 9e3752df363bb08ee1b8836f4f5cd99531588bd9 Mon Sep 17 00:00:00 2001 From: Nikita <152299288+nikitagorlov54@users.noreply.github.com> Date: Sun, 15 Mar 2026 05:42:06 +0100 Subject: [PATCH 1/2] fix(#1002): expand environment blocklist for terminal isolation Expanded the list of blocked environment variables to include Google, Groq, Mistral, and other major LLM providers. This ensures complete isolation and prevents conflicts with external CLI tools. --- tools/environments/local.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tools/environments/local.py b/tools/environments/local.py index 276ff9aca..75ba53eaf 100644 --- a/tools/environments/local.py +++ b/tools/environments/local.py @@ -56,6 +56,17 @@ def _build_provider_env_blocklist() -> frozenset: "ANTHROPIC_TOKEN", # OAuth token (not in registry as env var) "CLAUDE_CODE_OAUTH_TOKEN", "LLM_MODEL", + # Expanded isolation for other major providers (Issue #1002) + "GOOGLE_API_KEY", # Gemini / Google AI Studio + "DEEPSEEK_API_KEY", # DeepSeek + "MISTRAL_API_KEY", # Mistral AI + "GROQ_API_KEY", # Groq + "TOGETHER_API_KEY", # Together AI + "PERPLEXITY_API_KEY", # Perplexity + "COHERE_API_KEY", # Cohere + "FIREWORKS_API_KEY", # Fireworks AI + "XAI_API_KEY", # xAI (Grok) + "HELICONE_API_KEY", # LLM Observability proxy }) return frozenset(blocked) From 672dc1666f6c90099c18e6a5ef51f74ec5efec85 Mon Sep 17 00:00:00 2001 From: teknium1 Date: Sat, 14 Mar 2026 22:29:35 -0700 Subject: [PATCH 2/2] test: cover extra provider env blocklist vars --- tests/tools/test_local_env_blocklist.py | 34 +++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/tools/test_local_env_blocklist.py b/tests/tools/test_local_env_blocklist.py index 70a8ae5d1..d0a11b510 100644 --- a/tests/tools/test_local_env_blocklist.py +++ b/tests/tools/test_local_env_blocklist.py @@ -91,6 +91,25 @@ class TestProviderEnvBlocklist: for var in registry_vars: assert var not in result_env, f"{var} leaked into subprocess env" + def test_non_registry_provider_vars_are_stripped(self): + """Extra provider vars not in PROVIDER_REGISTRY must also be blocked.""" + extra_provider_vars = { + "GOOGLE_API_KEY": "google-key", + "DEEPSEEK_API_KEY": "deepseek-key", + "MISTRAL_API_KEY": "mistral-key", + "GROQ_API_KEY": "groq-key", + "TOGETHER_API_KEY": "together-key", + "PERPLEXITY_API_KEY": "perplexity-key", + "COHERE_API_KEY": "cohere-key", + "FIREWORKS_API_KEY": "fireworks-key", + "XAI_API_KEY": "xai-key", + "HELICONE_API_KEY": "helicone-key", + } + result_env = _run_with_env(extra_os_env=extra_provider_vars) + + for var in extra_provider_vars: + assert var not in result_env, f"{var} leaked into subprocess env" + def test_safe_vars_are_preserved(self): """Standard env vars (PATH, HOME, USER) must still be passed through.""" result_env = _run_with_env() @@ -171,3 +190,18 @@ class TestBlocklistCoverage: must also be in the blocklist.""" extras = {"ANTHROPIC_TOKEN", "CLAUDE_CODE_OAUTH_TOKEN"} assert extras.issubset(_HERMES_PROVIDER_ENV_BLOCKLIST) + + def test_non_registry_provider_vars_are_in_blocklist(self): + extras = { + "GOOGLE_API_KEY", + "DEEPSEEK_API_KEY", + "MISTRAL_API_KEY", + "GROQ_API_KEY", + "TOGETHER_API_KEY", + "PERPLEXITY_API_KEY", + "COHERE_API_KEY", + "FIREWORKS_API_KEY", + "XAI_API_KEY", + "HELICONE_API_KEY", + } + assert extras.issubset(_HERMES_PROVIDER_ENV_BLOCKLIST)