All notable changes to bssh will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Internal fork of
russh-sftpascrates/bssh-russh-sftpwith aserde_bytesperformance fix forSSH_FXP_WRITEandSSH_FXP_DATApackets. The upstream serde derive routesVec<u8>throughdeserialize_seq(byte-by-byte), accounting for ~42% of server CPU during 1 GiB SFTP uploads inperfprofiling. Annotating thedatafields with#[serde(with = "serde_bytes")]and implementing wire-compatibleserialize_byteson the SFTPSerializerroutes through the existing bulkdeserialize_byte_buf/try_get_bytespath. Measured impact on a CPU-bound host (Xeon Silver 4214): 1 GiB SFTP upload throughput improves from 74.8 MiB/s to 96.4 MiB/s (+29%), closing the gap to OpenSSHsftp-serverfrom ~26% to ~5%. scp.rootconfiguration field. SCP transfers now honor a chroot setting separate from SFTP. When unset, SCP falls back tosftp.root, so a single top-level chroot setting governs both subsystems unless an admin explicitly wants them split.
- Switched the top-level
russh-sftpdependency from crates.iorussh-sftp = "2.1.1"torussh-sftp = { package = "bssh-russh-sftp", version = "2.1.1", path = "crates/bssh-russh-sftp" }. All existinguse russh_sftp::...imports continue to work unchanged. - Default file-transfer behavior is no longer chrooted to the user's home directory. With
sftp.root/scp.rootunset (the default), absolute client paths are honored verbatim and relative paths resolve from the user's home directory, matching OpenSSHsftp-server/scpdefaults. Deployments that intentionally want chroot-at-home-dir must now setsftp.root: <home dir>(or equivalent) explicitly. (#186)
- bssh-server SCP/SFTP path doubling on absolute client paths (#186).
ScpHandler::resolve_pathandSftpHandler::resolve_path_staticpreviously re-rooted every absolute client path under the user's home directory, soscp local user@host:/home/work/file.binwrote to/home/work/home/work/file.binandbssh upload local /abs/remote.binfailed withNo such file. The resolver now treats absolute client paths verbatim when no chroot is configured and rejects out-of-chroot absolute paths withpermission_deniedwhen one is. Path-traversal and symlink-escape protections continue to apply. - SCP single-file destinations no longer have the source filename appended (#186).
ScpHandler::receive_filenow consultstarget_is_directory(parsed from-d/-r) and the filesystem state of the resolved target.scp local.bin user@host:/tmp/dest.binnow writes to/tmp/dest.bininstead of/tmp/dest.bin/local.bin. Directory destinations (/tmp/dir/, existing directory, or-d/-rflag) keep the previous filename-appending behavior. - Configured
sftp.rootis no longer dead code (#186). The handler-construction sites inSshHandlerpreviously hard-codeduser_info.home_diras the chroot root and ignoredconfig.sftp.rootentirely. Settingsftp.rootin the YAML configuration now actually changes the SFTP chroot. The same plumbing now exists forscp.root. - Chroot bypass via intermediate-directory symlink. The chroot resolver previously checked only lexical containment for paths whose final component did not exist (typical for new-file creates and
mkdir). A symlink inside the chroot pointing to a directory outside the chroot would let a client targetchroot/escape/newfileand haveopen(...)/create_dir(...)follow the symlink, writing outside the chroot. BothScpHandler::resolve_pathandSftpHandler::resolve_path_staticnow canonicalize the closest existing ancestor of the target path and verify it stays inside the canonicalized chroot, blocking the parent-symlink escape. Found during PR #194 review.
2.1.2 - 2026-04-27
- PTY session mouse tracking leak: after a PTY session disconnects (normal exit, Ctrl+C, network drop, or panic), the local terminal no longer prints raw SGR mouse escape sequences when the mouse is moved. All cleanup paths (
TerminalStateGuard::Drop,force_terminal_cleanup, and the panic hook viaTerminalGuard) now emit the full set of mouse-tracking-off sequences (modes 1000, 1002, 1003, 1006, 1015) plus cursor-show and alternate-screen-exit on teardown. (#189, #190) - Panic-hook safety in terminal cleanup:
force_terminal_cleanup()now usestry_lock()instead oflock()so the panic hook path (TerminalGuard::restore_terminal→force_terminal_cleanup) cannot deadlock if the panicking thread already holdsTERMINAL_MUTEX, and a previously poisoned mutex no longer triggers a secondary panic. The lock only serializes concurrent teardown; the underlying stdout writes anddisable_raw_modeare individually safe. (#190)
- Centralized terminal teardown logic:
TerminalGuard::restore_terminal()ininteractive_signal.rsnow delegates toforce_terminal_cleanup()instead of carrying its own incomplete cleanup, closing the gap on the panic-hook path.
- Added unit tests for
force_terminal_cleanup()covering idempotency, poisoned-mutex resilience, and held-mutex resilience (using localMutexinstances rather than the globalTERMINAL_MUTEXto keep the global state undisturbed).
- Trigger the Homebrew formula update workflow only after the official release:
release.ymlnow callsupdate_homebrew_formula.ymlviaworkflow_callfrom thepublish-releasejob (which converts pre-release to official), instead ofworkflow_runfiring on every Release workflow completion (including pre-release builds). - Prevent the release workflow from being triggered twice: removed the
publishedevent type from the trigger list sincepublish-releasealready handles the pre-release → official conversion.workflow_dispatchcontinues to cover manual runs.
2.1.1 - 2026-04-17
- bssh-server panic on client connection:
new_client_with_addrcalledblock_on()inside the tokio async runtime to check the auth rate limiter ban list, causing an immediate "Cannot start a runtime from within a runtime" panic on every incoming connection. Added non-blockingAuthRateLimiter::try_is_banned()usingRwLock::try_read(). (#185) - bssh-server auth rejection after successful verification: All
SshHandlerconstructors created a localSessionInfothat was never registered withSessionManager. After public key or password verification succeeded,authenticate_session()returnedSessionNotFound, rejecting the client. Fixed by deferring session creation to the authentication flow viaSessionManager::create_session(). (#185)
- Improved Launchpad PPA packaging for Rust 2024 edition: updated
debian/rulesvariants, addeddebian/sanitize-vendor.pyfor vendored crate checksum sanitization, fixed hidden path handling - Added
.pycfiles to.gitignore
2.1.0 - 2026-04-14
EnvGuardRAII wrapper (src/test_helpers/env_guard.rs) for safe environment variable handling in tests, with Drop-based restore semantics and soundness contract documentation (#179, #181)- Test Environment-Variable Mutation Pattern section in ARCHITECTURE.md documenting the
EnvGuardsoundness contract and#[serial]usage
- Migrated bssh and the bundled
bssh-russhcrate to the Rust 2024 edition - Applied 2024 edition clippy improvements: collapsed 38 nested
if letstatements into guard-clause form (if let Some(x) = y && condition) acrossbssh-russhclient/server/keys/kex modules - Replaced 177 ad-hoc
unsafe { env::set_var/remove_var }call sites across 17 test-bearing files withEnvGuard::set/EnvGuard::removeplus#[serial]from theserial_testcrate - Removed hand-rolled
ENV_MUTEX/once_cell::sync::Lazy<Mutex<()>>pattern in integration tests in favor of#[serial] - Pinned
bytesdependency to v1.11.1
- Fixed pattern matching for Rust 2024 edition: removed explicit
ref/ref mutbindings inif letpatterns insrc/server/handler.rsandsrc/server/shell.rs
2.0.1 - 2026-04-13
- bssh-keygen now included in Debian package build pipeline for all architectures
- Bumped bssh-russh from 0.60.0 to 0.60.1 with security updates
- Fixed GitHub Actions debian_build.yml distro configuration (questing -> resolute)
- Fixed debian_build.yml matrix validation issue causing workflow failures
- Updated rsa to 0.10.0-rc.17 (fixes RUSTSEC-2023-0071 RSA Marvin Attack)
- Updated RC dependencies to latest versions: elliptic-curve 0.14.0-rc.30, p256/p384/p521 0.14.0-rc.8, ml-kem 0.3.0-rc.2, spki 0.8.0 (stable)
2.0.0 - 2026-04-13
-
bssh-server SSH Server - A lightweight SSH server designed for container environments
- Full SSH, SFTP, and SCP protocol support
- PTY/shell session support with terminal handling
- Password and public key authentication
- YAML-based comprehensive configuration system
- Command execution handler with security controls
-
Audit Logging Infrastructure
- File-based audit exporter (JSON Lines format)
- OpenTelemetry audit exporter for observability platforms
- Logstash audit exporter for ELK stack integration
- Configurable audit event types and logging levels
-
Security Features
- IP-based access control (allow/deny lists)
- Authentication rate limiting (fail2ban-like protection)
- Session management and connection limits
- Path traversal prevention in SFTP handler
-
File Transfer Filtering
- Path-based filter rules for upload/download control
- Pattern-based filtering with glob support
- Configurable filter actions (allow/deny)
-
bssh-keygen Tool
- SSH key pair generation utility
- Support for RSA, Ed25519, and ECDSA key types
- Configurable key sizes and comments
-
Server Configuration
- Per-jump-host SSH private key configuration
- SSH config Host alias reference in jump_host configuration
- SSH keepalive settings in interactive mode
-
Separate Packaging
- bssh and bssh-server now distributed as separate packages
- Independent Debian packages for client and server
- Separate Homebrew formulas for each component
- Documentation: Added comprehensive server configuration manual and manpages
- CI/CD: Updated release workflow for dual-package distribution; Teams release notification added
- Dependencies: Synced bssh-russh fork with upstream
warp-tech/russhv0.60.0, which brings the RustCrypto chain migration — rand 0.9 → 0.10 stable, signature 3.0.0-rc.10, ed25519-dalek 3.0.0-pre.6, elliptic-curve 0.14.0-rc.28, p256/p384/p521 0.14.0-rc.7, ecdsa 0.17.0-rc.16, curve25519-dalek 5.0.0-pre.6, der 0.8, sec1 0.8, pkcs8 0.11.0-rc.11, pkcs5 0.8.0-rc.13, spki 0.8.0-rc.4, ml-kem 0.3.0-rc.1, ssh-key 0.6.18, tokio 1.51.1, socket2 0.6.3, signal-hook 0.4.4, fastrand 2.4.1 - Cluster flag help: Help examples and man pages now correctly show
-C(uppercase) for the cluster flag; running the previous-cexamples failed with clap's "unexpected argument" error
- SSH idle disconnects: Interactive sessions could disconnect inconsistently after idle time — sometimes within minutes, sometimes ~10 minutes
russh::Config::inactivity_timeout(10-minute client-side ceiling) is now explicitly set toNonewhen keepalive is enabled so the keepalive mechanism alone decides peer liveness- TCP-level
SO_KEEPALIVE(viasocket2::TcpKeepalive) is now applied to every SSH socket so the kernel can detect broken paths even when SSH keepalive replies are dropped by middleboxes - The exec-mode code path previously dropped the user-configured
SshConnectionConfigat theConnectionConfigboundary; it now flows throughconnect_direct/connect_via_jump_hosts/ the jump chain, soserver_alive_intervalactually takes effect in non-interactive runs
- bssh-server: Use consistent source package name in Debian
controlfile so dual-package builds resolve correctly - bssh-server: Use type inference for
ioctlto support both glibc and musl builds
- Shared module structure for client/server code reuse
- russh-based SSH server handler implementation
- Modular audit exporter architecture with trait-based design
SshConnectionConfig::to_russh_config()now overridesinactivity_timeoutbased on keepalive state;to_tcp_keepalive()derives a kernel TCP keepalive config from the same settingsClient::connect_with_configrewritten aroundrussh::client::connect_stream, building theTcpStreammanually so SO_KEEPALIVE can be applied before the SSH handshake- Dropped the
ssh_key::rand_core::OsRngworkaround in key-generation sites; now pass&mut rand::rng()(rand 0.10's thread RNG implements the newrand_core 0.10CryptoRngtrait directly)
1.7.0 - 2026-01-09
- SSH Keepalive Support (Issue #122)
--server-alive-intervaloption: Configure keepalive interval in seconds (default: 60, 0 to disable)--server-alive-count-maxoption: Maximum keepalive messages without response before disconnect (default: 3)- Configuration support in config.yaml via
server_alive_intervalandserver_alive_count_maxfields - Helps maintain long-running sessions through firewalls and NATs that drop idle connections
- Full integration with exec, interactive, and file transfer modes
- Documentation: Added GitHub downloads badge to README
- Updated russh from 0.55.0 to 0.56.0
- Updated ratatui from 0.29.0 to 0.30.0
- Updated signal-hook from 0.3.18 to 0.4.1
- Updated whoami from 1.6.1 to 2.0.1
- Updated unicode-width from 0.2.0 to 0.2.2
- Implemented SSH keepalive packet sending at configurable intervals
- Automatic connection termination after max retries without response
- Keepalive settings work with jump host connections
- Adapted to whoami 2.0 API changes (username() now returns Result)
1.6.0 - 2025-12-19
- Jump Host Configuration Support in YAML (Issue #115, PR #120)
- Global defaults level:
defaults.jump_hostfor all clusters - Cluster level:
clusters.<name>.jump_hostfor cluster-specific settings - Node level: Per-node
jump_hostin detailed node configuration - Environment variable expansion supported (
${VAR}or$VARsyntax) - Empty string (
"") explicitly disables jump host inheritance - CLI
-Joption always takes precedence over configuration
- Global defaults level:
- SSH Config ProxyJump Directive (Issue #117, PR #119)
- ProxyJump directive from SSH config now properly applied when
-Joption not specified - Priority order: CLI
-J> config.yaml jump_host > SSH config ProxyJump
- ProxyJump directive from SSH config now properly applied when
- Documentation Improvements
- Added comprehensive jump_host configuration documentation to README.md
- Updated docs/architecture/ssh-jump-hosts.md with detailed architecture
- Updated example-config.yaml with all jump_host configuration patterns
- CI/CD
- Updated GitHub workflows
- Jump Host Authentication (Issue #116, PR #118)
- Properly handle empty SSH agent when authenticating through jump hosts
- Fall back to key-based authentication when agent has no identities
- Config Fallback (PR #120)
- Environment variables now properly expanded in jump_host values via expand_env_vars
- Configuration jump_host properly used in exec and interactive modes
- Added
ConfigResolver::resolve_jump_host()method for centralized jump host resolution - Jump host priority: CLI > Node > Cluster > Global defaults
- Comprehensive test coverage: 424 lines of tests for jump_host configuration
- Integration tests for all priority levels and edge cases
1.5.1 - 2025-12-18
- SSH Disconnect Error Handling (Issue #113, PR #114)
- Handle SshError(Disconnect) during authentication for password fallback
- Fixed handling of SSH disconnect errors during authentication phase
- Enables proper password fallback when SSH connection is disconnected during auth
1.5.0 - 2025-12-18
-
pdsh Compatibility Mode (Issues #100-103, #105, #107, #110)
- Full pdsh-style command line compatibility when invoked as
pdshor with--pdsh-compat -w hostsoption mapped to-H hostsfor target host specification-x hostsoption mapped to--exclude hostsfor host exclusion-f Noption mapped to--parallel Nfor fanout control-l useroption for remote username-t Noption mapped to--connect-timeout Nfor connection timeout-u Noption mapped to--timeout Nfor command timeout-Noption mapped to--no-prefixfor disabling hostname prefix in output-boption mapped to--batchfor single Ctrl+C termination-koption mapped to--fail-fastfor stop on first failure-qquery mode to show target hosts and exit-Soption mapped to--any-failurefor returning largest exit code
- Full pdsh-style command line compatibility when invoked as
-
Hostlist Expressions (Issue #107)
- pdsh-style range expansion:
node[1-5]→ node1, node2, node3, node4, node5 - Zero-padded ranges:
node[01-05]→ node01, node02, node03, node04, node05 - Comma-separated values:
node[1,3,5]→ node1, node3, node5 - Cartesian product:
rack[1-2]-node[1-3]→ 6 hosts - Domain suffix support:
web[1-3].example.com - User and port preservation:
admin@db[01-03]:5432 - File input with
^/path/to/hostfile
- pdsh-style range expansion:
-
In-TUI Log Panel (Issue #106)
- Toggle visibility with
lkey - Color-coded by level: ERROR (red), WARN (yellow), INFO (white), DEBUG (gray)
- Configurable buffer size via
BSSH_TUI_LOG_MAX_ENTRIES(default: 1000, max: 10000) - Panel height adjustable from 3-10 lines with
+/-keys - Scroll with
j/kkeys, toggle timestamps witht
- Toggle visibility with
-
--fail-fast Option (Issue #103)
-k/--fail-fastflag to stop immediately on first failure- Compatible with pdsh
-koption - Cancels pending commands when any node fails
- Can be combined with
--require-all-successfor strict error handling
-
--batch Option (Issue #102)
-b/--batchflag for single Ctrl+C termination- Compatible with pdsh
-boption - Useful for non-interactive scripts and CI/CD pipelines
-
--exclude Option (Issue #100)
--exclude/-xfor host exclusion- Supports wildcards, glob patterns, and hostlist expressions
- Applied after
--filteroption
-
--no-prefix Option (Issue #101)
-N/--no-prefixfor disabling hostname prefix in output- Compatible with pdsh
-Noption - Works with both stream mode and file mode
-
--connect-timeout Option (PR #103)
- Separate connection timeout from command execution timeout
- Default: 30 seconds, minimum: 1 second
- Useful for fast failure detection on unreachable hosts
- CI Workflow Simplification
- Merged multiple jobs into single pipeline for efficiency
-
--timeout 0 Handling (Issue #112)
- Fixed --timeout 0 to correctly treat as unlimited execution time
- Previously the 0 value was being ignored, causing unexpected timeout behavior
- Added explicit CLI test to prevent regression
-
Environment Variable Test Race Conditions
- Added
#[serial]attribute to env var tests to prevent race conditions - Tests now run sequentially when accessing shared environment state
- Added
-
Connect Timeout Propagation
- Fixed connect_timeout not being propagated through all SSH connection paths
-
Architecture Restructure (Issue #109)
- Restructured ARCHITECTURE.md into modular documentation
- Removed residual dates and fixed incomplete sentences
-
pdsh Compatibility Documentation (Issue #110)
- Added comprehensive pdsh migration guide (docs/pdsh-migration.md)
- Added pdsh options reference (docs/pdsh-options.md)
- Added pdsh usage examples (docs/pdsh-examples.md)
- Added installation scripts for pdsh symlink setup
1.4.2 - 2025-12-16
- PTY Session Terminal Handling (PR #90)
- Fixed terminal escape sequence responses displayed on first prompt when starting tmux
- Improved terminal compatibility with multiplexers
- PTY Session Paste (PR #89)
- Fixed paste not working in PTY sessions
- Improved clipboard/paste functionality in interactive terminal sessions
- Dependencies
- Bumped dependencies to latest versions for security and compatibility
1.4.1 - 2025-12-16
- Comprehensive Test Suite (Issue #82, PR #86)
- tests/tui_snapshot_tests.rs: 20 tests for TUI rendering using ratatui's TestBackend
- tests/tui_event_tests.rs: 36 tests for keyboard navigation, scroll behavior, and view transitions
- tests/streaming_integration_tests.rs: 28 tests for NodeStream, MultiNodeStreamManager, and streaming execution
- benches/large_output_benchmark.rs: Performance benchmarks for large output handling
- Total: 84 new tests added
- SSH Agent Password Fallback (Issue #84, PR #85)
- Extended password fallback to handle all SSH agent authentication failures
- Now correctly triggers for: AgentAuthenticationFailed, AgentNoIdentities, AgentConnectionFailed, AgentRequestIdentitiesFailed
- Added
is_auth_error_for_password_fallback()helper function for testability - Added unit tests and integration tests for all error types
- TUI Module Documentation (Issue #81, PR #83)
- Added comprehensive TUI architecture section to ARCHITECTURE.md
- Enhanced README.md with keyboard shortcuts reference table
- Added view modes description table
- Added TUI activation conditions and requirements
- Added missing "1-9: Jump to node N" shortcut in detail view help text
- Added insta 1.34 (snapshot testing)
- Added criterion 0.5 (benchmarking)
- Added mockall 0.12 (mocking for integration tests)
- Refactored test code quality: removed unused functions, replaced panic! with matches! macro
- Added Unicode test cases (Korean, Chinese, Emoji)
- Improved assertion messages for better debugging
1.4.0 - 2025-12-15
- Sudo Password Support (Issue #74, PR #78)
-S/--sudo-passwordflag for automated sudo authentication- Securely prompts for sudo password before command execution
- Automatically detects and responds to sudo password prompts
- Works with both streaming and non-streaming execution modes
BSSH_SUDO_PASSWORDenvironment variable support (with security warnings)- Uses
secrecycrate for secure memory handling - Password cleared from memory immediately after use
- Developer Tooling
- Added githooks for development workflow
- Setup script for githooks configuration
- Password Fallback (PR #80)
- Improved SSH debugging for better compatibility
- Enhanced password authentication fallback logic
- Fixed clippy warnings for useless_vec and same_item_push
1.3.0 - 2025-12-10
- Interactive TUI (Terminal User Interface) (Phase 3 of #68)
- Summary view: All nodes at a glance with progress bars
- Detail view (1-9): Full output from specific node with scrolling
- Split view (s): Monitor 2-4 nodes simultaneously
- Diff view (d): Compare output from two nodes side-by-side
- Auto-scroll (f): Toggle automatic scrolling
- Navigation: Arrow keys, PgUp/PgDn, Home/End
- Help (?): Show keyboard shortcuts
- Press
qto quit
- Multi-node Stream Management (Phase 2 of #68)
- Real-time output modes for multi-node operations
- Stream mode with [node] prefixes for real-time monitoring
- Enhanced streaming infrastructure for real-time updates
- PTY Escape Sequence Filtering (PR #77)
- Filter terminal escape sequence responses in PTY sessions
- Fixed issue with terminal response codes appearing in output
- Implemented ratatui-based TUI rendering
- Added multi-node output aggregation and display
- Performance optimizations for real-time output streaming
1.2.2 - 2025-10-29
- Backend.AI Auto-detection (PR #66)
- Improved host heuristics for Backend.AI environments
- Added localhost and localhost.localdomain detection
- Added IPv4 address validation (127.0.0.1, 192.168.x.x, etc.)
- Enhanced detection for user@host, host:port, FQDN, IPv6 patterns
- Users can now use
bssh localhost "command"naturally in Backend.AI
- Extracted testable
looks_like_host_specification()function - Added
is_ipv4_address()helper with strict validation - Performance optimized with early returns
- 16 comprehensive tests added for host detection logic
1.2.1 - 2025-10-28
- Password Authentication Fallback in Interactive Mode (PR #65)
- Re-implemented password authentication fallback logic for interactive mode
- Fixed issue where password prompt was not appearing after key-based authentication failed
- Ensured proper authentication flow in interactive sessions
- Test Race Condition (commit d2e8ce9)
- Added
#[serial]attribute to tests callingRankDetectorto prevent environment variable race conditions - Tests now run sequentially when accessing shared environment state
- Prevents intermittent test failures due to concurrent environment variable access
- Added
1.2.0 - 2025-10-27
- Exit code behavior changed (Issue #62)
- Old behavior (v1.0-v1.1): Returns 0 only if all nodes succeeded, 1 if any failed
- New behavior (v1.2.0+): Returns main rank's actual exit code (matches MPI standard: mpirun, srun, mpiexec)
- Impact: Users relying on "all nodes must succeed" semantics must add
--require-all-successflag - Benefit: Preserves actual exit codes (139=SIGSEGV, 137=OOM, 124=timeout) for better diagnostics
- MPI users: No changes needed - behavior improved and matches standard tools
- Health checks: Add
--require-all-successflag to preserve old behavior
- Exit Code Strategy (Issue #62)
- Main rank exit code returned by default (matches MPI standard: mpirun, srun, mpiexec)
- Preserves actual exit codes: 139 (SIGSEGV), 137 (OOM), 124 (timeout), etc.
--require-all-successflag for v1.0-v1.1 behavior (returns 0 only if all nodes succeed)--check-all-nodesflag for hybrid mode (main rank code + all-node check)- Automatic main rank detection via
BACKENDAI_CLUSTER_ROLEenvironment variable - Example scripts:
examples/mpi_exit_code.sh,examples/health_check.sh
- Exit code behavior now aligns with HPC and distributed computing best practices
- Enables sophisticated error handling in shell scripts and CI/CD pipelines
1.1.0 - 2025-10-24
- macOS Keychain Integration (Issue #59, PR #61)
- Automatic passphrase storage in macOS Keychain after successful SSH key authentication
- Automatic passphrase retrieval before prompting user
- Secure memory handling with
Zeroizingfor all sensitive data - Integration with SSH config
UseKeychainoption per host - New module
src/ssh/keychain_macos.rswith complete Keychain API wrapper
- ProxyUseFdpass SSH Option (Issue #58, PR #60)
- Added
ProxyUseFdpassSSH configuration option support - Optimizes ProxyCommand usage by passing connected file descriptors back to ssh
- Reduces overhead from lingering processes and extra read/write operations
- Added
- Password Authentication Fallback
- Automatic password retry when publickey authentication fails
- Matches OpenSSH standard behavior for seamless user experience
- Interactive terminal detection with TTY checks
- Works for both exec and interactive modes
- SSH Key File Ownership Validation (PR #61)
- Prevents storing passphrases for SSH keys owned by other users
- Added macOS user ID checks using libc
- World-readable SSH key permission warnings
- User Consent for Password Fallback (PR #61)
- Explicit user consent prompt before attempting password authentication
- 30-second timeout for consent prompt
- Prevents unexpected password prompts that could lead to credential exposure
- Rate Limiting (PR #61)
- 100ms delay before initial connection attempts
- 1 second delay before password fallback
- Prevents brute-force attacks and fail2ban triggers
- Code Quality (PR #61)
- Eliminated 251 lines of code duplication in connection logic
- Created
establish_connection()helper function - Centralized authentication logic in auth module
- 60% reduction in connection.rs complexity
- Cross-Platform Support
- All macOS-specific code properly isolated with
#[cfg(target_os = "macos")] - Conditional imports to prevent unused code warnings on non-macOS platforms
- Stub functions for API consistency across platforms
- All macOS-specific code properly isolated with
- Fixed clippy warnings on non-macOS platforms (unused_mut, unused_imports, dead_code)
- Variable shadowing for macOS-specific code paths
- Conditional imports for platform-specific functions
- Fixed interactive mode missing
use_keychainfield causing authentication failures - Fixed password prompt not appearing when connecting to new servers in interactive mode
- Added
security-framework = "2.12.1"for macOS Keychain API integration - Added
libcfor macOS user ID checks (conditional on macOS)
1.0.0 - 2025-10-24
-
SSH Configuration: Certificate Authentication Options
CertificateFile- Specify SSH certificate files for PKI authentication (maximum 100 certificates)CASignatureAlgorithms- Define CA signature algorithms for certificate validation (maximum 50 algorithms)HostbasedAuthentication- Enable/disable host-based authenticationHostbasedAcceptedAlgorithms- Specify accepted algorithms for host-based authentication (maximum 50 algorithms)
-
SSH Configuration: Advanced Port Forwarding Control
GatewayPorts- Control remote port forwarding access (yes/no/clientspecified)ExitOnForwardFailure- Terminate connection when port forwarding failsPermitRemoteOpen- Specify allowed destinations for remote TCP port forwarding (maximum 1000 entries)
-
SSH Configuration: Command Execution and Automation Options
PermitLocalCommand- Allow execution of local commands after successful SSH connection (yes/no, default: no)LocalCommand- Execute local command after connection with token substitution support (%h, %H, %n, %p, %r, %u, %%)RemoteCommand- Execute command on remote host instead of starting interactive shellKnownHostsCommand- Execute command to obtain host keys dynamically (supports token substitution)ForkAfterAuthentication- Fork SSH process to background after successful authentication (yes/no)SessionType- Specify session type: none (port forwarding only), subsystem (e.g., SFTP), or default (shell)StdinNull- Redirect stdin from /dev/null for background operations and scripting (yes/no)
-
SSH Configuration: Host Key Verification & Security Options
NoHostAuthenticationForLocalhost- Skip host key verification for localhost connections (convenient for local development, default: no)HashKnownHosts- Hash hostnames in known_hosts file to prevent hostname disclosure if compromised (default: no)CheckHostIP- Check host IP address in known_hosts for DNS spoofing detection (deprecated in OpenSSH 8.5+, retained for legacy compatibility)VisualHostKey- Display ASCII art of host key fingerprint for visual verification (default: no)HostKeyAlias- Specify alias for host key lookup in known_hosts (useful for load-balanced services with shared keys)VerifyHostKeyDNS- Verify host keys using DNS SSHFP records (yes/no/ask, default: no)UpdateHostKeys- Accept updated host keys from server automatically (yes/no/ask, default: no)
-
SSH Configuration: Additional Authentication Options
NumberOfPasswordPrompts- Control password authentication retry attempts (valid range: 1-10, default: 3)EnableSSHKeysign- Enable ssh-keysign for host-based authentication (yes/no, default: no)
-
SSH Configuration: Network & Connection Options
BindInterface- Bind SSH connection to specific network interface (alternative to BindAddress for multi-homed hosts)IPQoS- Set IP type-of-service/DSCP values for interactive and bulk traffic (e.g., "lowdelay throughput")RekeyLimit- Control SSH session key renegotiation frequency (format: "data [time]", e.g., "1G 1h")
-
SSH Configuration: X11 Forwarding Options
ForwardX11Timeout- Set timeout for untrusted X11 forwarding connections (time interval, default: 0 = no timeout)ForwardX11Trusted- Enable trusted X11 forwarding with full display access (yes/no, default: no)
-
Security Enhancements
- Path validation to prevent usage of sensitive system files (e.g., /etc/passwd, /etc/shadow)
- Memory exhaustion prevention with entry limits for certificates and forwarding rules
- Algorithm list validation with maximum entry limits
- Deduplication for certificate files and remote forwarding destinations
- Command injection prevention for LocalCommand and KnownHostsCommand
- Token validation to prevent invalid substitution patterns
- Dangerous character detection in command strings (semicolons, backticks, pipes, etc.)
- SSH Config Parser: Refactored into modular structure for better maintainability
- Split oversized parser.rs (1706 lines) into category-based modules (~200-350 lines each)
- Organized option parsing by categories: authentication, security, forwarding, connection, etc.
- Improved code organization and maintainability
- Enhanced SSH configuration merging logic with proper priority handling
- Support for both "Option Value" and "Option=Value" syntax
- Scalar options override in later blocks, vector options accumulate with deduplication
- SSH Configuration Coverage: ~71 options (~69% of OpenSSH's 103 options)
- Basic options + Include + Match directives (structural)
- Certificate authentication and port forwarding (7 options)
- Command execution and automation (7 options)
- Host key verification, authentication, network, and X11 options (15 options)
- Comprehensive test coverage: 278 tests including parser, resolver, integration, and security tests
- Validation: NumberOfPasswordPrompts range checking (1-10), CheckHostIP deprecation warnings
0.9.1 - 2025-10-14
None
- PTY Terminal Modes: Complete implementation of PTY terminal modes for better interactive session support
- Shift Key Input Support: Full Shift key input handling in PTY mode for proper terminal behavior
- Terminal mode implementation for PTY sessions
- Shift key input handling in interactive mode
- Enhanced terminal mode settings for PTY allocation
- Implemented proper terminal flag handling for interactive sessions
- Improved keyboard input processing for special keys
0.9.0 - 2025-10-14
-
Configurable Jump Host Limit: Maximum number of jump hosts can now be configured via environment variable
BSSH_MAX_JUMP_HOSTSenvironment variable for dynamic limit configuration- Default: 10 jump hosts, Absolute maximum: 30 (security cap)
- Invalid/zero values fall back to default with warning logs
- Example:
BSSH_MAX_JUMP_HOSTS=20 bssh -J host1,...,host20 target - Prevents resource exhaustion attacks while allowing flexible configurations
-
Jump Host File Transfer Support: Added complete file transfer operations through SSH jump hosts
upload_file_with_jump_hosts()- Upload single files through jump host chainsdownload_file_with_jump_hosts()- Download single files through jump hostsupload_dir_with_jump_hosts()- Upload directories recursively through jump hostsdownload_dir_with_jump_hosts()- Download directories through jump hosts- All file transfer operations now fully support multi-hop SSH connections
-
Jump Host Interactive Mode Support: Interactive shell sessions now work through jump hosts
- Added
jump_hostsfield toInteractiveCommandstructure - Dynamic timeout calculation based on hop count (30s base + 15s per hop)
- Prevents premature timeouts on multi-hop connections
- Full authentication support (SSH keys, agent, password) for each hop
- Added
-
Parallel Executor Integration: Jump host support across all parallel operations
- Updated
executor.rsto propagate jump_hosts to all node operations - Maintains backward compatibility with
Option<&str>type - All
*_to_node()functions now acceptjump_hostsparameter
- Updated
-
Interactive Mode: Now includes jump host support with automatic timeout adjustment
- Connection timeout scales with hop count for reliability
- Example timeouts: Direct (30s), 1 hop (45s), 2 hops (60s), 3 hops (75s)
-
Test Coverage: Updated all test files to include jump_hosts parameter
tests/interactive_test.rs: Addedjump_hosts: Noneto test casestests/interactive_integration_test.rs: Updated all 9 test instancesexamples/interactive_demo.rs: Updated example with jump_hosts field
-
Dependencies: Updated various dependencies for security patches and stability
- Interactive mode timeout issues when connecting through jump hosts
- File transfer operations not working with jump host chains
- Added
serial_testdependency for thread-safe environment variable testing - Comprehensive test coverage for environment variable functionality (6 new tests)
- Files Modified: 8 files
- Lines Added: +623
- Lines Removed: -26
- Net Change: +597 lines
- Test Results: All 132 tests passing
0.8.0 - 2025-09-12
- Comprehensive SSH port forwarding support
- Local port forwarding (
-L) for tunneling to remote services - Remote port forwarding (
-R) for exposing local services - Dynamic port forwarding (
-D) for SOCKS4/5 proxy functionality
- Local port forwarding (
- Improved error messages with better context and recovery suggestions
- Removed dangerous
unwrap()calls throughout codebase - Enhanced error handling with detailed failure reasons
0.7.0 - 2025-08-30
- SSH jump host infrastructure (
-Joption)- OpenSSH ProxyJump format parsing
- Multiple jump hosts support (comma-separated)
- IPv6 address handling with bracket notation
- Jump host chain management and connection establishment
- Improved Ubuntu PPA support with better packaging
- Fixed deprecated GitHub Actions workflows
0.6.1 - 2025-08-28
- Rebranded from "Backend.AI SSH" to "Broadcast SSH"
- Emphasizes core broadcast/parallel functionality
- Better reflects the tool's primary purpose
0.6.0 - 2025-08-28
- SSH configuration file support (
-Foption)- Auto-loads from
~/.ssh/configby default - Supports 40+ SSH directives
- Wildcard pattern matching and negation
- Environment variable expansion in paths
- Auto-loads from
- PTY allocation for interactive sessions (
-t/-Toptions) - SSH configuration caching for improved performance
- LRU cache with configurable size and TTL
- File modification detection
- 10-100x faster repeated operations
- Enhanced security with improved host key verification
- Performance improvements across core operations
- SSH-compatible command-line interface (drop-in replacement)
0.5.4 - 2025-08-27
- Parallel configuration value handling issues
- Interactive mode authentication alignment with exec mode
0.5.3 - 2025-08-27
- Backend.AI cluster auto-detection now uses cluster SSH key configuration
0.5.2 - 2025-08-27
- Configuration file loading priority issues
- Backend.AI environment variable handling improvements
- Now uses cluster SSH key configuration when available
0.5.1 - 2025-08-25
- Configurable command timeout support
- Set timeout via
--timeoutflag or configuration file - Support for unlimited execution time (
timeout=0) - Default timeout: 300 seconds (5 minutes)
- Set timeout via
0.5.0 - 2025-08-22
- Interactive mode with PTY support
- Single-node mode for focused interaction
- Multiplex mode for parallel command execution
- Node switching commands (
!node1,!node2, etc.) - Broadcast command (
!broadcast <cmd>) - Visual status indicators (● active, ○ inactive)
- Command history with rustyline
- Configurable prompts and settings
- Improved Backend.AI cluster auto-detection
- Enhanced interactive shell capabilities
0.4.0 - 2025-08-22
- Password authentication support (
-Pflag) - SSH key passphrase support with secure prompting
- Modern UI with semantic colors and Unicode symbols
- Debian package distribution (
.deb)
- XDG Base Directory specification compliance
- Improved configuration management
- Enhanced visual feedback and progress indicators
0.3.0 - 2025-08-22
- Native SFTP directory operations
- Recursive file transfer support
- Upload directories with
-rflag - Download entire directory trees
- Glob pattern support for batch operations
- Upload directories with
0.2.0 - 2025-08-21
- Backend.AI multi-node session support
- Automatic cluster detection from environment variables
- Default SSH port 2200 for Backend.AI clusters
- SSH authentication enhancements
- SSH agent authentication with auto-detection
- Host key verification with known_hosts support
- Multiple authentication method fallback
- Environment variable expansion in configuration files
- Connection and command timeout configuration
- SFTP file transfer (upload/download)
- SCP-compatible file copy functionality
- Progress tracking for file operations
- Improved error messages and diagnostics
- Enhanced security with host key verification
0.1.0 - 2025-08-21
- Initial release of bssh
- Parallel SSH command execution across multiple nodes
- Cluster configuration management via YAML files
- Node specification via CLI (
-Hflag) - SSH key-based authentication
- Real-time progress tracking with progress bars
- Per-node output collection and aggregation
- Configurable parallel execution limits
- Connectivity testing (
pingcommand) - Cluster listing (
listcommand)
- Built with Rust for performance and safety
- Async/await pattern for maximum concurrency
- Tokio runtime for efficient I/O operations
- russh library for native SSH implementation
- Cross-platform support (Linux and macOS)