mirror of
https://github.com/esphome/esphome.git
synced 2026-08-22 22:26:21 +00:00
[core] fix PYTHONPATH leak (#18360)
This commit is contained in:
@@ -109,6 +109,8 @@ def _get_idf_env(version: str | None = None) -> dict[str, str]:
|
|||||||
env_cache = _cache().env
|
env_cache = _cache().env
|
||||||
if version not in env_cache:
|
if version not in env_cache:
|
||||||
env_cache[version] = os.environ.copy()
|
env_cache[version] = os.environ.copy()
|
||||||
|
# Do not leak PYTHONPATH into child env
|
||||||
|
env_cache[version].pop("PYTHONPATH", None)
|
||||||
|
|
||||||
# Use provided IDF framework if available
|
# Use provided IDF framework if available
|
||||||
if "IDF_PATH" not in os.environ:
|
if "IDF_PATH" not in os.environ:
|
||||||
|
|||||||
@@ -155,6 +155,8 @@ def run_command(
|
|||||||
_LOGGER.debug("%s - running ...", cmd_str)
|
_LOGGER.debug("%s - running ...", cmd_str)
|
||||||
|
|
||||||
run_env = os.environ.copy()
|
run_env = os.environ.copy()
|
||||||
|
# Do not leak PYTHONPATH
|
||||||
|
run_env.pop("PYTHONPATH", None)
|
||||||
if env:
|
if env:
|
||||||
run_env.update(env)
|
run_env.update(env)
|
||||||
|
|
||||||
|
|||||||
@@ -265,6 +265,21 @@ def test_get_idf_env_sets_git_ceiling_directories(setup_core: Path) -> None:
|
|||||||
assert str(CORE.config_dir) in env["GIT_CEILING_DIRECTORIES"].split(os.pathsep)
|
assert str(CORE.config_dir) in env["GIT_CEILING_DIRECTORIES"].split(os.pathsep)
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_idf_env_pops_inherited_pythonpath(setup_core: Path) -> None:
|
||||||
|
"""A PYTHONPATH from the parent environment must not reach idf.py.
|
||||||
|
|
||||||
|
It would override the IDF venv's isolation, shadowing its pinned
|
||||||
|
packages and failing idf.py's dependency check.
|
||||||
|
"""
|
||||||
|
toolchain._cache().env.clear()
|
||||||
|
with patch.dict(
|
||||||
|
os.environ,
|
||||||
|
{"IDF_PATH": str(setup_core), "PYTHONPATH": "/outside/site-packages"},
|
||||||
|
):
|
||||||
|
env = toolchain._get_idf_env(version="5.5.4")
|
||||||
|
assert "PYTHONPATH" not in env
|
||||||
|
|
||||||
|
|
||||||
def test_get_cmake_output_without_build_dir(setup_core: Path) -> None:
|
def test_get_cmake_output_without_build_dir(setup_core: Path) -> None:
|
||||||
"""A build dir that was never created raises EsphomeError.
|
"""A build dir that was never created raises EsphomeError.
|
||||||
|
|
||||||
|
|||||||
@@ -188,6 +188,24 @@ def test_run_command_passes_env(mock_subprocess_run: Mock) -> None:
|
|||||||
assert mock_subprocess_run.call_args[1]["env"]["MY_VAR"] == "42"
|
assert mock_subprocess_run.call_args[1]["env"]["MY_VAR"] == "42"
|
||||||
|
|
||||||
|
|
||||||
|
def test_run_command_pops_inherited_pythonpath(mock_subprocess_run: Mock) -> None:
|
||||||
|
"""A PYTHONPATH from the parent environment must not leak into subprocesses."""
|
||||||
|
mock_subprocess_run.return_value = Mock(returncode=0, stdout="", stderr="")
|
||||||
|
with patch.dict(os.environ, {"PYTHONPATH": "/outside/site-packages"}):
|
||||||
|
run_command(["cmd"])
|
||||||
|
assert "PYTHONPATH" not in mock_subprocess_run.call_args[1]["env"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_run_command_env_pythonpath_preferred_over_pop(
|
||||||
|
mock_subprocess_run: Mock,
|
||||||
|
) -> None:
|
||||||
|
"""A PYTHONPATH set explicitly via ``env`` is passed through."""
|
||||||
|
mock_subprocess_run.return_value = Mock(returncode=0, stdout="", stderr="")
|
||||||
|
with patch.dict(os.environ, {"PYTHONPATH": "/outside/site-packages"}):
|
||||||
|
run_command(["cmd"], env={"PYTHONPATH": "/idf/tools"})
|
||||||
|
assert mock_subprocess_run.call_args[1]["env"]["PYTHONPATH"] == "/idf/tools"
|
||||||
|
|
||||||
|
|
||||||
def test_run_command_passes_cwd(mock_subprocess_run: Mock, tmp_path: Path) -> None:
|
def test_run_command_passes_cwd(mock_subprocess_run: Mock, tmp_path: Path) -> None:
|
||||||
mock_subprocess_run.return_value = Mock(returncode=0, stdout="", stderr="")
|
mock_subprocess_run.return_value = Mock(returncode=0, stdout="", stderr="")
|
||||||
run_command(["cmd"], cwd=str(tmp_path))
|
run_command(["cmd"], cwd=str(tmp_path))
|
||||||
|
|||||||
Reference in New Issue
Block a user