Repository navigation
Verify the run_command timeout against a real sshd running the capture broker #1384
Description
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.executeCommandagainst a real OpenSSH server whose session runs the capture broker underForceCommand, 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
integrationruns a command that outlives a shortexecuteCommandtimeout through a real sshd withForceCommandrunning 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
.pidregistration 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
- run_command leaves the remote command running and buffering after its timeout #1290 (the
run_commandtimeout) and its fix fix(mcp): stop the remote command and close its channel when run_command times out #1293 (Scope section). - Harvest Kali captures for a run_command that timed out #1319 (harvest after a timeout), which needs the broker's final records this test observes.
Activity