feat: remote shell — @authmesh/shell with agent daemon + shell client - #11
Merged
Conversation
…l client New @authmesh/shell package (separate install, separate binaries): - amesh-agent: daemon on target, persistent relay connection, PTY via Bun.spawn() - amesh-shell: client on controller, interactive + single command (-c) mode - ShellCipher: ChaCha20-Poly1305 with incrementing nonces (not random) - Shell handshake: ECDH + identity exchange, no OTC/SAS, device-ID-bound HKDF - Frame protocol: data, resize, exit, ping/pong, command (binary framing) Security foundations (all critical review findings addressed): - permissions.shell field in AllowListDevice (C2 fix — explicit opt-in) - amesh grant --shell / --no-shell command in CLI - deriveShellSessionKey() with device-ID binding (H3 fix) - Agent registration with publicKey on relay (C1 fix — anti-squatting) - Uniform relay responses for shell requests (C3 fix — no enumeration) - Shell rate limiting, heartbeat, agent store with stale cleanup - Root guard: agent refuses root without --allow-root (M1 fix) - Per-controller session limits (M2 fix) - No session resumption (H4 fix) - Idle timeout with configurable duration (H1 fix) Docs + site: - Remote Shell use case page + guide page on landing site - ADR-011: remote shell as separate package with explicit permission - Remote Shell Guide in docs index - navigation.ts updated (auto-propagates to nav, footer, indexes) - Sitemap updated - Shell spec and security review documents Tests: 15 new (ShellCipher: 8, frame protocol: 7) + 3 deriveShellSessionKey tests
H1: Validate selfSig timestamp freshness (60s window) in shell handshake H2: Zero ephemeral private key, shared secret, and temp key after derivation H3: Increment session counter before async handshake (prevent race condition) L3: Zero session key copy after constructing ShellCipher M1: Add payload length checks to parseResize/parseExit M2: Add nonce counter overflow guard (2^64 limit) M6: Shell rate limiter only counts failures, not successful connections Also: fix Dockerfile.relay for new workspace layout, Dockerfile uses bun install
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.
Summary
New
@authmesh/shellpackage — SSH-like remote access using amesh device identity. Separate install, separate binaries (amesh-agent,amesh-shell). All 3 critical + 4 high security review findings addressed in the implementation.New package:
@authmesh/shellamesh-agent start— daemon on target, persistent relay connection, PTY viaBun.spawn({ terminal: }), encrypted I/O, session managementamesh-shell <device>— client on controller, interactive + single command (-c) mode, raw terminal, resize handlingShellCipher— ChaCha20-Poly1305 with incrementing nonces (controller starts 0x00, target starts 0x80), not random noncesamesh-shell-v1salt), no OTC/SAS neededSecurity review findings addressed
permissions.shellfield in AllowListDevice, requiresamesh grant --shellagent_not_foundmessage; rate limited--idle-timeoutderiveShellSessionKey(shared, targetId, controllerId)with shell-specific HKDF--allow-rootModified existing packages
deriveShellSessionKey()in ecdh.ts + 3 new testsDevicePermissionstype,updatePermissions()on AllowListamesh grant <device-id> --shell/--no-shellcommandAgentStore, agent/shell/ping message handlers, shell rate limitingDocs + site
docs/remote-shell-spec.md) + security review (docs/remote-shell-security-review.md)Test plan
bun run build— all packages compile (core, keystore, cli, sdk, relay, shell, landpage)