Skip to content

Commit

Permalink
fixes #66133 path verification for symlinks with destination outside …
Browse files Browse the repository at this point in the history
…of root
  • Loading branch information
hurzhurz committed Apr 22, 2024
1 parent 38ed660 commit d3fbb96
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 3 deletions.
17 changes: 14 additions & 3 deletions salt/fileserver/roots.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,23 @@
import salt.utils.path
import salt.utils.platform
import salt.utils.stringutils
import salt.utils.verify
import salt.utils.versions

log = logging.getLogger(__name__)


def _clean_path(root, path):
if not os.path.isabs(root):
return ""
root = os.path.normpath(root)
if not os.path.isabs(path):
path = os.path.join(root, path)
path = os.path.normpath(path)
if os.path.commonpath([path, root]) == root:
return path
return ""


def find_file(path, saltenv="base", **kwargs):
"""
Search the environment for the relative path.
Expand Down Expand Up @@ -101,7 +112,7 @@ def _add_file_stat(fnd):
full = os.path.join(root, path)

# Refuse to serve file that is not under the root.
if not salt.utils.verify.clean_path(root, full, subdir=True):
if not _clean_path(root, full):
continue

if os.path.isfile(full) and not salt.fileserver.is_file_ignored(__opts__, full):
Expand Down Expand Up @@ -149,7 +160,7 @@ def serve_file(load, fnd):
if saltenv == "__env__":
root = root.replace("__env__", actual_saltenv)
# Refuse to serve file that is not under the root.
if salt.utils.verify.clean_path(root, fpath, subdir=True):
if _clean_path(root, fpath):
file_in_root = True
if not file_in_root:
return ret
Expand Down
25 changes: 25 additions & 0 deletions tests/pytests/unit/fileserver/test_roots.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,3 +315,28 @@ def test_serve_file_not_in_root(tmp_state_tree):
assert ret == {"data": "", "dest": "..\\bar"}
else:
assert ret == {"data": "", "dest": "../bar"}


def test_find_file_symlink_destination_not_in_root(tmp_state_tree):
dirname = pathlib.Path(tmp_state_tree).parent / "foo"
dirname.mkdir(parents=True, exist_ok=True)
testfile = dirname / "testfile"
testfile.write_text("testfile")
symlink = tmp_state_tree / "bar"
symlink.symlink_to(str(dirname))
ret = roots.find_file("bar/testfile")
assert ret["path"] == str(symlink / "testfile")
assert ret["rel"] == "bar/testfile"


def test_serve_file_symlink_destination_not_in_root(tmp_state_tree):
dirname = pathlib.Path(tmp_state_tree).parent / "foo"
dirname.mkdir(parents=True, exist_ok=True)
testfile = dirname / "testfile"
testfile.write_text("testfile")
symlink = tmp_state_tree / "bar"
symlink.symlink_to(str(dirname))
load = {"path": "bar/testfile", "saltenv": "base", "loc": 0}
fnd = {"path": str(symlink / "testfile"), "rel": "bar/testfile"}
ret = roots.serve_file(load, fnd)
assert ret == {"data": b"testfile", "dest": "bar/testfile"}

0 comments on commit d3fbb96

Please sign in to comment.