Summary
When sftp.root (SFTP chroot) is configured, directory listing works but every path resolution fails — you can ls the root and see entries, but cd <subdir>, get <file>, and even get <file-at-root> all fail. This makes the sftp.root confinement feature unusable.
Reproduces on both macOS (aarch64) and Linux (x86_64-musl) builds of bssh-server v2.2.3.
Reproduction
Config (config.yaml):
server:
bind_address: 127.0.0.1
port: 2223
host_keys: [/tmp/cctest/hostkey]
auth:
methods: [publickey]
publickey:
authorized_keys_pattern: /tmp/cctest/{user}.keys
sftp:
enabled: true
root: /tmp/cctest/data # <-- chroot
Data layout:
/tmp/cctest/data/hello.txt
/tmp/cctest/data/subdir/nested.txt
Run: bssh-server run -c config.yaml -D, then connect with the OpenSSH sftp client:
sftp> pwd
Remote working directory: /
sftp> ls
hello.txt subdir # <-- readdir OK
sftp> cd subdir
realpath /subdir: Access denied: path outside root # <-- BUG
sftp> get subdir/nested.txt
File "/subdir/nested.txt" not found. # <-- BUG
sftp> get hello.txt
File "/hello.txt" not found. # <-- BUG (file is at chroot root!)
Expected
cd subdir → enters /subdir (i.e. <root>/subdir)
get hello.txt → downloads <root>/hello.txt
get subdir/nested.txt → downloads <root>/subdir/nested.txt
Actual
ls (readdir) resolves entries under the chroot root correctly.
- But
realpath/open/stat of any path — including a file directly at the chroot root — is rejected as path outside root or not found.
So there is an inconsistency between the readdir path handling and the open/realpath path handling when sftp.root is set: listing translates the chroot correctly, but per-path resolution does not (it appears to treat the virtual /… as an absolute host path and then reject it against the root boundary).
Workaround
Leave sftp.root unset (root: null) — without chroot, all SFTP operations work correctly (verified: nav, upload, download, rename, chmod, rm/rmdir, spaces/unicode filenames, multi-MB binary transfer with matching checksum).
Environment
bssh-server 2.2.3 (bssh-server-macos-aarch64 and bssh-server-linux-x86_64-musl)
- OpenSSH
sftp client
Summary
When
sftp.root(SFTP chroot) is configured, directory listing works but every path resolution fails — you canlsthe root and see entries, butcd <subdir>,get <file>, and evenget <file-at-root>all fail. This makes thesftp.rootconfinement feature unusable.Reproduces on both macOS (aarch64) and Linux (x86_64-musl) builds of
bssh-serverv2.2.3.Reproduction
Config (
config.yaml):Data layout:
Run:
bssh-server run -c config.yaml -D, then connect with the OpenSSHsftpclient:Expected
cd subdir→ enters/subdir(i.e.<root>/subdir)get hello.txt→ downloads<root>/hello.txtget subdir/nested.txt→ downloads<root>/subdir/nested.txtActual
ls(readdir) resolves entries under the chroot root correctly.realpath/open/statof any path — including a file directly at the chroot root — is rejected aspath outside rootornot found.So there is an inconsistency between the readdir path handling and the open/realpath path handling when
sftp.rootis set: listing translates the chroot correctly, but per-path resolution does not (it appears to treat the virtual/…as an absolute host path and then reject it against the root boundary).Workaround
Leave
sftp.rootunset (root: null) — without chroot, all SFTP operations work correctly (verified: nav, upload, download, rename, chmod, rm/rmdir, spaces/unicode filenames, multi-MB binary transfer with matching checksum).Environment
bssh-server2.2.3 (bssh-server-macos-aarch64andbssh-server-linux-x86_64-musl)sftpclient