v1.5.2
Added
- Windows installer (
installer/NeoSSHWinManager.iss, built with Inno Setup 6): a properSetup.exealongside the existing standalone executables, with a setup wizard offering desktop shortcut and "start with Windows" tasks, an optional CLI component (NeoSSHWinManager-cli.execan be excluded via a Compact install), and an app-preferences page to pre-select the application's language and dark/light theme before first launch. The installer's own UI is available in English, German, Spanish, Russian and Dutch. Preferences chosen in the wizard are written toinstall_prefs.jsonand applied byAuthManager.register()when the first local user account is created, instead of the hardcodeden/darkdefaults. - CLI companion executable restored:
NeoSSHWinManager-cli.exe(console subsystem,cli_main.py) is back in the build (NeoSSHWinManager-cli.spec,build_dual.ps1) after being dropped from distribution in 1.5.1. Lets a saved connection with CLI access enabled be reached non-interactively viaNeoSSHWinManager-cli.exe --connect-cli <access_key> [--exec "command"]while the main GUI is running and logged in. The GUI's own build stays a standalone onefile executable, unaffected. - FTP and FTPS support: Connections now carry a protocol (SFTP / FTPS / FTP). The file browser speaks all three — the new
src/ftp_client.pyimplements FTP overftplibwith explicit TLS (AUTH TLS, port 21), implicit TLS (port 990) and plain unencrypted FTP, MLSD listings with a LIST fallback for older servers, passive/active mode, progress-reporting up- and downloads and automatic re-login after an idle timeout. - Add/Edit form gained a protocol selector plus FTP options (implicit TLS, passive mode, certificate verification); the port follows the protocol default (22 / 21 / 990) unless a custom port was entered, and SSH-only fields (key file, drive letter, CLI access, PuTTY key) are hidden for FTP connections.
- Plain-FTP connections can be handed to the on-board Windows Explorer FTP client from the card context menu (the password stays out of the URL — Explorer asks for it).
Changed
- FTP/FTPS connections cannot be mounted as a drive and have no SSH terminal: their card shows a protocol badge and opens the file browser, and mount/terminal/system-info actions report that they are unavailable instead of failing later.
- Database migrations now run each
ALTER TABLEindependently, so one column that SQLite refuses (e.g. adding aUNIQUEcolumn to an old table) no longer silently skips every migration after it.
Fixed
- SSHFS write corruption: Files could end up as pure NUL bytes after writing/overwriting through a mounted drive. Caused by
FileInfoTimeout=-1, which turns on WinFsp's write-back file data caching; a hard-killedsshfs.exe(e.g. on unmount) could drop not-yet-flushed pages and leave the server-side zero-fill in place. Mounts now use a finiteFileInfoTimeout, synchronous SFTP writes (sshfs_sync) and disabled read-ahead (no_readahead) instead. - New folders/files invisible until refresh:
sshfs.execarries its own directory-entry cache (dir_cache/dcache_dir_timeout, default 20s) entirely separate from — and underneath — the WinFsp-side cache timeouts this app already sets, so the existing "disable directory cache" setting never fully applied. Mounts now also tune the sshfs-side cache (fully disabled when that setting is on, tightened to match otherwise). - "New Folder"/new file silently duplicated 4x in Explorer: on a mounted drive, creating an item in Windows Explorer could appear to fail (no rename prompt) and then show up to 4 times after a manual refresh. Root cause is an upstream WinFsp/Windows security-token mismatch (
TokenUservsTokenOwner) that only affects the built-in Administrator account when UAC Admin Approval Mode is disabled for it (Windows' default for that account) — not fixable from the app's mount options. Documented for anyone else hitting it: enable "User Account Control: Admin Approval Mode for the Built-in Administrator account" (secpol.mscorFilterAdministratorToken=1) and log back in. - Startup crash after fixing the account-token issue above: files created earlier under the affected account end up owned by the
BUILTIN\Administratorsgroup instead of the user; once that account's token no longer carries the group, the app's own permission-hardening (SetFileSecurity) started failing with access denied and crashing startup. That call is now best-effort (logs a warning instead of crashing), and the app now detects this exact ownership mismatch on its own at startup and offers a one-time, UAC-elevated automatic repair (src/permission_repair.py) — so anyone hitting this after an update or reinstall gets a guided fix instead of a crash. - CLI access key could never match, for any connection:
get_by_cli_key()re-encrypted the incoming key with a fresh random AES-GCM IV and compared the result against the stored ciphertext — which uses a different random IV from when the key was originally saved, so the comparison could never succeed even for the correct key. Lookup now uses a deterministiccli_access_key_hash(SHA-256 of the plaintext key) instead; existing connections get this hash backfilled automatically on next login. - CLI SSH connections always rejected:
launch_ssh_in_current_terminal()(used by--connect-cli) set aRejectPolicyhost-key policy but never actually loadedknown_hostsinto paramiko first, so every connection was rejected as "unknown host" regardless of what was already trusted on disk. Now loads the sameknown_hostsfile the rest of the app uses before checking the policy. - Embedded terminal froze the whole window while connecting: opening an SSH session in the integrated xterm.js terminal (
terminal_clientsetting = "xterm") calledTerminalBridgeServer.create_session_token()— which runs a blockingparamiko.SSHClient.connect()— directly on the Qt main thread. A slow or unresponsive host could freeze the entire UI for the length of paramiko's auth timeout (30s by default) on top of the connect timeout. Connection setup now runs in a backgroundTerminalConnectWorker(src/ui/worker.py), matching the existingMountWorker/UnmountWorkerpattern; the tab is only created once the SSH session is actually up.
Security
- CLI access over
--connect-clinow also works for password-authenticated connections: the local IPC response includes the password (previously withheld per an earlier finding). The pipe was already restricted to the current user's SID (_make_pipe_security_attributes), the 64-byte access key itself is a strong bearer secret, and requests are already rate-limited per PID — sending the password over this already-restricted channel was the missing piece for a CLI feature whose whole purpose is unattended access to saved connections, not an added exposure.
Full Changelog: v1.5.1...v1.5.2