-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathno_github_guard.py
More file actions
executable file
·123 lines (109 loc) · 4.36 KB
/
no_github_guard.py
File metadata and controls
executable file
·123 lines (109 loc) · 4.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/env python3
# @bigd-hook-meta
# name: no_github_guard
# fires_on: PreToolUse
# relevant_intents: [git, pm, code]
# irrelevant_intents: [bigd, telegram, docx, x_tweet, vps, sync, memory, debug]
# cost_score: 1
# always_fire: false
"""PreToolUse hook: permanently block `git push`, `git remote add`, and
`git clone` for projects that MUST NEVER reach GitHub or any public remote.
Contains trading logic, private wallet keys in .env, cartel intel, and
other Mac-local-forever artefacts. Self-hosted ssh://... remotes may be
added manually by the user if desired — this guard targets GitHub/public
remotes only.
DO NOT remove entries from this set unless the user explicitly says the
project is now safe for GitHub (usually because they scrubbed secrets +
forked to a new clean repo). "Create a GitHub repo" is NOT a remediation
path — these projects are intentionally off-GitHub.
"""
import json
import re
import sys
from pathlib import Path
NEVER_GITHUB_PROJECTS: set[str] = {
"/Users/bernard/on-chain-bots/dagou",
"/Users/bernard/on-chain-bots/hyperliquid",
"/Users/bernard/on-chain-bots/hyperliquid-ts",
"/Users/bernard/on-chain-bots/sniper",
"/Users/bernard/on-chain-bots/shared",
"/Users/bernard/prediction-markets",
# Add more private projects here as they appear.
}
def main() -> None:
try:
data = json.load(sys.stdin)
except (json.JSONDecodeError, EOFError, ValueError):
print(json.dumps({}))
return
tool = data.get("tool_name", "")
if tool != "Bash":
print(json.dumps({}))
return
cmd: str = data.get("tool_input", {}).get("command", "")
cwd: str = data.get("cwd", "") or data.get("tool_input", {}).get("cwd", "")
# Fire only on git push, git remote add, or git clone into a protected path.
risky = re.search(r"\bgit\s+(push|remote\s+add|clone)\b", cmd)
if not risky:
print(json.dumps({}))
return
# Only block if the command targets a PUBLIC remote — GitHub/GitLab/Bitbucket.
# Self-hosted ssh://... and user@host:... remotes are explicitly allowed
# (honors the module docstring). Detect by scanning the command for known
# public hostnames. If the push uses a bare remote name ("origin"), the URL
# isn't in the command — fall back to checking the configured remote URL.
PUBLIC_HOSTS = ("github.com", "gitlab.com", "bitbucket.org")
cmd_public = any(h in cmd for h in PUBLIC_HOSTS)
def remote_is_public(project_dir: str, cmd_text: str) -> bool:
if cmd_public:
return True
# `git push <remote> ...` — the second token is the remote name.
m = re.search(r"\bgit\s+push\s+(\S+)", cmd_text)
remote_name = m.group(1) if m else "origin"
if "://" in remote_name or remote_name.startswith("git@"):
return any(h in remote_name for h in PUBLIC_HOSTS)
import subprocess
try:
url = subprocess.check_output(
["git", "-C", project_dir, "remote", "get-url", remote_name],
stderr=subprocess.DEVNULL, timeout=3,
).decode().strip()
except Exception:
return False
return any(h in url for h in PUBLIC_HOSTS)
for protected in NEVER_GITHUB_PROJECTS:
hit = (
(cwd and Path(cwd).resolve().as_posix().startswith(protected))
or (protected in cmd)
)
if not hit:
continue
if not remote_is_public(protected, cmd):
continue
print(json.dumps({
"decision": "block",
"reason": (
f"BLOCKED: `{protected}` is in NEVER_GITHUB_PROJECTS. "
f"This project must NEVER reach GitHub/public remotes "
f"(trading logic, wallet keys, cartel intel). "
f"Self-hosted ssh remotes are fine if needed; use a "
f"different command that doesn't target github.com."
),
}))
return
print(json.dumps({}))
if __name__ == "__main__":
import io
import os
sys.path.insert(0, os.path.dirname(__file__))
_raw = sys.stdin.read()
try:
_prompt = json.loads(_raw).get("prompt", "") if _raw else ""
except Exception:
_prompt = ""
from _semantic_router import should_fire
if not should_fire(__file__, _prompt):
print("{}")
sys.exit(0)
sys.stdin = io.StringIO(_raw)
main()