@wernerbisschoff/pi-gatekeeper 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +122 -0
- package/dist/default-rules.json +216 -0
- package/dist/gatekeeper.d.ts +621 -0
- package/dist/gatekeeper.d.ts.map +1 -0
- package/dist/gatekeeper.js +2715 -0
- package/dist/gatekeeper.js.map +1 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# pi-gatekeeper
|
|
2
|
+
|
|
3
|
+
**Permission enforcement extension for [Pi/OMP](https://pi.dev).**
|
|
4
|
+
|
|
5
|
+
Gatekeeper replaces pi's `bash` tool with a mode-aware wrapper that classifies shell commands against configurable allow/deny/ask rules and blocks access to sensitive file paths (`.env`, `~/.ssh/`, crypto keys, etc.). It's designed as a security layer for teams that share pi configurations or want guardrails without leaving the terminal.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Global (all projects)
|
|
11
|
+
pi install npm:@wernerbisschoff/pi-gatekeeper
|
|
12
|
+
|
|
13
|
+
# Project-local
|
|
14
|
+
pi install npm:@wernerbisschoff/pi-gatekeeper -l
|
|
15
|
+
|
|
16
|
+
# Try once without installing
|
|
17
|
+
pi -e npm:@wernerbisschoff/pi-gatekeeper
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick start
|
|
21
|
+
|
|
22
|
+
Once installed, gatekeeper runs automatically on every `session_start`. The default mode is **medium**.
|
|
23
|
+
|
|
24
|
+
### Permission modes
|
|
25
|
+
|
|
26
|
+
| Mode | Guard | Best for |
|
|
27
|
+
|------|-------|----------|
|
|
28
|
+
| 🔵 LOW | Read-only commands plus `git status/log/diff` etc. | Auditing, reviewing, pair-programming observers |
|
|
29
|
+
| 🟡 MEDIUM | Read + safe writes (git push/commit, npm install) | Day-to-day development |
|
|
30
|
+
| 🟠HIGH | Everything except `rm -rf /`, `mkfs`, `dd of=/dev/`, `eval`, `curl\|sh` | Full-access sessions, CI debugging |
|
|
31
|
+
|
|
32
|
+
### Switch modes
|
|
33
|
+
|
|
34
|
+
Use the `/perm` slash command inside pi:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
/perm → cycle: low → medium → high → low
|
|
38
|
+
/perm low → set explicitly
|
|
39
|
+
/perm medium → set explicitly
|
|
40
|
+
/perm high → set explicitly
|
|
41
|
+
/perm allowlist → inspect the current rules and file path
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Or pass a CLI flag on startup:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pi --perm-mode low
|
|
48
|
+
pi --perm-mode medium
|
|
49
|
+
pi --perm-mode high
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The CLI flag overrides the persisted mode for the current session only — the next session resumes at the persisted level.
|
|
53
|
+
|
|
54
|
+
## How it works
|
|
55
|
+
|
|
56
|
+
1. **On session start**, gatekeeper bootstraps `~/.pi/agent/perm-rules.json` from the bundled defaults (if absent), or loads the existing file.
|
|
57
|
+
2. **Every `bash` tool call** is classified by the gatekeeper's classifier against the per-level deny/allow/ask lists. Blocked commands are rejected before execution.
|
|
58
|
+
3. **Sensitive paths** (`read`/`edit`/`write` to `.env`, `~/.ssh/`, `*.pem`, etc.) are blocked unconditionally regardless of mode — these are compile-time guards, not user-configurable.
|
|
59
|
+
4. **Mode changes** persist to `perm-rules.json` and update the TUI footer indicator immediately.
|
|
60
|
+
|
|
61
|
+
## Configuration
|
|
62
|
+
|
|
63
|
+
Edit `~/.pi/agent/perm-rules.json` directly to customise the per-level deny/allow/ask lists:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"version": 2,
|
|
68
|
+
"currentMode": "medium",
|
|
69
|
+
"rules": {
|
|
70
|
+
"low": { "deny": ["..."], "allow": ["..."], "ask": [] },
|
|
71
|
+
"medium": { "deny": ["..."], "allow": ["..."], "ask": [] },
|
|
72
|
+
"high": { "deny": ["..."], "allow": ["..."], "ask": [] }
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Use `/perm allowlist` inside pi to inspect the current rules. The file supports all three tri-state lists:
|
|
78
|
+
|
|
79
|
+
- **deny** — commands that are always blocked at this level
|
|
80
|
+
- **allow** — commands allowed without confirmation
|
|
81
|
+
- **ask** — (future) commands that trigger a confirmation prompt
|
|
82
|
+
|
|
83
|
+
The classifier supports glob-style matching (`*` wildcard) so `git push *` matches `git push origin main`.
|
|
84
|
+
|
|
85
|
+
## Sensitive paths (always blocked)
|
|
86
|
+
|
|
87
|
+
| Pattern | Reason |
|
|
88
|
+
|---------|--------|
|
|
89
|
+
| `.env*` | Environment files (secrets) |
|
|
90
|
+
| `~/.ssh/` | SSH keys |
|
|
91
|
+
| `~/.aws/` | AWS credentials |
|
|
92
|
+
| `~/.gnupg/` | GPG keys |
|
|
93
|
+
| `~/.kube/` | Kubernetes config |
|
|
94
|
+
| `*.pem`, `*.key`, `*.crt` | Crypto material |
|
|
95
|
+
| `.netrc` | Generic credential store |
|
|
96
|
+
| `.npmrc` | npm auth tokens |
|
|
97
|
+
| `.pypirc` | PyPI credentials |
|
|
98
|
+
| `.git-credentials` | Git plaintext credentials |
|
|
99
|
+
| `~/.docker/config.json` | Docker registry auth |
|
|
100
|
+
| `~/.config/gh/hosts.yml` | GitHub CLI tokens |
|
|
101
|
+
|
|
102
|
+
These patterns are compile-time constants — they cannot be overridden by user config (by design).
|
|
103
|
+
|
|
104
|
+
## Development
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
git clone https://github.com/wernerbisschoff/pi-gatekeeper.git
|
|
108
|
+
cd pi-gatekeeper
|
|
109
|
+
npm install
|
|
110
|
+
npm run build
|
|
111
|
+
npm test
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Load locally during development
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
pi -e ./src/gatekeeper.ts
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## License
|
|
121
|
+
|
|
122
|
+
MIT
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 2,
|
|
3
|
+
"currentMode": "medium",
|
|
4
|
+
"rules": {
|
|
5
|
+
"low": {
|
|
6
|
+
"deny": [
|
|
7
|
+
"rm -rf /",
|
|
8
|
+
"mkfs",
|
|
9
|
+
"dd of=/dev/",
|
|
10
|
+
"eval",
|
|
11
|
+
"curl|sh",
|
|
12
|
+
"wget|sh",
|
|
13
|
+
"shutdown",
|
|
14
|
+
"rm -rf /*",
|
|
15
|
+
"mkfs *",
|
|
16
|
+
"dd of=/dev/*",
|
|
17
|
+
"eval *",
|
|
18
|
+
"curl *|sh",
|
|
19
|
+
"wget *|sh",
|
|
20
|
+
"reboot",
|
|
21
|
+
"halt",
|
|
22
|
+
"poweroff",
|
|
23
|
+
"init 0",
|
|
24
|
+
"init 1",
|
|
25
|
+
"init 2",
|
|
26
|
+
"init 3",
|
|
27
|
+
"init 4",
|
|
28
|
+
"init 5",
|
|
29
|
+
"init 6",
|
|
30
|
+
"init 0-6"
|
|
31
|
+
],
|
|
32
|
+
"allow": [
|
|
33
|
+
"ls",
|
|
34
|
+
"ls *",
|
|
35
|
+
"find",
|
|
36
|
+
"find *",
|
|
37
|
+
"cat",
|
|
38
|
+
"cat *",
|
|
39
|
+
"echo",
|
|
40
|
+
"echo *",
|
|
41
|
+
"cd",
|
|
42
|
+
"cd *",
|
|
43
|
+
"pwd",
|
|
44
|
+
"which",
|
|
45
|
+
"which *",
|
|
46
|
+
"type",
|
|
47
|
+
"type *",
|
|
48
|
+
"whoami",
|
|
49
|
+
"id",
|
|
50
|
+
"id *",
|
|
51
|
+
"date",
|
|
52
|
+
"head",
|
|
53
|
+
"head *",
|
|
54
|
+
"tail",
|
|
55
|
+
"tail *",
|
|
56
|
+
"wc",
|
|
57
|
+
"wc *",
|
|
58
|
+
"sort",
|
|
59
|
+
"sort *",
|
|
60
|
+
"uniq",
|
|
61
|
+
"uniq *",
|
|
62
|
+
"cut",
|
|
63
|
+
"cut *",
|
|
64
|
+
"readlink",
|
|
65
|
+
"readlink *",
|
|
66
|
+
"realpath",
|
|
67
|
+
"realpath *",
|
|
68
|
+
"dirname",
|
|
69
|
+
"dirname *",
|
|
70
|
+
"basename",
|
|
71
|
+
"basename *",
|
|
72
|
+
"env",
|
|
73
|
+
"env *",
|
|
74
|
+
"printenv",
|
|
75
|
+
"printenv *",
|
|
76
|
+
"ps",
|
|
77
|
+
"ps *",
|
|
78
|
+
"top",
|
|
79
|
+
"df",
|
|
80
|
+
"df *",
|
|
81
|
+
"du",
|
|
82
|
+
"du *",
|
|
83
|
+
"uptime",
|
|
84
|
+
"uname",
|
|
85
|
+
"uname *",
|
|
86
|
+
"locale",
|
|
87
|
+
"locale *",
|
|
88
|
+
"getconf",
|
|
89
|
+
"getconf *",
|
|
90
|
+
"git status",
|
|
91
|
+
"git status *",
|
|
92
|
+
"git log",
|
|
93
|
+
"git log *",
|
|
94
|
+
"git diff",
|
|
95
|
+
"git diff *",
|
|
96
|
+
"git show",
|
|
97
|
+
"git show *",
|
|
98
|
+
"git grep",
|
|
99
|
+
"git grep *",
|
|
100
|
+
"git blame",
|
|
101
|
+
"git blame *",
|
|
102
|
+
"git branch",
|
|
103
|
+
"git fetch",
|
|
104
|
+
"git fetch *",
|
|
105
|
+
"git remote",
|
|
106
|
+
"git remote -v",
|
|
107
|
+
"git stash list",
|
|
108
|
+
"git stash show",
|
|
109
|
+
"git stash show *",
|
|
110
|
+
"git tag",
|
|
111
|
+
"git describe",
|
|
112
|
+
"git describe *",
|
|
113
|
+
"git shortlog",
|
|
114
|
+
"git shortlog *",
|
|
115
|
+
"git ls-files",
|
|
116
|
+
"git ls-files *",
|
|
117
|
+
"git rev-parse",
|
|
118
|
+
"git rev-parse *"
|
|
119
|
+
],
|
|
120
|
+
"ask": []
|
|
121
|
+
},
|
|
122
|
+
"medium": {
|
|
123
|
+
"deny": [
|
|
124
|
+
"rm -rf /",
|
|
125
|
+
"mkfs",
|
|
126
|
+
"dd of=/dev/",
|
|
127
|
+
"eval",
|
|
128
|
+
"curl|sh",
|
|
129
|
+
"wget|sh",
|
|
130
|
+
"shutdown",
|
|
131
|
+
"rm -rf /*",
|
|
132
|
+
"mkfs *",
|
|
133
|
+
"dd of=/dev/*",
|
|
134
|
+
"eval *",
|
|
135
|
+
"curl *|sh",
|
|
136
|
+
"wget *|sh",
|
|
137
|
+
"reboot",
|
|
138
|
+
"halt",
|
|
139
|
+
"poweroff",
|
|
140
|
+
"init 0",
|
|
141
|
+
"init 1",
|
|
142
|
+
"init 2",
|
|
143
|
+
"init 3",
|
|
144
|
+
"init 4",
|
|
145
|
+
"init 5",
|
|
146
|
+
"init 6",
|
|
147
|
+
"init 0-6"
|
|
148
|
+
],
|
|
149
|
+
"allow": [
|
|
150
|
+
"git push",
|
|
151
|
+
"git push *",
|
|
152
|
+
"git pull",
|
|
153
|
+
"git pull *",
|
|
154
|
+
"git commit",
|
|
155
|
+
"git commit *",
|
|
156
|
+
"git add",
|
|
157
|
+
"git add *",
|
|
158
|
+
"git merge",
|
|
159
|
+
"git merge *",
|
|
160
|
+
"git rebase",
|
|
161
|
+
"git rebase *",
|
|
162
|
+
"git checkout",
|
|
163
|
+
"git checkout *",
|
|
164
|
+
"git switch",
|
|
165
|
+
"git switch *",
|
|
166
|
+
"git restore",
|
|
167
|
+
"git restore *",
|
|
168
|
+
"git stash",
|
|
169
|
+
"git stash *",
|
|
170
|
+
"git reset",
|
|
171
|
+
"git reset *",
|
|
172
|
+
"git rm",
|
|
173
|
+
"git rm *",
|
|
174
|
+
"git mv",
|
|
175
|
+
"git mv *",
|
|
176
|
+
"git revert",
|
|
177
|
+
"git revert *",
|
|
178
|
+
"git cherry-pick",
|
|
179
|
+
"git cherry-pick *",
|
|
180
|
+
"git clean",
|
|
181
|
+
"git clean *"
|
|
182
|
+
],
|
|
183
|
+
"ask": []
|
|
184
|
+
},
|
|
185
|
+
"high": {
|
|
186
|
+
"deny": [
|
|
187
|
+
"rm -rf /",
|
|
188
|
+
"mkfs",
|
|
189
|
+
"dd of=/dev/",
|
|
190
|
+
"eval",
|
|
191
|
+
"curl|sh",
|
|
192
|
+
"wget|sh",
|
|
193
|
+
"shutdown",
|
|
194
|
+
"rm -rf /*",
|
|
195
|
+
"mkfs *",
|
|
196
|
+
"dd of=/dev/*",
|
|
197
|
+
"eval *",
|
|
198
|
+
"curl *|sh",
|
|
199
|
+
"wget *|sh",
|
|
200
|
+
"reboot",
|
|
201
|
+
"halt",
|
|
202
|
+
"poweroff",
|
|
203
|
+
"init 0",
|
|
204
|
+
"init 1",
|
|
205
|
+
"init 2",
|
|
206
|
+
"init 3",
|
|
207
|
+
"init 4",
|
|
208
|
+
"init 5",
|
|
209
|
+
"init 6",
|
|
210
|
+
"init 0-6"
|
|
211
|
+
],
|
|
212
|
+
"allow": [],
|
|
213
|
+
"ask": []
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|