Security and reliability fixes for gateway and subprocess
NousResearch/hermes-agent · cluster 33208 · agent
Data as of
Nothing open on GitHub. Fix merged in #54128. Check it covers your case.
The short answer
- Known?
- Yes. 5 related items grouped here, 2 issues already closed.
- Fix event
- A fix was merged to main in PR #54128. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
partially resolved, deciding PR #54128. That is separate from the fix event. - Still open
- Nothing open on GitHub.
This group covers security-focused patches including restricting gateway quick commands to authorized users, reducing shell=True subprocess usage, and a reliability fix replacing blocking sleep with async sleep in MCP auth polling.
Open issues0
Open PRs0
Fixes on record
-
#54128 fix(gateway): gate quick_commands through slash access policy (#44727)
files:
gateway/run.py,tests/gateway/test_slash_access_dispatch.pyShow the diff
-
gateway/run.py@@ -8874,6 +8874,16 @@ async def _do_undo(): if not isinstance(quick_commands, dict): quick_commands = {} if command in quick_commands: + # Quick commands are slash capabilities too — and type:exec + # ones run a shell command in the gateway process. The early + # gate above only fires for registry-known commands, so quick + # commands (never in the registry) would otherwise reach this + # dispatch sink unchecked. Apply the same admin/user policy to + # the raw typed name here so non-admins can't invoke admin-only + # quick commands. (#44727) + _denied = self._check_slash_access(source, command) + if _denied is not None: + return _denied qcmd = quick_commands[command] if qcmd.get("type") == "exec": exec_cmd = qcmd.get("command", "") -
tests/gateway/test_slash_access_dispatch.py@@ -315,6 +315,74 @@ def fake_is_known(name): assert "/myplugin is admin-only here" in result [redacted:email] +async def test_non_admin_denied_for_unlisted_quick_command_exec(): + """A non-admin must not reach the quick_commands exec sink for a command + that isn't in user_allowed_commands. Regression for #44727 — quick + commands are never in the gateway registry, so the early gate skips them; + the sink gate must catch them.""" + runner = _make_runner( + platform_extra={ + "allow_admin_from": ["111"], + "user_allowed_commands": [], + } + ) + runner.config.quick_commands = { + "limits": {"type": "exec", "command": "printf quick-command-bypass-confirmed"} + } + + result = await runner._handle_message( + _make_event("/limits", _make_source(user_id="999")) + ) + + assert result is not None + assert "⛔" in result + assert "/limits is admin-only here" in result + assert "quick-command-bypass-confirmed" not in result + + [redacted:email] +async def test_listed_quick_command_runs_for_non_admin(): + """When the operator lists the quick command in user_allowed_commands, a + non-admin can run it — the gate must allow, not blanket-deny.""" + runner = _make_runner( + platform_extra={ + "allow_admin_from": ["111"], + "user_allowed_commands": ["limits"], + } + ) + runner.config.quick_commands = { + "limits": {"type": "exec", "command": "printf quick-command-allowed"} + } + + result = await runner._handle_message( + _make_event("/limits", _make_source(user_id="999")) + ) + + assert result == "quick-command-allowed" + + [redacted:email] +async def test_admin_runs_quick_command_when_gating_enabled(): + """An admin runs the quick command even under an enabled gate with an + empty user_allowed_commands list.""" + runner = _make_runner( + platform_extra={ + "allow_admin_from": ["111"], + "user_allowed_commands": [], + } + ) + runner.config.quick_commands = { + "limits": {"type": "exec", "command": "printf quick-command-admin"} + } + + result = await runner._handle_message( + _make_event("/limits", _make_source(user_id="111")) + ) + + assert result == "quick-command-admin" + + # --------------------------------------------------------------------------- # Running-agent fast-path gating — admin/user split must hold even when an # agent is already running. The fast-path block in _handle_message dispatches
-
2 PRs closed without merging
From the close comments: merged via another change 2
Closed issues · 2
How this cluster was grouped
-
Link evidence (
partly structural links): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text. - Members outside that structural core may belong to a different underlying problem.
-
Pairwise link density
0.34: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the LabAt a glance
- Subsystem
- agent
- Merged PRs
- #54128
- Closed issues
- 2
- Attempts
- 2 PRs closed without merging
- Fix link checked
- 28 Jun 2026