metis-desk/scripts/visual-audit.test.py

88 lines
3.7 KiB
Python

#!/usr/bin/env python3
"""Regresión del aislamiento de las sesiones del lanzador, sin Docker ni credenciales."""
import json
import os
from pathlib import Path
import subprocess
import tempfile
import tomllib
import unittest
ROOT = Path(__file__).resolve().parent.parent
class SessionLauncherTests(unittest.TestCase):
def setUp(self):
artifacts = ROOT / ".artifacts/playwright"
artifacts.mkdir(parents=True, exist_ok=True)
self.directory = tempfile.TemporaryDirectory(prefix="session-guard-", dir=artifacts)
self.root = Path(self.directory.name)
self.executable = self.root / "codex-probe"
self.executable.write_text("#!/usr/bin/env python3\nimport json,sys\nprint(json.dumps({'args':sys.argv[1:],'stdin':sys.stdin.read()}))\n")
self.executable.chmod(0o700)
def tearDown(self):
self.directory.cleanup()
def state(self, domain="localhost", mode=0o600):
path = self.root / "session.json"
path.write_text(json.dumps({"cookies": [{"name": "metis.sid", "domain": domain,
"httpOnly": True, "value": "placeholder-not-a-session"}]}))
path.chmod(mode)
return path
def launch(self, state=None):
environment = {**os.environ, "METIS_CODEX_BIN": str(self.executable)}
environment.pop("METIS_PLAYWRIGHT_STORAGE_STATE", None)
if state is not None:
environment["METIS_PLAYWRIGHT_STORAGE_STATE"] = str(state)
return subprocess.run(["bash", str(ROOT / "scripts/codex-playwright-wsl.sh"), "mcp", "list", "--json"],
input="stdin-check", text=True, capture_output=True, env=environment,
cwd=self.root, timeout=15, check=False)
def args(self, result):
self.assertEqual(result.returncode, 0, result.stderr)
payload = json.loads(result.stdout)
self.assertEqual(payload["stdin"], "stdin-check")
argument = next(item for item in payload["args"] if item.startswith("mcp_servers.playwright.args="))
return tomllib.loads(argument)["mcp_servers"]["playwright"]["args"]
def test_default_has_no_session(self):
self.assertFalse(any("storage-state" in item or "type=bind" in item for item in self.args(self.launch())))
def test_private_session_is_readonly_and_not_in_arguments(self):
state = self.state()
args = self.args(self.launch(state.relative_to(ROOT)))
self.assertTrue(any("readonly" in item and str(state) in item for item in args))
self.assertEqual(args.count("--storage-state=/tmp/metis-audit-state.json"), 1)
self.assertNotIn("placeholder-not-a-session", " ".join(args))
def test_public_permissions_are_rejected(self):
result = self.launch(self.state(mode=0o644))
self.assertNotEqual(result.returncode, 0)
self.assertIn("privado", result.stderr)
def test_remote_cookie_is_rejected(self):
result = self.launch(self.state(domain="production.example.test"))
self.assertNotEqual(result.returncode, 0)
self.assertIn("locales", result.stderr)
def test_external_file_is_rejected(self):
with tempfile.TemporaryDirectory() as directory:
path = Path(directory) / "session.json"
path.write_text("{}")
path.chmod(0o600)
result = self.launch(path)
self.assertNotEqual(result.returncode, 0)
self.assertIn("privado", result.stderr)
def test_missing_session_is_rejected(self):
result = self.launch(self.root / "missing.json")
self.assertNotEqual(result.returncode, 0)
self.assertIn("ausente", result.stderr)
if __name__ == "__main__":
unittest.main()