Skip to content

security(tui-gateway): fail-closed dangerous-command check in shell.exec / command.dispatch (#16560) - #17045

Closed
0xsir0000 wants to merge 1 commit into
NousResearch:mainfrom
0xsir0000:fix/tui-gateway-shell-exec-fail-secure
Closed

security(tui-gateway): fail-closed dangerous-command check in shell.exec / command.dispatch (#16560)#17045
0xsir0000 wants to merge 1 commit into
NousResearch:mainfrom
0xsir0000:fix/tui-gateway-shell-exec-fail-secure

Conversation

@0xsir0000

Copy link
Copy Markdown
Contributor

Summary

Two subprocess.run(..., shell=True) call sites in tui_gateway/server.py accept input that is not gated by the danger-pattern check:

  • shell.exec (JSON-RPC method, cmd from request params) wrapped the detect_dangerous_command import in except ImportError: pass — any caller able to make tools.approval un-importable (deleted, shadowed, broken venv) bypassed the entire safety gate.
  • command.dispatch for quick_commands ran the configured command via shell=True straight from _load_cfg() with no danger check at all.

Fix

Hoist the danger check into _check_dangerous_shell_command(), which treats both pattern matches and import failures as a refusal (returns a JSON-RPC error instead of executing). Both call sites now share the same fail-closed gate, so an environment that breaks the safety module fails loudly instead of silently dropping protection, and quick commands match the same standard as shell.exec.

Test plan

  • test_shell_exec_blocks_dangerous_command — flagged command is refused (existing pattern path).
  • test_shell_exec_fails_closed_when_safety_module_missingImportError no longer falls through to subprocess.run.
  • test_command_dispatch_blocks_dangerous_quick_command — flagged quick_commands entry is refused.
  • test_command_dispatch_exec_nonzero_surfaces_error (existing) still passes — non-flagged quick commands run unchanged.

Fixes #16560

…xec / command.dispatch (NousResearch#16560)

The ``shell.exec`` JSON-RPC handler in ``tui_gateway/server.py`` wrapped the
``detect_dangerous_command`` import in ``except ImportError: pass``, so a
caller able to make ``tools.approval`` un-importable (deleted, shadowed,
broken venv) bypassed the entire safety gate and got a free
``subprocess.run(cmd, shell=True, ...)`` against a JSON-RPC parameter.

The ``command.dispatch`` quick-commands path skipped the safety check
entirely — quick commands ran via ``shell=True`` straight from
``_load_cfg()`` with no normalization or filtering at all.

Hoist the danger check into ``_check_dangerous_shell_command()``, which
treats both pattern matches and import failures as a refusal (returns a
JSON-RPC error instead of executing). Both call sites now share the same
fail-closed gate, so neither one can run shell input that the rest of the
codebase already classifies as dangerous, and an environment that breaks
the safety module fails loudly instead of silently dropping protection.

Three regression tests cover (a) ``shell.exec`` blocking a flagged
command, (b) ``shell.exec`` refusing to run when ``tools.approval`` is
unimportable, and (c) ``command.dispatch`` blocking a flagged
``quick_commands`` entry.

Fixes NousResearch#16560
@0xsir0000

Copy link
Copy Markdown
Contributor Author

Closing as duplicate — I missed @alt-glitch's earlier comment that #15542 and #15881 already cover both fail-closed shell.exec and quick-command hardening. Sorry for the noise.

@0xsir0000 0xsir0000 closed this Apr 28, 2026
@alt-glitch alt-glitch added type/security Security vulnerability or hardening P1 High — major feature broken, no workaround comp/tui Terminal UI (ui-tui/ + tui_gateway/) labels Apr 28, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Likely duplicate of #15542 — same fail-closed fix for ImportError in dangerous-command guard. Also overlaps with #15881 which hardens quick commands. See #16560 for the tracking issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/tui Terminal UI (ui-tui/ + tui_gateway/) P1 High — major feature broken, no workaround type/security Security vulnerability or hardening

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Command injection via shell=True in tui_gateway/server.py

2 participants