diff --git a/cron/lifecycle_guard.py b/cron/lifecycle_guard.py index 6c7a5eaad062..96e64a884309 100644 --- a/cron/lifecycle_guard.py +++ b/cron/lifecycle_guard.py @@ -258,7 +258,10 @@ def _read_referenced_script(path: Path) -> tuple[Optional[str], bool]: flags = os.O_RDONLY | getattr(os, "O_NONBLOCK", 0) try: descriptor = os.open(path, flags) - except OSError: + except (OSError, ValueError): + # Path-like input can contain an embedded NUL after shell tokenization. + # Treat malformed references like unreadable paths instead of crashing + # the terminal tool before the requested command can run. return None, False try: metadata = os.fstat(descriptor) diff --git a/tests/hermes_cli/test_gateway_restart_loop.py b/tests/hermes_cli/test_gateway_restart_loop.py index bd90e9913010..5265a86ec29e 100644 --- a/tests/hermes_cli/test_gateway_restart_loop.py +++ b/tests/hermes_cli/test_gateway_restart_loop.py @@ -579,6 +579,13 @@ def test_clean_prompt_does_not_raise(self): check_gateway_lifecycle("research the gateway architecture", None) check_gateway_lifecycle("check server health and restart watchers", None) + def test_embedded_nul_in_referenced_path_does_not_crash(self): + """Malformed shell input must not crash the terminal guard in os.open.""" + from cron.lifecycle_guard import contains_gateway_lifecycle_command_or_referenced_script + + command = "/bin/bash /tmp/safe\x00broken.sh" + assert not contains_gateway_lifecycle_command_or_referenced_script(command) + def test_script_with_command_raises(self, tmp_path, monkeypatch): from cron.lifecycle_guard import GatewayLifecycleBlocked, check_gateway_lifecycle script = tmp_path / "restart.sh"