This vulnerability stems from a single architectural assumption that crept into three layers of the tabby-ssh codebase: that SFTP filename responses are "clean" data rather than untrusted input requiring defensive sanitization. The SFTPSession layer used POSIX path processing — reasonable for the session layer's purposes. The downloadFolderRecursive() method propagated item.name unchanged — reasonable if you trust upstream data. Then ElectronDirectoryDownload.createFile() called Windows-native path.join() with those un-sanitized names — correct for Windows, catastrophic when the SFTP server returns filenames containing backslashes. Each component was correct in isolation; the failure was the implicit trust boundary between the protocol layer and the filesystem layer.
The cross-platform dimension is critical here. On POSIX systems, backslashes in a filename are just characters. On Windows, they're path separators with semantic meaning. The developers likely tested on Linux/macOS where the behavior "worked fine," never imagining a server would return a filename like ".....ssh\authorized_keys". The SFTP protocol permits arbitrary byte sequences in filenames — it makes no promises about what a server will return.
What makes this particularly dangerous is the blast radius. Terminal emulators are credential-adjacent infrastructure — they disproportionately store SSH keys, config files with credentials, and sensitive dotfiles. An attacker who compromises a single SFTP server doesn't just get arbitrary file write; they get arbitrary file write in a context likely to contain elevated access to secrets. There's also a temporal dimension: if a malicious server returns backslash-containing filenames once, subsequent operations on that session's cached directory listing inherit the corrupted state. The cascade isn't just one call chain — it's persistent contamination that could affect future operations even after the malicious server disconnects.
The fix is simple — normalize path separators before path construction — but it creates a single checkpoint in a river with no banks. The real vulnerability is the assumption that protocol-layer data is inherently safe relative to the target filesystem. That assumption survives the fix, just with one valve installed. Future developers will see normalized separators and assume the trust boundary is handled — but what about the other places tabby-ssh propagates item.name? What about third-party plugins? The normalization should happen at the SFTPSession ingestion layer, not in application code, so downstream components can't accidentally bypass it.
This isn't a novel failure mode. CVE-2019-6111 (OpenSSH scp filename injection) and related rsync-over-SSH bugs established that applications using SFTP responses as filenames without normalization are vulnerable. The lesson never propagated because those CVEs were framed as server-side fixes rather than client-side hardening requirements. The institutional memory failure isn't just the 1990s web server analogy — it's that the SFTP-specific variant was documented within the last five years and still didn't register in tabby's threat model.