diff options
| -rw-r--r-- | setuptools/config.py | 12 | ||||
| -rw-r--r-- | setuptools/tests/test_config.py | 12 |
2 files changed, 23 insertions, 1 deletions
diff --git a/setuptools/config.py b/setuptools/config.py index d8513a72..c2319ed5 100644 --- a/setuptools/config.py +++ b/setuptools/config.py @@ -128,7 +128,10 @@ class ConfigHandler(object): @classmethod def _parse_file(cls, value): """Represents value as a string, allowing including text - from nearest files using include(). + from nearest files using `file:` directive. + + Directive is sandboxed and won't reach anything outside + directory with setup.py. Examples: include: LICENSE @@ -144,7 +147,14 @@ class ConfigHandler(object): if not value.startswith(include_directive): return value + current_directory = os.getcwd() + filepath = value.replace(include_directive, '').strip() + filepath = os.path.abspath(filepath) + + if not filepath.startswith(current_directory): + raise DistutilsOptionError( + '`file:` directive can not access %s' % filepath) if os.path.isfile(filepath): with io.open(filepath, encoding='utf-8') as f: diff --git a/setuptools/tests/test_config.py b/setuptools/tests/test_config.py index 08c5bd19..9fb55b06 100644 --- a/setuptools/tests/test_config.py +++ b/setuptools/tests/test_config.py @@ -86,6 +86,18 @@ class TestMetadata: assert metadata.name == 'fake_name' assert metadata.keywords == ['one', 'two'] + def test_file_sandboxed(self, tmpdir): + + fake_env( + tmpdir, + '[metadata]\n' + 'long_description = file: ../../README\n' + ) + + with get_dist(tmpdir, parse=False) as dist: + with pytest.raises(DistutilsOptionError): + dist.parse_config_files() # file: out of sandbox + def test_aliases(self, tmpdir): fake_env( |
