Skip to content

Verify the run_command timeout against a real sshd running the capture broker #1384

Open

Description

@doublewhy

Problem

#1293 (fix for #1290) makes a timed-out run_command send TERM with ssh2's ClientChannel.signal() and then close the exec channel (stopTimedOutCommand in mcp/aptl-mcp-common/src/ssh-manager.ts). Its tests drive the real executeCommand through a stub connection and an EventEmitter channel, so they show what the client sends, not what a server does with it.

On the Kali path the server is OpenSSH with ForceCommand /usr/local/bin/broker.py (containers/kali-capture/sshd_config:19, dev f7277fd). OpenSSH accepts signal requests only for sessions without a forced command (OpenSSH 7.9 release notes, bz#1424), so there the close is what has to end the session. That the closed channel then ends the broker, that its finally block terminates the inner ssh process group (os.killpg(child.pid, signal.SIGTERM), then SIGKILL after 5 s, containers/kali-capture/broker.py:507-516), and that recorder.finish(close_reason) writes the session's close record (:520-523) is read from the code. No test or recorded run has shown it against a real sshd and broker.

The existing real-server lane, "Restricted SSH transport against built MCP processes" in .github/workflows/checks.yml, runs tests/test_mcp_transport_processes.py and tests/test_mcp_payload_processes.py against a host OpenSSH. It does not use the capture broker or the run_command timeout.

Scope

  • Run the built SSHConnectionManager.executeCommand against a real OpenSSH server whose session runs the capture broker under ForceCommand, with a short timeout and a command that outlives it.
  • Observe the server side after the rejection: the broker process, the inner command's process group, the session registration under the broker's runtime root, and the close record the recorder writes.
  • If the session does not end, fix the cause in the same change (client or broker), not in a follow-up.
  • Keep the test hermetic to one container or a host sshd; it must not need a full lab.

Done when

  • A test marked integration runs a command that outlives a short executeCommand timeout through a real sshd with ForceCommand running broker.py, and asserts that the call rejects with the unchanged timeout error.
  • The same test asserts that, within a bounded time after the rejection, the broker and the inner command's process group have exited and the session's .pid registration is gone.
  • The test asserts the session's close record and its close_reason.
  • A CI lane selects the test, and the PR names the run that passed it.

Related

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions