example
This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
"""Tests for flow.commands.bootstrap helpers and schema behavior."""
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from flow.commands.bootstrap import (
|
||||
_ensure_required_variables,
|
||||
_get_profiles,
|
||||
_install_binary_package,
|
||||
_normalize_profile_package_entry,
|
||||
_resolve_package_manager,
|
||||
_resolve_package_spec,
|
||||
@@ -141,3 +143,73 @@ def test_ensure_required_variables_accepts_vars(monkeypatch):
|
||||
env["USER_EMAIL"] = "a@b"
|
||||
env["TARGET_HOSTNAME"] = "devbox"
|
||||
_ensure_required_variables({"requires": ["USER_EMAIL", "TARGET_HOSTNAME"]}, env)
|
||||
|
||||
|
||||
class _FakeResponse:
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc, tb):
|
||||
return False
|
||||
|
||||
def read(self):
|
||||
return b"archive"
|
||||
|
||||
|
||||
def _patch_binary_download(monkeypatch, after_unpack=None):
|
||||
monkeypatch.setattr(
|
||||
"flow.commands.bootstrap.urllib.request.urlopen",
|
||||
lambda *args, **kwargs: _FakeResponse(),
|
||||
)
|
||||
|
||||
def _fake_unpack(_archive, extract_dir):
|
||||
extracted = Path(extract_dir)
|
||||
extracted.mkdir(parents=True, exist_ok=True)
|
||||
if after_unpack:
|
||||
after_unpack(extracted)
|
||||
|
||||
monkeypatch.setattr("flow.commands.bootstrap.shutil.unpack_archive", _fake_unpack)
|
||||
|
||||
|
||||
def test_install_binary_package_rejects_absolute_declared_path(monkeypatch, tmp_path, ctx):
|
||||
absolute_item = tmp_path / "outside-bin"
|
||||
absolute_item.write_text("binary")
|
||||
|
||||
_patch_binary_download(monkeypatch)
|
||||
monkeypatch.setattr(
|
||||
"flow.commands.bootstrap._copy_install_item",
|
||||
lambda *args, **kwargs: pytest.fail("_copy_install_item should not be called"),
|
||||
)
|
||||
|
||||
spec = {
|
||||
"name": "demo",
|
||||
"type": "binary",
|
||||
"source": "https://example.invalid/demo",
|
||||
"asset-pattern": "demo.tar.gz",
|
||||
"install": {"bin": [str(absolute_item)]},
|
||||
}
|
||||
|
||||
with pytest.raises(RuntimeError, match="must be relative"):
|
||||
_install_binary_package(ctx, spec, {}, dry_run=False)
|
||||
|
||||
|
||||
def test_install_binary_package_rejects_parent_traversal_declared_path(monkeypatch, ctx):
|
||||
def _after_unpack(extracted):
|
||||
(extracted.parent / "escape-bin").write_text("binary")
|
||||
|
||||
_patch_binary_download(monkeypatch, after_unpack=_after_unpack)
|
||||
monkeypatch.setattr(
|
||||
"flow.commands.bootstrap._copy_install_item",
|
||||
lambda *args, **kwargs: pytest.fail("_copy_install_item should not be called"),
|
||||
)
|
||||
|
||||
spec = {
|
||||
"name": "demo",
|
||||
"type": "binary",
|
||||
"source": "https://example.invalid/demo",
|
||||
"asset-pattern": "demo.tar.gz",
|
||||
"install": {"bin": ["../escape-bin"]},
|
||||
}
|
||||
|
||||
with pytest.raises(RuntimeError, match="parent traversal"):
|
||||
_install_binary_package(ctx, spec, {}, dry_run=False)
|
||||
|
||||
Reference in New Issue
Block a user