summaryrefslogtreecommitdiff
path: root/setuptools
diff options
context:
space:
mode:
authorMike Salvatore <mike.s.salvatore@gmail.com>2022-09-18 19:30:03 -0400
committerMike Salvatore <mike.s.salvatore@gmail.com>2022-09-18 19:30:03 -0400
commit4249da1ecfaca9541d64f0d3c7f08fb22e73e3b9 (patch)
tree8263e1b19f96844f8e6fded9c1a1f8932a5c129b /setuptools
parentba3995e5705a22e13bb5d2231ac22c77e4417747 (diff)
downloadpython-setuptools-git-4249da1ecfaca9541d64f0d3c7f08fb22e73e3b9.tar.gz
Catch an edge case in expand._assert_local()
Using str.startswith() has an edge case where someone can access files outside the root directory. For example, consider the case where the root directory is "/home/user/my-package" but some secrets are stored in "/home/user/my-package-secrets". Evaluating a check that "/home/user/my-package-secrets".startswith("/home/user/my-package") will return True, but the statement's intention is that no file outside of "/home/user/my-package" can be accessed. Using pathlib.Path.resolve() and pathlib.Path.parents eliminates this edge case.
Diffstat (limited to 'setuptools')
-rw-r--r--setuptools/config/expand.py5
-rw-r--r--setuptools/tests/config/test_expand.py9
2 files changed, 13 insertions, 1 deletions
diff --git a/setuptools/config/expand.py b/setuptools/config/expand.py
index 384504d8..1497b20c 100644
--- a/setuptools/config/expand.py
+++ b/setuptools/config/expand.py
@@ -41,6 +41,7 @@ from typing import (
Union,
cast
)
+from pathlib import Path
from types import ModuleType
from distutils.errors import DistutilsOptionError
@@ -150,7 +151,9 @@ def _read_file(filepath: Union[bytes, _Path]) -> str:
def _assert_local(filepath: _Path, root_dir: str):
- if not os.path.abspath(filepath).startswith(root_dir):
+ # NOTE: Path.resolve() will raise RuntimeError if an infinite loop is
+ # encountered along the resolution path of root_dir or file_path.
+ if Path(root_dir).resolve() not in Path(filepath).resolve().parents:
msg = f"Cannot access {filepath!r} (or anything outside {root_dir!r})"
raise DistutilsOptionError(msg)
diff --git a/setuptools/tests/config/test_expand.py b/setuptools/tests/config/test_expand.py
index 523779a8..87e00438 100644
--- a/setuptools/tests/config/test_expand.py
+++ b/setuptools/tests/config/test_expand.py
@@ -1,4 +1,5 @@
import os
+from pathlib import Path
import pytest
@@ -45,6 +46,10 @@ def test_read_files(tmp_path, monkeypatch):
}
write_files(files, dir_)
+ secrets = Path(str(dir_) + "secrets")
+ secrets.mkdir(exist_ok=True)
+ write_files({"secrets.txt": "secret keys"}, secrets)
+
with monkeypatch.context() as m:
m.chdir(dir_)
assert expand.read_files(list(files)) == "a\nb\nc"
@@ -53,6 +58,10 @@ def test_read_files(tmp_path, monkeypatch):
with pytest.raises(DistutilsOptionError, match=cannot_access_msg):
expand.read_files(["../a.txt"])
+ cannot_access_secrets_msg = r"Cannot access '.*secrets\.txt'"
+ with pytest.raises(DistutilsOptionError, match=cannot_access_secrets_msg):
+ expand.read_files(["../dir_secrets/secrets.txt"])
+
# Make sure the same APIs work outside cwd
assert expand.read_files(list(files), dir_) == "a\nb\nc"
with pytest.raises(DistutilsOptionError, match=cannot_access_msg):