feat: disable Remote Control - #12
Merged
Merged
Conversation
Remote Control opened a reverse tunnel to a relay operated by a third party and forwarded public-internet traffic into the local server. That server has the terminal, file and approval APIs enabled, because it is only reachable on a loopback bind and the tunnel requires one, so a caller the relay let through could run shell commands, read and write files, and answer the agent's own approval prompts. Three properties made it worth removing rather than documenting: - The tunnel client does no local authorization. It strips the caller's Authorization, Cookie, Host and Origin, then injects the local server token and Host, so the server's bearer, Host and Origin checks pass by construction. The only real check is the relay operator's. - It authenticates with the long-lived Kimi refresh token, not an access token, carried as a WebSocket subprotocol value where proxies and CDNs log it far more readily than an Authorization header, and re-sent on every reconnect. - POST /api/v1/remote-control started it with no terminal interaction and no second confirmation, so anything holding the local server token could put the machine on the public internet. The refusal sits in startRemoteControl, which is the single point every caller reaches: the CLI, the TUI and the server route all start a tunnel through it, so a caller added by a later upstream merge is covered too. Upstream's implementation is kept as startRemoteControlTunnel, unreachable, so upstream's own tunnel tests keep running against it and upstream changes still merge cleanly instead of conflicting with a deleted function. Also removed so the feature is not merely unreachable but absent: the `kimi rc` / `kimi remote` subcommand, the `--rc` / `--remote-control` flag, and the `/rc` slash command. The server route now returns a refusal rather than starting a tunnel. `kimi web` is unaffected. There is deliberately no environment escape hatch. An env variable would re-enable a public tunnel from exactly the contexts where the environment is least trustworthy, which is the same weakness noted for upstream's KIMI_CODE_DANGEROUS_COMMAND_GUARD. Re-enabling is a source change. Verified: every CLI path refuses in the built binary (`rc` and `remote` are unknown commands, `--rc` and `--remote-control` are unknown options), and a live `kimi web` returns the refusal for POST /api/v1/remote-control with the tunnel state still off. The new unit tests were negative-controlled by removing the guard: all three fail without it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
createRemoteControlHome takes the refresh token to plant; calling it with no argument typechecked locally only because vitest does not typecheck, so CI caught it and the suite did not. Planting a valid token also strengthens the tests: the credential the tunnel would use is present on disk and it still refuses. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Upstream 2.0.0 added Remote Control: a reverse tunnel that registers the machine with a relay operated by a third party and forwards public-internet HTTP and WebSocket traffic into the local server. That server has the terminal, file and approval APIs enabled, because it is only reachable on a loopback bind and the tunnel requires one, so a caller the relay lets through can run shell commands, read and write files, and answer the agent's own approval prompts.
Three properties made it worth removing rather than documenting:
Authorization,Cookie,HostandOrigin, then injects the local server token and Host, so the server's bearer, Host and Origin checks pass by construction rather than by decision. The only real check is the relay operator's.Authorizationheader, and re-sent on every reconnect.POST /api/v1/remote-controlstarted it with no terminal interaction and no second confirmation, so anything holding the local server token could put the machine on the public internet.What changed
The refusal sits in
startRemoteControl, which is the single point every caller reaches: the CLI, the TUI and the server route all start a tunnel through it. A caller added by a later upstream merge is therefore covered too.Upstream's implementation is kept as
startRemoteControlTunnel, unreachable. That keeps upstream's own tunnel tests (header blocklist, absolute-URI rejection, reconnect behaviour) running, and lets upstream changes to the tunnel merge cleanly rather than conflicting against a deleted function.Removed so the feature is absent rather than merely unreachable:
kimi rc/kimi remotesubcommand--rc/--remote-controlflag onkimi web/rcand/remote-controlslash commandsstaticEnableErroris now unconditional, so the server route refuses instead of starting a tunnelkimi webis unaffected.No environment escape hatch, deliberately. An env variable would re-enable a public tunnel from exactly the contexts where the environment is least trustworthy, which is the same weakness this fork's audit flagged in upstream's
KIMI_CODE_DANGEROUS_COMMAND_GUARD. Re-enabling is a source change, reviewed as one.Verification
Typecheck, lint and build clean. Test suite is at the same 70 pre-existing kap-server search failures as
main, plus one known parallelism flake (reconcile.test.ts, passes 3/3 in isolation and has no remote-control references).Against the built binary:
Against a live
kimi web, the route that needed no terminal interaction:The new unit tests were negative-controlled by temporarily removing the guard: all three fail without it, and the kap-server test asserts the relay saw no WebSocket connection and no registration at all.
🤖 Generated with Claude Code