Skip to content

[security] fix(ohmo): gate gateway-scoped /provider and /model commands#281

Open
glitch-ux wants to merge 1 commit into
HKUDS:mainfrom
glitch-ux:fix/ohmo-gateway-scoped-commands-remote-bypass
Open

[security] fix(ohmo): gate gateway-scoped /provider and /model commands#281
glitch-ux wants to merge 1 commit into
HKUDS:mainfrom
glitch-ux:fix/ohmo-gateway-scoped-commands-remote-bypass

Conversation

@glitch-ux
Copy link
Copy Markdown
Contributor

Summary

Closes #280. Restores the remote_invocable / remote_admin_opt_in gate for the two ohmo gateway-scoped administrative commands (/provider, /model) that were silently bypassing it.

The bug

ohmo/gateway/runtime.py short-circuited /provider and /model through _handle_gateway_scoped_command before the remote-allowed gate at lines 276-298, so neither remote_invocable=False nor the allow_remote_admin_commands + allowed_remote_admin_commands opt-in was consulted for those two commands. Any sender on the channel allowlist could swap the active provider profile or mutate allowed_models over Slack/Telegram/Feishu/Discord/Matrix.

Both commands are registered with remote_invocable=False, remote_admin_opt_in=True at src/openharness/commands/registry.py:2453-2470, matching the pattern recently extended to /commit, /diff, /tasks, /autopilot, /session, /issue, etc.

The fix

ohmo/gateway/runtime.py — move the _handle_gateway_scoped_command call after the existing gate. The gate already supports admin opt-in via GatewayConfig.allow_remote_admin_commands=True and allowed_remote_admin_commands=["provider","model"], so the operator-opted-in flow keeps working unchanged.

Test plan

  • New parametrized test test_runtime_pool_rejects_gateway_scoped_command_without_admin_opt_in covers both /provider codex and /model gpt-5.5 and asserts:
    • handle_gateway_provider_command / handle_gateway_model_command are NOT invoked.
    • The user-visible reply is the standard "only available in the local OpenHarness UI" rejection.
    • gateway.yaml's provider_profile is unchanged.
    • The runtime is not rebuilt (build_calls length stays at 1).
  • Existing positive test test_runtime_pool_provider_command_refresh_uses_gateway_profile updated to set allow_remote_admin_commands=True, allowed_remote_admin_commands=["provider","model"]. It still asserts the runtime rebuild + active-profile swap on success.
  • uv run pytest tests/test_ohmo/test_gateway.py -q72 passed
  • uv run pytest tests/test_ohmo/ -q92 passed
  • uv run ruff check src tests scripts → clean

CHANGELOG intentionally not updated per repo maintainer practice for [security] fix(...) commits.

/provider and /model are registered with remote_invocable=False and
remote_admin_opt_in=True in src/openharness/commands/registry.py, but
OhmoSessionRuntimePool.stream_message intercepted them with
_handle_gateway_scoped_command before the remote-allowed gate ran, so the
contract was silently skipped for both commands.

Move the gateway-scoped intercept after the gating block so the existing
remote_admin_opt_in / allow_remote_admin_commands +
allowed_remote_admin_commands path governs them like every other admin
command. Add a regression test that asserts /provider and /model are
rejected unless the operator has opted in, and update the existing
positive test to set the opt-in so it continues to exercise the success
path.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[security] ohmo gateway /provider and /model bypass remote_invocable + admin allowlist

1 participant