import importlib.util, json, subprocess, sys HOOK = "scripts/claude-hooks/check-secret-read.py" spec = importlib.util.spec_from_file_location("h", HOOK) m = importlib.util.module_from_spec(spec) spec.loader.exec_module(m) F = "/opt/gendesign/backend/.env" + ".runtime" K = "METRICS_UI_PASSWORD" cases = [ (f"timeout 40 ssh -o BatchMode=yes gendesign \"grep '^{K}=' {F}\"", True, "разрешённый anchored-греп"), (f"ssh gendesign \"grep -v '^{K}=' {F}\"", False, "инверсия -v"), (f"ssh gendesign \"grep '^{K}=' {F}; cat {F}\"", False, "цепочка ;"), (f"ssh gendesign \"grep '^{K}=' {F} | cat {F}\"", False, "пайп"), (f"ssh gendesign \"grep '^{K}=' {F} > /tmp/x\"", False, "редирект"), (f"ssh gendesign \"grep '^POSTGRES_PASSWORD=' {F}\"", False, "другой ключ"), (f"ssh gendesign \"grep '{K}' {F}\"", False, "без якоря ^"), (f"cat {F}", False, "обычный cat"), (f"ssh gendesign \"grep '^{K}=' {F} && cat {F}\"", False, "цепочка &&"), (f"ssh gendesign \"grep '^{K}=' $(echo {F})\"", False, "подстановка"), ] ok = True for cmd, want, name in cases: got = m._is_allowed_key_read(cmd) if got != want: ok = False print(f"{'OK ' if got == want else 'FAIL'} allow={str(got):5} want={str(want):5} {name}") print("--- end-to-end через сам хук ---") for cmd, want_allow, name in cases: p = subprocess.run( [sys.executable, HOOK], input=json.dumps({"tool_name": "Bash", "tool_input": {"command": cmd}}), capture_output=True, text=True, ) allowed = p.returncode == 0 if allowed != want_allow: ok = False print(f"FAIL rc={p.returncode} want_allow={want_allow} {name}") print("ALL OK" if ok else "ЕСТЬ ПРОВАЛЫ")