Open
Conversation
Replace the TypeScript SSH server (ssh2 + just-bash) with a pure Rust implementation using russh for the SSH protocol and bashkit for the sandboxed bash interpreter. Modules: - ssh.rs: SSH server with exec/shell modes, connection limits, per-IP concurrency tracking, and graceful auth handling - bash.rs: bashkit sandbox setup with execution limits, virtual filesystem, and docs mounting at /supabase/docs - session.rs: interactive shell REPL over SSH channels with line editing, Ctrl+C/D handling, and prompt with cwd tracking - cache.rs: LRU command cache for read-only filesystem results - main.rs: entry point with env-based configuration matching the TypeScript server's environment variables https://claude.ai/code/session_01NFHnNXnCq5kXxuWmRPdmdW
Three tests verifying end-to-end SSH functionality: - TCP banner exchange - Full SSH handshake + exec `echo hello world` via bashkit - Non-zero exit code for failing commands (`false`) https://claude.ai/code/session_01NFHnNXnCq5kXxuWmRPdmdW
- bash.rs: Use bashkit's `realfs` feature with `mount_real_readonly_at` to mount the host docs directory read-only at /supabase/docs instead of an empty in-memory overlay - ssh.rs: Enforce session_timeout_secs via tokio::time::timeout around the shell session, sending a colored timeout message before disconnect - lib.rs: Add library crate so integration tests can access create_bash - tests: Add exec_cat_doc_from_realfs_mount test that writes a real file to a temp dir, mounts it via realfs, and reads it back over SSH https://claude.ai/code/session_01NFHnNXnCq5kXxuWmRPdmdW
Replace the raw byte-by-byte input handler with a proper line editor that processes ANSI escape sequences over SSH channels. Supports: - Arrow keys: left/right cursor movement, up/down history navigation - Home/End keys (and Ctrl+A/Ctrl+E) - Ctrl+U (kill to start), Ctrl+K (kill to end), Ctrl+W (kill word) - Ctrl+C (cancel line), Ctrl+D (EOF or delete char) - Ctrl+L (clear screen) - Backspace and Delete key - Insert in middle of line with proper redraw - Command history (100 entries, dedup) 10 unit tests covering all key interactions. https://claude.ai/code/session_01NFHnNXnCq5kXxuWmRPdmdW
Fixes: - Add SessionLimits (10K total commands, 500 exec calls) and MemoryLimits (10K array entries, 1MB variable storage) to match the defense-in-depth of the TS version - Tighten execution timeout from 30s to 10s (matching TS execTimeout) - Add max_total_loop_iterations (10K) and max_input_bytes (1MB) - Fix auth bypass: all auth methods (none/password/pubkey) now go through the same connection limit check - Fix exec error handling: bashkit ResourceLimit errors now return stderr + exit code 1 to the client instead of dropping the connection Tests ported from attacks.test.ts: - Infinite loops (while true, until false) - Output flooding (bounded to 1MB) - String/memory amplification - Array construction limits - Recursion depth (max_function_depth=50) - Command count exhaustion (1500 commands) - sed loop amplification - Read-only realfs mount (write/mkdir/rm rejected) - In-memory writes sandboxed (can't reach host) - Execution timeout enforcement (<15s) - Concurrent instance fairness https://claude.ai/code/session_01NFHnNXnCq5kXxuWmRPdmdW
Replace the hard cutoff at max_connections with a linear probability ramp matching the TS implementation: - Below soft_limit (80%): always accept - Between soft and hard: linearly increasing drop probability - Above hard_limit (100%): always reject e.g. with max_connections=100: at 80 conns 0% drop, at 90 conns 50% drop, at 100+ conns 100% drop. https://claude.ai/code/session_01NFHnNXnCq5kXxuWmRPdmdW
- Register custom `ssh` builtin via bashkit's Builtin trait that returns a helpful error message matching the TS version's behavior - Add per-connection idle timeout: spawns a watcher task that checks last_activity every 5s and disconnects after idle_timeout_secs (60s default) with a friendly reconnect message - Add graceful shutdown: SIGTERM/SIGINT triggers a select! that stops the server and allows 2s drain for in-flight commands https://claude.ai/code/session_01NFHnNXnCq5kXxuWmRPdmdW
Tests: - 8 cache unit tests (miss, hit, cwd differentiation, stats, LRU eviction, LRU promotion, max output skip, update without eviction) - 4 new security tests (brace expansion bomb, command substitution depth, arithmetic tight loop, awk infinite loop) README documents: - Quick start (keygen, cargo run, ssh connect) - All env vars with defaults - Architecture overview (module layout) - Security model summary - Build and test commands - Docker example Total: 40 tests (18 unit + 4 integration + 18 security) https://claude.ai/code/session_01NFHnNXnCq5kXxuWmRPdmdW
0.1.15 includes 20+ security fixes: regex size limits, memory exhaustion caps, sandbox escape fix, credential leak prevention, header injection mitigation, AWK getline/printf constraints, curl multipart sanitization, path traversal prevention, and recursion depth limits in Python conversions. No API changes — drop-in replacement. Updated test stack size requirement from 8MB to 16MB for recursion depth test. https://claude.ai/code/session_01NFHnNXnCq5kXxuWmRPdmdW
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
russh(SSH protocol) andbashkit(sandboxed bash interpreter), replacing the TypeScriptssh2+just-bashstackrealfsfeature with path traversal protectionWhat's included
Core modules (
crates/supabase-ssh/src/):ssh.rs— SSH server with exec/shell modes, probabilistic soft/hard connection limit ramp, per-IP concurrency, idle timeout, graceful shutdown (SIGTERM/SIGINT)bash.rs— bashkit sandbox setup with execution limits (1000 commands, 1000 loops, 50 recursion depth, 10s timeout, 1MB output), memory limits, session limits,realfsread-only mount, customsshcommand blockersession.rs— Interactive shell REPL over SSH channelsline_editor.rs— Terminal input handling: arrow keys, history (100 entries), Ctrl+A/E/U/K/W/C/D/L, Home/End, Delete, backspace, insert-in-middlecache.rs— LRU command cache (safe because VFS is read-only)Tests (40 total):
attacks.test.ts(infinite loops, output flooding, string amplification, recursion depth, command count, sed/awk loops, brace expansion, read-only FS, timeout enforcement, concurrency)Security parity with TS version:
defenseInDepthis N/A (JS-specific — bashkit has no host runtime to escape into)Test plan
RUST_MIN_STACK=8388608 cargo test— all 40 tests passcargo test --test integration— SSH protocol: banner, exec, exit codes, realfs doc readingcargo test --test security— all 18 attack surface tests passcargo test --lib— cache + line editor unit testsPORT=2222 cargo runthenssh -p 2222 localhost 'cat /supabase/docs/...'https://claude.ai/code/session_01NFHnNXnCq5kXxuWmRPdmdW