Skip to content

fix(remote-debug): gate registration messages on completed handshake - #800

Open
SashaMIT wants to merge 1 commit into
langgenius:mainfrom
SashaMIT:fix/remote-debug-handshake-gate
Open

fix(remote-debug): gate registration messages on completed handshake#800
SashaMIT wants to merge 1 commit into
langgenius:mainfrom
SashaMIT:fix/remote-debug-handshake-gate

Conversation

@SashaMIT

@SashaMIT SashaMIT commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

The remote-debugging TCP server no longer processes plugin registration messages before the handshake completes.

What

The debugging server authenticates clients with a handshake message carrying a per-tenant key (122-bit UUID, 2h TTL), but onMessage never enforced it: ASSET_CHUNK, the declaration messages, and END were all processed while runtime.handshake was still false. The only enforcement was a 10-second timer in OnOpen that closes connections which never handshake, and a full registration completes well inside that window.

Why

An unauthenticated client with network reachability to the remote-installing port could, per connection: write up to 50MB of attacker-chosen asset data into media storage (repeatable across connections, a storage-exhaustion vector), occupy a connection slot against maxConn (default 256, locking out legitimate developers), and register arbitrary attacker-chosen plugin identities in the node's runtime registry for the life of the connection.

Honest scope limits, verified while testing: invocation hijack or shadowing an installed plugin is not possible through this path, because runtime identity includes a checksum over the declaration plus tenant id, and a handshake-less connection has no tenant id to collide with. The handshake key itself is not guessable. Port exposure is deployment-dependent; the feature is on by default.

How

One gate in onMessage before the registration switch: any registration message other than HAND_SHAKE arriving before runtime.handshake is true is rejected, the connection is closed with a handshake failed error (consistent with the existing invalid-handshake path), and the runtime is latched handshakeFailed so later messages are ignored. The 10-second timer stays as-is.

How verified

  • New internal/core/debugging_runtime/hooks_test.go: TestRegistrationRejectedBeforeHandshake connects over TCP and sends a manifest declaration, an endpoint declaration, an asset chunk, and END with no handshake. Each is rejected with a handshake failed reply and a closed connection, and no runtime is ever registered.
  • The post-handshake registration flow remains covered by the existing TestAcceptConnection (requires Redis and Postgres, runs in CI).
  • go build passes for the touched package, and all internal/core/debugging_runtime tests that do not require a local Postgres/Redis pass, including the new one.

Same disclosure class as our merged #796: a missing check visible in the public source, fixed directly via public PR.

Made with Cursor

The remote-debugging TCP server authenticates clients with a handshake
message carrying a per-tenant key, but onMessage never enforced it:
ASSET_CHUNK, the declaration messages and END were all processed while
runtime.handshake was still false. The only enforcement was a 10 second
timer closing connections that never handshake, and a full registration
completes well inside that window, so an unauthenticated client could
write assets to media storage, consume connection slots and register
arbitrary plugin identities in the node registry.

Reject every registration message other than HAND_SHAKE until the
handshake completes, close the connection with a handshake failure and
latch handshakeFailed so later messages are ignored. The 10 second
timer stays as-is.
@dosubot dosubot Bot added size:XS This PR changes 0-9 lines, ignoring generated files. bug Something isn't working go Pull requests that update go code labels Aug 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working go Pull requests that update go code size:XS This PR changes 0-9 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant