diff --git a/cli.py b/cli.py index 35ccd9a59..2b761166a 100644 --- a/cli.py +++ b/cli.py @@ -8600,12 +8600,19 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin): try: # shell=True is intentional: quick_commands are user-defined # shell snippets from config.yaml — not agent/LLM controlled. + # Sanitize env to prevent credential leakage — + # quick commands run in the CLI process which + # has all API keys in os.environ. + from tools.environments.local import _sanitize_subprocess_env + sanitized_env = _sanitize_subprocess_env(os.environ.copy()) result = subprocess.run( exec_cmd, shell=True, capture_output=True, - text=True, timeout=30 + text=True, timeout=30, env=sanitized_env ) output = result.stdout.strip() or result.stderr.strip() if output: + from agent.redact import redact_sensitive_text + output = redact_sensitive_text(output) self._console_print(_rich_text_from_ansi(output)) else: self._console_print("[dim]Command returned no output[/]") diff --git a/tui_gateway/server.py b/tui_gateway/server.py index 2c057155b..6c39b3a66 100644 --- a/tui_gateway/server.py +++ b/tui_gateway/server.py @@ -11310,6 +11310,11 @@ def _(rid, params: dict) -> dict: if name in qcmds: qc = qcmds[name] if qc.get("type") == "exec": + # Sanitize env to prevent credential leakage — + # quick commands run in the TUI server process which + # has all API keys in os.environ. + from tools.environments.local import _sanitize_subprocess_env + sanitized_env = _sanitize_subprocess_env(os.environ.copy()) r = subprocess.run( qc.get("command", ""), shell=True, @@ -11317,12 +11322,16 @@ def _(rid, params: dict) -> dict: text=True, timeout=30, stdin=subprocess.DEVNULL, + env=sanitized_env, ) output = ( (r.stdout or "") + ("\n" if r.stdout and r.stderr else "") + (r.stderr or "") ).strip()[:4000] + if output: + from agent.redact import redact_sensitive_text + output = redact_sensitive_text(output) if r.returncode != 0: return _err( rid,