mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-24 10:52:21 +00:00
fix(security): quote HERMES_TIMEZONE in remote code execution to prevent shell injection
This commit is contained in:
parent
bef1d3e4ff
commit
84fcbbf6a9
2 changed files with 42 additions and 1 deletions
|
|
@ -174,6 +174,47 @@ class TestExecuteCodeRemoteTempDir(unittest.TestCase):
|
|||
self.assertIn("rm -rf /data/data/com.termux/files/usr/tmp/hermes_exec_", cleanup_cmd)
|
||||
self.assertNotIn("mkdir -p /tmp/hermes_exec_", mkdir_cmd)
|
||||
|
||||
def test_timezone_shell_quoted_in_remote_execution(self):
|
||||
"""HERMES_TIMEZONE must be shell-quoted in remote env_prefix to prevent injection."""
|
||||
class FakeEnv:
|
||||
def __init__(self):
|
||||
self.commands = []
|
||||
|
||||
def get_temp_dir(self):
|
||||
return "/tmp"
|
||||
|
||||
def execute(self, command, cwd=None, timeout=None):
|
||||
self.commands.append((command, cwd, timeout))
|
||||
if "command -v python3" in command:
|
||||
return {"output": "OK\n"}
|
||||
if "python3 script.py" in command:
|
||||
return {"output": "hello\n", "returncode": 0}
|
||||
return {"output": ""}
|
||||
|
||||
env = FakeEnv()
|
||||
fake_thread = MagicMock()
|
||||
|
||||
malicious_tz = "US/Eastern; echo PWNED"
|
||||
|
||||
with patch("tools.code_execution_tool._load_config",
|
||||
return_value={"timeout": 30, "max_tool_calls": 5}), \
|
||||
patch("tools.code_execution_tool._get_or_create_env",
|
||||
return_value=(env, "ssh")), \
|
||||
patch("tools.code_execution_tool._ship_file_to_remote"), \
|
||||
patch("tools.code_execution_tool.threading.Thread",
|
||||
return_value=fake_thread), \
|
||||
patch.dict(os.environ, {"HERMES_TIMEZONE": malicious_tz}):
|
||||
result = json.loads(_execute_remote("print('hello')", "task-1", ["terminal"]))
|
||||
|
||||
self.assertEqual(result["status"], "success")
|
||||
run_cmd = next(cmd for cmd, _, _ in env.commands if "python3 script.py" in cmd)
|
||||
# The TZ value must be shell-quoted — it should NOT contain unescaped semicolons
|
||||
self.assertNotIn("TZ=US/Eastern; echo PWNED", run_cmd,
|
||||
"TZ value with shell metacharacters must not appear unquoted")
|
||||
# shlex.quote wraps values containing special characters in single quotes
|
||||
self.assertIn("TZ='US/Eastern; echo PWNED'", run_cmd,
|
||||
"TZ value must be wrapped in single quotes by shlex.quote()")
|
||||
|
||||
|
||||
@unittest.skipIf(sys.platform == "win32", "UDS not available on Windows")
|
||||
class TestExecuteCode(unittest.TestCase):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue