Files
sshfs/test/test_hostname_validation.py
Abhinav Agarwal 29bb565ea6 reject hostname option injection via bracketed mount source
A source like [-oProxyCommand=CMD]:/path passes the bracket-parsing
check in find_base_path() and ends up as -oProxyCommand=CMD in the
ssh argv.  When sftp_server is a path, ssh gets a destination argument
and executes the injected ProxyCommand before connecting.

Reject hostnames starting with - after bracket stripping, and add --
before the hostname in the ssh command line so positional args can't
be misread as options.
2026-05-29 16:00:27 -07:00

61 lines
1.5 KiB
Python

#!/usr/bin/env python3
"""Tests for hostname validation — no FUSE mount required."""
if __name__ == "__main__":
import pytest
import sys
sys.exit(pytest.main([__file__] + sys.argv[1:]))
import subprocess
from util import base_cmdline, basename
from os.path import join as pjoin
def test_reject_option_injection_in_hostname(tmpdir):
"""Bracketed source that resolves to a dash-prefixed host must be rejected."""
mnt_dir = str(tmpdir.mkdir("mnt"))
malicious = "[-oProxyCommand=echo pwned]:/path"
cmdline = base_cmdline + [
pjoin(basename, "sshfs"),
"-f",
malicious,
mnt_dir,
]
res = subprocess.run(
cmdline,
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
timeout=10,
text=True,
)
assert res.returncode != 0
assert "invalid hostname" in res.stderr
def test_reject_dash_host_after_doubledash(tmpdir):
"""Non-bracketed dash-prefixed source after -- must also be rejected."""
mnt_dir = str(tmpdir.mkdir("mnt"))
cmdline = base_cmdline + [
pjoin(basename, "sshfs"),
"-f",
"--",
"-oProxyCommand=echo pwned:/path",
mnt_dir,
]
res = subprocess.run(
cmdline,
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
timeout=10,
text=True,
)
assert res.returncode != 0
assert "invalid hostname" in res.stderr