From 1a0d7878c68420a9b16b9a0b381d22d428f0aa50 Mon Sep 17 00:00:00 2001 From: srojk34 <286497132+srojk34@users.noreply.github.com> Date: Wed, 1 Jul 2026 22:05:14 +0300 Subject: [PATCH] security(terminal): strip VERTEX_CREDENTIALS_PATH/GOOGLE_APPLICATION_CREDENTIALS from subprocess env MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Vertex AI authenticates via OAuth2 (service-account JSON path / ADC), not PROVIDER_REGISTRY, and VERTEX_CREDENTIALS_PATH is declared with password=False (it's a path, not a bare key) under category="provider" — a category the registry-derived blocklist loop never checks. Both it and GOOGLE_APPLICATION_CREDENTIALS (the ADC fallback the adapter also reads) fell through every existing blocklist source and leaked the on-disk location of a GCP service-account key into every spawned subprocess (terminal, codex/copilot app-server, browser workers) — the same leak class already closed for every other provider's credentials in #53503. --- tests/tools/test_local_env_blocklist.py | 23 +++++++++++++++++++++++ tools/environments/local.py | 4 ++++ 2 files changed, 27 insertions(+) diff --git a/tests/tools/test_local_env_blocklist.py b/tests/tools/test_local_env_blocklist.py index 914fdfa2c..0020022cc 100644 --- a/tests/tools/test_local_env_blocklist.py +++ b/tests/tools/test_local_env_blocklist.py @@ -114,6 +114,29 @@ class TestProviderEnvBlocklist: "AWS_BEARER_TOKEN_BEDROCK leaked into subprocess env (see #32314)" ) + def test_vertex_credentials_path_is_stripped(self): + """The Vertex AI service-account JSON path must not leak into + subprocesses, even though it is filesystem path metadata rather + than a bare API key. + + Regression: ``vertex`` authenticates via OAuth2 (service-account + JSON / ADC), not PROVIDER_REGISTRY, and OPTIONAL_ENV_VARS marks + VERTEX_CREDENTIALS_PATH as ``password=False`` (it's a path, not a + secret string) with ``category="provider"`` — a category the + registry-derived loop above never checks — so it fell through both + blocklist sources. GOOGLE_APPLICATION_CREDENTIALS (the ADC fallback + the adapter also reads) had the same gap. A leaked path discloses + the on-disk location of a GCP service-account key to every spawned + subprocess (terminal, codex/copilot app-server, browser workers). + """ + result_env = _run_with_env(extra_os_env={ + "VERTEX_CREDENTIALS_PATH": "/home/user/.config/gcloud/sa-key.json", + "GOOGLE_APPLICATION_CREDENTIALS": "/home/user/.config/gcloud/adc.json", + }) + + assert "VERTEX_CREDENTIALS_PATH" not in result_env + assert "GOOGLE_APPLICATION_CREDENTIALS" not in result_env + def test_general_aws_credential_chain_is_preserved(self): """The GENERAL AWS credential chain must STILL pass through to subprocesses — this is the no-regression guard for #32314. diff --git a/tools/environments/local.py b/tools/environments/local.py index bccba3888..1b94fbdd0 100644 --- a/tools/environments/local.py +++ b/tools/environments/local.py @@ -155,6 +155,10 @@ def _build_provider_env_blocklist() -> frozenset: "CLAUDE_CODE_OAUTH_TOKEN", "LLM_MODEL", "GOOGLE_API_KEY", + # Path to a GCP service-account JSON, not a bare key, so + # OPTIONAL_ENV_VARS marks it password=False and the loop above skips it. + "VERTEX_CREDENTIALS_PATH", + "GOOGLE_APPLICATION_CREDENTIALS", "DEEPSEEK_API_KEY", "MISTRAL_API_KEY", "GROQ_API_KEY",