fix(terminal): skip sudo prompt when local NOPASSWD sudo works

When running on a host with sudoers NOPASSWD configured for the current
user, interactive Hermes sessions were unnecessarily entering the
password prompt path before executing sudo commands. Outside Hermes,
`sudo -n true` exits 0 for that user.

Add `_sudo_nopasswd_works()` that probes `sudo -n true` and, when it
succeeds, lets `_transform_sudo_command()` return the command unchanged
with no stdin password. The probe:

- Is scoped to the `local` terminal backend only, so Docker/SSH/Modal
  and other remote backends do not inherit host sudo state.
- Re-probes every call (no process-lifetime cache) so an expired sudo
  timestamp cannot silently make a later command block waiting for a
  password that Hermes never prompts for.
- Is bypassed entirely when `SUDO_PASSWORD` is configured or a cached
  password already exists, preserving existing explicit-password flows.

Co-authored-by: Junting Wu <juntingpublic@gmail.com>
This commit is contained in:
Mind-Dragon 2026-04-30 20:37:37 -07:00 committed by Teknium
parent ccfe6a47c3
commit ab6c629ccc
2 changed files with 86 additions and 0 deletions

View file

@ -104,6 +104,57 @@ def test_cached_sudo_password_isolated_by_session_key(monkeypatch):
assert terminal_tool._get_cached_sudo_password() == "alpha-pass"
def test_passwordless_sudo_skips_interactive_prompt_and_rewrite(monkeypatch):
monkeypatch.delenv("SUDO_PASSWORD", raising=False)
monkeypatch.delenv("TERMINAL_ENV", raising=False)
monkeypatch.setenv("HERMES_INTERACTIVE", "1")
def _fail_prompt(*_args, **_kwargs):
raise AssertionError(
"interactive sudo prompt should not run when sudo -n already works"
)
monkeypatch.setattr(terminal_tool, "_prompt_for_sudo_password", _fail_prompt)
monkeypatch.setattr(terminal_tool, "_sudo_nopasswd_works", lambda: True, raising=False)
transformed, sudo_stdin = terminal_tool._transform_sudo_command("sudo whoami")
assert transformed == "sudo whoami"
assert sudo_stdin is None
def test_passwordless_sudo_probe_rechecks_local_terminal(monkeypatch):
monkeypatch.delenv("TERMINAL_ENV", raising=False)
calls = []
class Result:
def __init__(self, returncode):
self.returncode = returncode
def fake_run(args, **kwargs):
calls.append((args, kwargs))
return Result(0 if len(calls) == 1 else 1)
monkeypatch.setattr(terminal_tool.subprocess, "run", fake_run)
assert terminal_tool._sudo_nopasswd_works() is True
assert terminal_tool._sudo_nopasswd_works() is False
assert len(calls) == 2
assert calls[0][0] == ["sudo", "-n", "true"]
assert calls[1][0] == ["sudo", "-n", "true"]
def test_passwordless_sudo_probe_is_disabled_for_nonlocal_terminal_env(monkeypatch):
monkeypatch.setenv("TERMINAL_ENV", "docker")
def _fail_run(*_args, **_kwargs):
raise AssertionError("host sudo probe must not run for non-local terminal envs")
monkeypatch.setattr(terminal_tool.subprocess, "run", _fail_run)
assert terminal_tool._sudo_nopasswd_works() is False
def test_validate_workdir_allows_windows_drive_paths():
assert terminal_tool._validate_workdir(r"C:\Users\Alice\project") is None
assert terminal_tool._validate_workdir("C:/Users/Alice/project") is None