security-review/tests/test_pre_push_hook.py

100 lines
3 KiB
Python
Raw Normal View History

"""Regression tests for the global pre-push security hook fail-closed behavior."""
from __future__ import annotations
import os
import subprocess
from pathlib import Path
import pytest
REPO_ROOT = Path(__file__).resolve().parents[1]
PRE_PUSH = REPO_ROOT / "hooks" / "pre-push"
@pytest.fixture
def temp_git_repo(tmp_path: Path) -> Path:
"""Minimal git repo so the hook's git rev-parse succeeds."""
repo = tmp_path / "repo"
repo.mkdir()
subprocess.run(["git", "init"], cwd=repo, check=True, capture_output=True)
subprocess.run(
["git", "config", "user.email", "test@example.com"],
cwd=repo,
check=True,
capture_output=True,
)
subprocess.run(
["git", "config", "user.name", "Test"],
cwd=repo,
check=True,
capture_output=True,
)
(repo / "README").write_text("x\n", encoding="utf-8")
subprocess.run(["git", "add", "README"], cwd=repo, check=True, capture_output=True)
subprocess.run(
["git", "commit", "-m", "init"],
cwd=repo,
check=True,
capture_output=True,
)
return repo
def _run_hook(
repo: Path, review_sh: str | Path, *, env_extra: dict[str, str] | None = None
) -> subprocess.CompletedProcess[str]:
env = os.environ.copy()
env["SH_REVIEW_SH"] = str(review_sh)
if env_extra:
env.update(env_extra)
return subprocess.run(
["bash", str(PRE_PUSH)],
cwd=repo,
env=env,
capture_output=True,
text=True,
check=False,
)
def test_missing_scanner_fails_closed(temp_git_repo: Path, tmp_path: Path) -> None:
missing = tmp_path / "no-such-review.sh"
result = _run_hook(temp_git_repo, missing)
assert result.returncode == 1
assert str(missing) in result.stderr
assert "missing or not executable" in result.stderr
assert "install-hooks.sh --global" in result.stderr
def test_non_executable_scanner_fails_closed(
temp_git_repo: Path, tmp_path: Path
) -> None:
stub = tmp_path / "review.sh"
stub.write_text("#!/usr/bin/env bash\nexit 0\n", encoding="utf-8")
stub.chmod(0o644)
result = _run_hook(temp_git_repo, stub)
assert result.returncode == 1
assert str(stub) in result.stderr
assert "missing or not executable" in result.stderr
assert "install-hooks.sh --global" in result.stderr
def test_scanner_success_allows_push(temp_git_repo: Path, tmp_path: Path) -> None:
stub = tmp_path / "review.sh"
stub.write_text("#!/usr/bin/env bash\nexit 0\n", encoding="utf-8")
stub.chmod(0o755)
result = _run_hook(temp_git_repo, stub)
assert result.returncode == 0
assert "BLOCKED" not in result.stderr
assert "missing or not executable" not in result.stderr
def test_scanner_block_blocks_push(temp_git_repo: Path, tmp_path: Path) -> None:
stub = tmp_path / "review.sh"
stub.write_text("#!/usr/bin/env bash\nexit 1\n", encoding="utf-8")
stub.chmod(0o755)
result = _run_hook(temp_git_repo, stub)
assert result.returncode == 1
assert "BLOCKED" in result.stderr