From d783c312a79a8458116cd777b56664a4ac81f63c Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Wed, 9 Sep 2026 16:58:26 -0700 Subject: [PATCH] fix(plugins): run gh auth token under the noninteractive git env The MCP-catalog noninteractive contract test asserts every subprocess spawned during a git install carries GIT_TERMINAL_PROMPT=0 and a closed stdin; the gh token probe was spawned with the inherited env. Use the same hardened env (plus GH_PROMPT_DISABLED) so gh cannot open a browser/device flow either, and let the contract accept a stdin fed by input= (credential fill writes its request and closes). --- hermes_cli/git_credentials.py | 6 ++++-- tests/hermes_cli/test_noninteractive_git.py | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/hermes_cli/git_credentials.py b/hermes_cli/git_credentials.py index d08a5f0dec..c6ffb5b57b 100644 --- a/hermes_cli/git_credentials.py +++ b/hermes_cli/git_credentials.py @@ -27,7 +27,7 @@ import subprocess import urllib.parse from typing import Mapping, Optional -from hermes_cli._subprocess_compat import windows_hide_flags +from hermes_cli._subprocess_compat import noninteractive_git_env, windows_hide_flags logger = logging.getLogger(__name__) @@ -54,9 +54,11 @@ def _github_token() -> Optional[str]: if not gh: return None try: + env = noninteractive_git_env() + env["GH_PROMPT_DISABLED"] = "1" result = subprocess.run( [gh, "auth", "token"], capture_output=True, text=True, encoding="utf-8", errors="replace", - timeout=10, stdin=subprocess.DEVNULL, creationflags=windows_hide_flags()) + timeout=10, stdin=subprocess.DEVNULL, env=env, creationflags=windows_hide_flags()) except (OSError, subprocess.TimeoutExpired) as exc: logger.debug("gh auth token lookup failed: %s", exc) return None diff --git a/tests/hermes_cli/test_noninteractive_git.py b/tests/hermes_cli/test_noninteractive_git.py index 72f5f4a177..a3e0588965 100644 --- a/tests/hermes_cli/test_noninteractive_git.py +++ b/tests/hermes_cli/test_noninteractive_git.py @@ -202,7 +202,8 @@ def _capture_run(monkeypatch, module, **result_kwargs): def _assert_noninteractive(call: dict): - assert call.get("stdin") is subprocess.DEVNULL, call["argv"] + # A stdin fed by ``input=`` (git credential fill's request) is written and closed, not a terminal. + assert call.get("stdin") is subprocess.DEVNULL or "input" in call, call["argv"] env = call.get("env") assert env is not None and env.get("GIT_TERMINAL_PROMPT") == "0", call["argv"]