@vtstech/pi-security 1.2.0 → 1.2.2
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 +2 -1
- package/package.json +3 -3
- package/security.js +16 -8
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ pi install "npm:@vtstech/pi-security"
|
|
|
14
14
|
|
|
15
15
|
- **Partitioned command blocklist** — 41 CRITICAL commands (always blocked: system modification, privilege escalation, network attacks, shell escapes) + 25 EXTENDED commands (blocked in max mode: package management, process control, development tools)
|
|
16
16
|
- **Mode-aware SSRF protection** — 22 ALWAYS_BLOCKED URL patterns (loopback, RFC1918 private ranges, cloud metadata endpoints) + 7 MAX_ONLY patterns (localhost by name, broadcast, link-local, current network) that are allowed in basic mode
|
|
17
|
-
- **Security mode toggle** — switch between `basic` and `
|
|
17
|
+
- **Security mode toggle** — switch between `basic`, `max`, and `off` modes at runtime; persisted to `~/.pi/agent/security.json`
|
|
18
18
|
- **Path validation** — prevents filesystem escape and access to critical system directories; symlinks are dereferenced via `fs.realpathSync()` to block `/tmp/evil → /etc/passwd` bypasses
|
|
19
19
|
- **Shell injection detection** — regex patterns for command chaining, substitution, and redirection
|
|
20
20
|
- **Full-word command scanning** — all words in a command are checked against CRITICAL_COMMANDS (catches `sudo chmod`, `exec dd`, etc.)
|
|
@@ -26,6 +26,7 @@ pi install "npm:@vtstech/pi-security"
|
|
|
26
26
|
```bash
|
|
27
27
|
/security mode basic # Relaxed — CRITICAL commands blocked, localhost URLs allowed
|
|
28
28
|
/security mode max # Full lockdown — all 66 commands blocked, strict SSRF
|
|
29
|
+
/security mode off # Disable all security checks
|
|
29
30
|
```
|
|
30
31
|
|
|
31
32
|
**Default mode: `max`**. The current mode is shown in the status bar as `SEC:BASIC` or `SEC:MAX`.
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vtstech/pi-security",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "Security extension for Pi Coding Agent",
|
|
5
5
|
"main": "security.js",
|
|
6
|
-
"keywords": ["pi-extensions"],
|
|
6
|
+
"keywords": ["pi-package", "pi", "pi-coding-agent", "pi-extensions"],
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"access": "public",
|
|
9
9
|
"type": "module",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"url": "https://github.com/VTSTech/pi-coding-agent"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@vtstech/pi-shared": "1.2.
|
|
17
|
+
"@vtstech/pi-shared": "1.2.2"
|
|
18
18
|
},
|
|
19
19
|
"peerDependencies": {
|
|
20
20
|
"@mariozechner/pi-coding-agent": ">=0.66"
|
package/security.js
CHANGED
|
@@ -52,9 +52,11 @@ function security_temp_default(pi) {
|
|
|
52
52
|
lines2.push(section("MODE DIFFERENCES"));
|
|
53
53
|
lines2.push(info("Basic: critical commands blocked, localhost/127.x allowed"));
|
|
54
54
|
lines2.push(info("Max: all commands blocked, full SSRF protection"));
|
|
55
|
+
lines2.push(info("Off: no security enforcement, all commands allowed"));
|
|
55
56
|
lines2.push(section("SWITCH MODE"));
|
|
56
57
|
lines2.push(info("/security mode basic \u2014 relax restrictions for development"));
|
|
57
58
|
lines2.push(info("/security mode max \u2014 full lockdown (default)"));
|
|
59
|
+
lines2.push(info("/security mode off \u2014 disable all security checks"));
|
|
58
60
|
lines2.push(branding);
|
|
59
61
|
pi.sendMessage({
|
|
60
62
|
customType: "security-mode-info",
|
|
@@ -63,7 +65,7 @@ function security_temp_default(pi) {
|
|
|
63
65
|
});
|
|
64
66
|
return;
|
|
65
67
|
}
|
|
66
|
-
if (value === "basic" || value === "max") {
|
|
68
|
+
if (value === "basic" || value === "max" || value === "off") {
|
|
67
69
|
if (value === currentMode) {
|
|
68
70
|
ctx.ui.notify(`Security mode is already ${value.toUpperCase()}`, "info");
|
|
69
71
|
return;
|
|
@@ -94,9 +96,12 @@ function security_temp_default(pi) {
|
|
|
94
96
|
lines2.push(warn("Extended commands are now ALLOWED: rm, sudo, npm, apt, git, curl, wget, etc."));
|
|
95
97
|
lines2.push(warn("Localhost and 127.x URLs are now ALLOWED for SSRF"));
|
|
96
98
|
lines2.push(ok("Critical commands remain blocked: dd, mkfs, shred, fdisk, ssh, etc."));
|
|
97
|
-
} else {
|
|
99
|
+
} else if (value === "max") {
|
|
98
100
|
lines2.push(ok(`Full lockdown active \u2014 all ${totalCmds} commands blocked`));
|
|
99
101
|
lines2.push(ok("Full SSRF protection \u2014 localhost and private IPs blocked"));
|
|
102
|
+
} else if (value === "off") {
|
|
103
|
+
lines2.push(ok("Security enforcement disabled \u2014 all commands allowed"));
|
|
104
|
+
lines2.push(ok("SSRF protection disabled \u2014 all URLs allowed"));
|
|
100
105
|
}
|
|
101
106
|
lines2.push(branding);
|
|
102
107
|
pi.sendMessage({
|
|
@@ -106,7 +111,7 @@ function security_temp_default(pi) {
|
|
|
106
111
|
});
|
|
107
112
|
return;
|
|
108
113
|
}
|
|
109
|
-
ctx.ui.notify(`Invalid mode: "${value}". Use "basic" or "
|
|
114
|
+
ctx.ui.notify(`Invalid mode: "${value}". Use "basic", "max", or "off".`, "error");
|
|
110
115
|
return;
|
|
111
116
|
}
|
|
112
117
|
const lines = [branding];
|
|
@@ -114,6 +119,7 @@ function security_temp_default(pi) {
|
|
|
114
119
|
lines.push(info("/security mode \u2014 show current security mode"));
|
|
115
120
|
lines.push(info("/security mode basic \u2014 relax to basic mode"));
|
|
116
121
|
lines.push(info("/security mode max \u2014 switch to max lockdown"));
|
|
122
|
+
lines.push(info("/security mode off \u2014 disable all security checks"));
|
|
117
123
|
lines.push(info("/security-audit \u2014 show security audit report"));
|
|
118
124
|
lines.push(branding);
|
|
119
125
|
pi.sendMessage({
|
|
@@ -138,7 +144,8 @@ function security_temp_default(pi) {
|
|
|
138
144
|
if (sub === "mode" && args.length === 2) {
|
|
139
145
|
return [
|
|
140
146
|
{ value: "basic", label: "basic", description: "Relax to basic mode \u2014 only critical commands blocked" },
|
|
141
|
-
{ value: "max", label: "max", description: "Full lockdown \u2014 all commands blocked (default)" }
|
|
147
|
+
{ value: "max", label: "max", description: "Full lockdown \u2014 all commands blocked (default)" },
|
|
148
|
+
{ value: "off", label: "off", description: "Disable all security checks" }
|
|
142
149
|
];
|
|
143
150
|
}
|
|
144
151
|
return [];
|
|
@@ -149,11 +156,12 @@ function security_temp_default(pi) {
|
|
|
149
156
|
const input = event.input ?? {};
|
|
150
157
|
const toolCallId = event.toolCallId;
|
|
151
158
|
let result;
|
|
159
|
+
const currentMode = getSecurityMode();
|
|
152
160
|
switch (toolName) {
|
|
153
161
|
case "bash":
|
|
154
162
|
case "shell":
|
|
155
163
|
case "run_command":
|
|
156
|
-
result = checkBashToolInput(input);
|
|
164
|
+
result = checkBashToolInput(input, currentMode);
|
|
157
165
|
break;
|
|
158
166
|
case "read":
|
|
159
167
|
case "read_file":
|
|
@@ -163,17 +171,17 @@ function security_temp_default(pi) {
|
|
|
163
171
|
case "edit_file":
|
|
164
172
|
case "list_directory":
|
|
165
173
|
case "list_dir":
|
|
166
|
-
result = checkFileToolInput(input);
|
|
174
|
+
result = checkFileToolInput(input, currentMode);
|
|
167
175
|
break;
|
|
168
176
|
case "http_get":
|
|
169
177
|
case "http_post":
|
|
170
178
|
case "fetch":
|
|
171
179
|
case "web_search":
|
|
172
180
|
case "http_request":
|
|
173
|
-
result = checkHttpToolInput(input);
|
|
181
|
+
result = checkHttpToolInput(input, currentMode);
|
|
174
182
|
break;
|
|
175
183
|
default:
|
|
176
|
-
result = checkInjectionPatterns(input);
|
|
184
|
+
result = checkInjectionPatterns(input, currentMode);
|
|
177
185
|
break;
|
|
178
186
|
}
|
|
179
187
|
if (!result.safe) {
|