mindweave 3.0.1 → 3.2.0
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 +36 -4
- package/dist/alternator/chassis/lsp.js +36 -4
- package/dist/alternator/chassis/lsp.js.map +1 -1
- package/dist/alternator/chassis/provision.js +54 -6
- package/dist/alternator/chassis/provision.js.map +1 -1
- package/dist/alternator/chassis/servers.js +34 -21
- package/dist/alternator/chassis/servers.js.map +1 -1
- package/dist/cli/App.js +118 -16
- package/dist/cli/App.js.map +1 -1
- package/dist/cli/attachments.js +37 -1
- package/dist/cli/attachments.js.map +1 -1
- package/dist/cli/bootstrap.js +25 -3
- package/dist/cli/bootstrap.js.map +1 -1
- package/dist/cli/components/BlockView.js +5 -5
- package/dist/cli/components/BlockView.js.map +1 -1
- package/dist/cli/components/CommandGroup.js +100 -0
- package/dist/cli/components/CommandGroup.js.map +1 -0
- package/dist/cli/components/MarathonBox.js +2 -1
- package/dist/cli/components/MarathonBox.js.map +1 -1
- package/dist/cli/components/TipLine.js +1 -0
- package/dist/cli/components/TipLine.js.map +1 -1
- package/dist/cli/components/ToolLine.js +69 -14
- package/dist/cli/components/ToolLine.js.map +1 -1
- package/dist/cli/components/WorkGroup.js +115 -0
- package/dist/cli/components/WorkGroup.js.map +1 -0
- package/dist/cli/diffWrap.js +24 -0
- package/dist/cli/diffWrap.js.map +1 -0
- package/dist/cli/expandHits.js +74 -0
- package/dist/cli/expandHits.js.map +1 -0
- package/dist/cli/marathonUi.js +2 -0
- package/dist/cli/marathonUi.js.map +1 -1
- package/dist/cli/mouse.js +16 -8
- package/dist/cli/mouse.js.map +1 -1
- package/dist/cli/scrollGlide.js +72 -0
- package/dist/cli/scrollGlide.js.map +1 -0
- package/dist/cli/scrollPill.js +21 -1
- package/dist/cli/scrollPill.js.map +1 -1
- package/dist/cli/selfUpdate.js +7 -0
- package/dist/cli/selfUpdate.js.map +1 -1
- package/dist/cli/terminalRestore.js +1 -1
- package/dist/cli/terminalRestore.js.map +1 -1
- package/dist/cli/toolDisplay.js +14 -10
- package/dist/cli/toolDisplay.js.map +1 -1
- package/dist/cli/transcript.js +100 -29
- package/dist/cli/transcript.js.map +1 -1
- package/dist/cli/uiLines.js +60 -0
- package/dist/cli/uiLines.js.map +1 -0
- package/dist/cli/wheelStep.js +29 -0
- package/dist/cli/wheelStep.js.map +1 -0
- package/dist/cli/workLines.js +84 -0
- package/dist/cli/workLines.js.map +1 -0
- package/dist/core/permissions.js +26 -1
- package/dist/core/permissions.js.map +1 -1
- package/dist/core/spendView.js +8 -1
- package/dist/core/spendView.js.map +1 -1
- package/dist/core/turnRunner.js +36 -8
- package/dist/core/turnRunner.js.map +1 -1
- package/dist/drivers/deepseek/inlineTools.js +36 -2
- package/dist/drivers/deepseek/inlineTools.js.map +1 -1
- package/dist/drivers/ollama/endpoint.js +25 -0
- package/dist/drivers/ollama/endpoint.js.map +1 -1
- package/dist/dynamo/engine.js +414 -88
- package/dist/dynamo/engine.js.map +1 -1
- package/dist/dynamo/guard.js +11 -4
- package/dist/dynamo/guard.js.map +1 -1
- package/dist/dynamo/hooks.js +209 -0
- package/dist/dynamo/hooks.js.map +1 -0
- package/dist/dynamo/marathon.js +67 -10
- package/dist/dynamo/marathon.js.map +1 -1
- package/dist/dynamo/todoReminder.js +26 -0
- package/dist/dynamo/todoReminder.js.map +1 -0
- package/dist/governor/forbidden.js +19 -0
- package/dist/governor/forbidden.js.map +1 -1
- package/dist/governor/freshness.js +1 -1
- package/dist/governor/freshness.js.map +1 -1
- package/dist/governor/index.js +8 -1
- package/dist/governor/index.js.map +1 -1
- package/dist/governor/rules.js +1 -0
- package/dist/governor/rules.js.map +1 -1
- package/dist/governor/write.js +50 -2
- package/dist/governor/write.js.map +1 -1
- package/dist/mcp/config.js +0 -41
- package/dist/mcp/config.js.map +1 -1
- package/dist/mcp/projectApproval.js +117 -0
- package/dist/mcp/projectApproval.js.map +1 -0
- package/dist/mcp/resultStore.js +19 -5
- package/dist/mcp/resultStore.js.map +1 -1
- package/dist/mcp/transport/stdio.js +4 -1
- package/dist/mcp/transport/stdio.js.map +1 -1
- package/dist/memory/allMetas.js +1 -1
- package/dist/memory/allMetas.js.map +1 -1
- package/dist/memory/autoMemory.js +1 -0
- package/dist/memory/autoMemory.js.map +1 -1
- package/dist/memory/clearedArchive.js +120 -0
- package/dist/memory/clearedArchive.js.map +1 -0
- package/dist/memory/compaction.js +178 -15
- package/dist/memory/compaction.js.map +1 -1
- package/dist/memory/counters.js +64 -0
- package/dist/memory/counters.js.map +1 -0
- package/dist/memory/projectNotes.js +61 -13
- package/dist/memory/projectNotes.js.map +1 -1
- package/dist/memory/rewind.js +6 -2
- package/dist/memory/rewind.js.map +1 -1
- package/dist/memory/session.js +13 -5
- package/dist/memory/session.js.map +1 -1
- package/dist/memory/sessionMemory.js +6 -2
- package/dist/memory/sessionMemory.js.map +1 -1
- package/dist/memory/store.js +3 -0
- package/dist/memory/store.js.map +1 -1
- package/dist/memory/types.js.map +1 -1
- package/dist/memory/workingSet.js +0 -375
- package/dist/memory/workingSet.js.map +1 -1
- package/dist/project/context.js +54 -7
- package/dist/project/context.js.map +1 -1
- package/dist/tools/approval.js +19 -4
- package/dist/tools/approval.js.map +1 -1
- package/dist/tools/backgroundShells.js +8 -1
- package/dist/tools/backgroundShells.js.map +1 -1
- package/dist/tools/browser.js +2 -1
- package/dist/tools/browser.js.map +1 -1
- package/dist/tools/checkpoints.js +28 -4
- package/dist/tools/checkpoints.js.map +1 -1
- package/dist/tools/childEnv.js +50 -0
- package/dist/tools/childEnv.js.map +1 -0
- package/dist/tools/codeIntel.js +4 -1
- package/dist/tools/codeIntel.js.map +1 -1
- package/dist/tools/commandParse.js +238 -0
- package/dist/tools/commandParse.js.map +1 -0
- package/dist/tools/commandPolicy.js +283 -0
- package/dist/tools/commandPolicy.js.map +1 -0
- package/dist/tools/detail.js +113 -1
- package/dist/tools/detail.js.map +1 -1
- package/dist/tools/edit.js +2 -1
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/editRipple.js +18 -3
- package/dist/tools/editRipple.js.map +1 -1
- package/dist/tools/editTarget.js +11 -6
- package/dist/tools/editTarget.js.map +1 -1
- package/dist/tools/governorTools.js +61 -1
- package/dist/tools/governorTools.js.map +1 -1
- package/dist/tools/grep.js +13 -5
- package/dist/tools/grep.js.map +1 -1
- package/dist/tools/guard.js +249 -2
- package/dist/tools/guard.js.map +1 -1
- package/dist/tools/invisible.js +62 -0
- package/dist/tools/invisible.js.map +1 -0
- package/dist/tools/killTree.js +3 -0
- package/dist/tools/killTree.js.map +1 -1
- package/dist/tools/readFile.js +11 -3
- package/dist/tools/readFile.js.map +1 -1
- package/dist/tools/readSymbol.js +5 -24
- package/dist/tools/readSymbol.js.map +1 -1
- package/dist/tools/rebuildDetail.js +155 -0
- package/dist/tools/rebuildDetail.js.map +1 -0
- package/dist/tools/replaceSymbol.js +1 -1
- package/dist/tools/replaceSymbol.js.map +1 -1
- package/dist/tools/ripgrepShell.js +56 -0
- package/dist/tools/ripgrepShell.js.map +1 -0
- package/dist/tools/runCommand.js +77 -18
- package/dist/tools/runCommand.js.map +1 -1
- package/dist/tools/runsLater.js +50 -0
- package/dist/tools/runsLater.js.map +1 -0
- package/dist/tools/serverConsent.js +27 -0
- package/dist/tools/serverConsent.js.map +1 -0
- package/dist/tools/ui.js +81 -1
- package/dist/tools/ui.js.map +1 -1
- package/dist/tools/untrusted.js +22 -1
- package/dist/tools/untrusted.js.map +1 -1
- package/dist/tools/viewImage.js +2 -2
- package/dist/tools/viewImage.js.map +1 -1
- package/dist/tools/webFetch.js +76 -8
- package/dist/tools/webFetch.js.map +1 -1
- package/dist/tools/workspace.js +87 -24
- package/dist/tools/workspace.js.map +1 -1
- package/dist/tools/writeFile.js +9 -4
- package/dist/tools/writeFile.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* commandParse.ts — read a shell command into the commands it contains (pure).
|
|
3
|
+
*
|
|
4
|
+
* The command guard used to be regular expressions over the raw text, which cannot tell
|
|
5
|
+
* `cat .env` from `echo ".env"`, misses the second command in `a; b`, and has no idea
|
|
6
|
+
* what a command names as its arguments. This reads the text the way a shell would, far
|
|
7
|
+
* enough to answer three questions: which commands run, what words each was given, and
|
|
8
|
+
* whether it writes a file.
|
|
9
|
+
*
|
|
10
|
+
* It is NOT a shell. It does not expand variables, run substitutions or follow
|
|
11
|
+
* redirections into anything clever; whatever it cannot read with certainty it says so
|
|
12
|
+
* (`unreadable`), and every caller treats that as "ask", never as "allow". That one rule
|
|
13
|
+
* is what lets this stay small: a construct it does not model is not a hole, it is a
|
|
14
|
+
* question for the person.
|
|
15
|
+
*
|
|
16
|
+
* Three dialects, because Windows runs PowerShell or cmd and everything else runs a
|
|
17
|
+
* POSIX shell: they differ in what is an escape (backslash in POSIX, backtick in
|
|
18
|
+
* PowerShell, a caret in cmd) and a backslash in a Windows path is not an escape at all.
|
|
19
|
+
*/
|
|
20
|
+
const NULL_TARGETS = new Set(["/dev/null", "$null", "nul", "NUL", "Nul"]);
|
|
21
|
+
/** Split `command` into simple commands. Never throws. */
|
|
22
|
+
export function parseCommand(command, dialect = process.platform === "win32" ? "powershell" : "posix") {
|
|
23
|
+
const commands = [];
|
|
24
|
+
let unreadable = null;
|
|
25
|
+
const fail = (why) => {
|
|
26
|
+
unreadable ??= why;
|
|
27
|
+
};
|
|
28
|
+
let words = [];
|
|
29
|
+
let writes = [];
|
|
30
|
+
let reads = [];
|
|
31
|
+
let expands = false;
|
|
32
|
+
let cur = "";
|
|
33
|
+
let inWord = false;
|
|
34
|
+
/** A redirect operator waiting for its target word. */
|
|
35
|
+
let pending = null;
|
|
36
|
+
const endWord = () => {
|
|
37
|
+
if (!inWord)
|
|
38
|
+
return;
|
|
39
|
+
inWord = false;
|
|
40
|
+
const word = cur;
|
|
41
|
+
cur = "";
|
|
42
|
+
if (pending) {
|
|
43
|
+
if (pending === ">" && !NULL_TARGETS.has(word))
|
|
44
|
+
writes.push(word);
|
|
45
|
+
if (pending === "<")
|
|
46
|
+
reads.push(word);
|
|
47
|
+
pending = null;
|
|
48
|
+
}
|
|
49
|
+
else
|
|
50
|
+
words.push(word);
|
|
51
|
+
};
|
|
52
|
+
const endCommand = () => {
|
|
53
|
+
endWord();
|
|
54
|
+
pending = null;
|
|
55
|
+
if (words.length > 0 || writes.length > 0 || reads.length > 0)
|
|
56
|
+
commands.push({ words, writes, reads, expands });
|
|
57
|
+
words = [];
|
|
58
|
+
writes = [];
|
|
59
|
+
reads = [];
|
|
60
|
+
expands = false;
|
|
61
|
+
};
|
|
62
|
+
const n = command.length;
|
|
63
|
+
for (let i = 0; i < n; i++) {
|
|
64
|
+
const c = command[i];
|
|
65
|
+
const next = command[i + 1];
|
|
66
|
+
// ── quotes ──
|
|
67
|
+
if (c === "'") {
|
|
68
|
+
inWord = true;
|
|
69
|
+
let end = command.indexOf("'", i + 1);
|
|
70
|
+
// In PowerShell a doubled quote inside single quotes is one literal quote: 'it''s'.
|
|
71
|
+
while (dialect === "powershell" && end >= 0 && command[end + 1] === "'") {
|
|
72
|
+
cur += command.slice(i + 1, end) + "'";
|
|
73
|
+
i = end + 1;
|
|
74
|
+
end = command.indexOf("'", i + 1);
|
|
75
|
+
}
|
|
76
|
+
if (end < 0) {
|
|
77
|
+
fail("an unclosed quote");
|
|
78
|
+
cur += command.slice(i + 1);
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
cur += command.slice(i + 1, end);
|
|
82
|
+
i = end;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (c === '"') {
|
|
86
|
+
inWord = true;
|
|
87
|
+
let j = i + 1;
|
|
88
|
+
for (; j < n && command[j] !== '"'; j++) {
|
|
89
|
+
const d = command[j];
|
|
90
|
+
if (d === "$") {
|
|
91
|
+
expands = true;
|
|
92
|
+
if (command[j + 1] === "(")
|
|
93
|
+
fail("a command substitution inside quotes");
|
|
94
|
+
}
|
|
95
|
+
if (d === "`" && dialect !== "cmd")
|
|
96
|
+
fail("a backtick inside quotes");
|
|
97
|
+
// An escaped character inside double quotes.
|
|
98
|
+
if ((dialect === "posix" && d === "\\" && j + 1 < n) || (dialect === "powershell" && d === "`" && j + 1 < n)) {
|
|
99
|
+
cur += command[j + 1];
|
|
100
|
+
j++;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
cur += d;
|
|
104
|
+
}
|
|
105
|
+
if (j >= n)
|
|
106
|
+
fail("an unclosed quote");
|
|
107
|
+
i = j;
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
// ── escapes ──
|
|
111
|
+
if (dialect === "posix" && c === "\\") {
|
|
112
|
+
if (next === "\n") {
|
|
113
|
+
i++;
|
|
114
|
+
continue; // a line continuation
|
|
115
|
+
}
|
|
116
|
+
inWord = true;
|
|
117
|
+
if (next !== undefined)
|
|
118
|
+
cur += next;
|
|
119
|
+
i++;
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (dialect === "powershell" && c === "`") {
|
|
123
|
+
fail("a backtick");
|
|
124
|
+
inWord = true;
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
if (dialect === "cmd" && c === "^") {
|
|
128
|
+
fail("a caret escape");
|
|
129
|
+
inWord = true;
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
// ── separators ──
|
|
133
|
+
if (c === "\n" || c === "\r" || c === ";") {
|
|
134
|
+
endCommand();
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
if (c === "&") {
|
|
138
|
+
if (next === "&")
|
|
139
|
+
i++;
|
|
140
|
+
else if (next === ">")
|
|
141
|
+
fail("a combined redirect");
|
|
142
|
+
else if (words.length === 0 && !inWord)
|
|
143
|
+
fail("the call operator");
|
|
144
|
+
endCommand();
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (c === "|") {
|
|
148
|
+
if (next === "|" || next === "&")
|
|
149
|
+
i++;
|
|
150
|
+
endCommand();
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
// ── redirects ──
|
|
154
|
+
if (c === ">" || c === "<") {
|
|
155
|
+
// A file-descriptor duplicate (2>&1, >&2) writes to no file.
|
|
156
|
+
if (c === ">" && next === "&") {
|
|
157
|
+
i++;
|
|
158
|
+
while (command[i + 1] !== undefined && /[0-9-]/.test(command[i + 1]))
|
|
159
|
+
i++;
|
|
160
|
+
// The number before it was read as a word; it is not an argument.
|
|
161
|
+
if (inWord && /^[0-9]$/.test(cur)) {
|
|
162
|
+
cur = "";
|
|
163
|
+
inWord = false;
|
|
164
|
+
}
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (c === "<" && (next === "<" || next === "(")) {
|
|
168
|
+
fail(next === "<" ? "a here-document" : "a process substitution");
|
|
169
|
+
endCommand();
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
// `2>` and `1>`: the digit is the stream, not a word.
|
|
173
|
+
if (inWord && /^[0-9]$/.test(cur)) {
|
|
174
|
+
cur = "";
|
|
175
|
+
inWord = false;
|
|
176
|
+
}
|
|
177
|
+
else
|
|
178
|
+
endWord();
|
|
179
|
+
if (c === ">" && next === ">")
|
|
180
|
+
i++;
|
|
181
|
+
if (c === ">" && next === "(")
|
|
182
|
+
fail("a process substitution");
|
|
183
|
+
pending = c;
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
// ── whitespace ──
|
|
187
|
+
if (c === " " || c === "\t") {
|
|
188
|
+
endWord();
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
// ── things this reader does not model ──
|
|
192
|
+
if (c === "$") {
|
|
193
|
+
if (next === "(")
|
|
194
|
+
fail("a command substitution");
|
|
195
|
+
expands = true;
|
|
196
|
+
}
|
|
197
|
+
if (c === "`" && dialect === "posix")
|
|
198
|
+
fail("a command substitution");
|
|
199
|
+
if (c === "{" || c === "}") {
|
|
200
|
+
// A script block, a brace expansion or a group. `{}` alone is find's placeholder.
|
|
201
|
+
if (!(c === "{" && next === "}") && !(c === "}" && command[i - 1] === "{"))
|
|
202
|
+
fail("a block or brace expansion");
|
|
203
|
+
}
|
|
204
|
+
if (c === "(" || c === ")")
|
|
205
|
+
fail("a group or expression");
|
|
206
|
+
if (c === "@" && (next === "'" || next === '"') && !inWord)
|
|
207
|
+
fail("a here-string");
|
|
208
|
+
if (c === "%" && dialect !== "cmd" && !inWord && next === "{")
|
|
209
|
+
fail("a script block");
|
|
210
|
+
inWord = true;
|
|
211
|
+
cur += c;
|
|
212
|
+
}
|
|
213
|
+
endCommand();
|
|
214
|
+
// What a command may start with that changes what runs.
|
|
215
|
+
for (const cmd of commands) {
|
|
216
|
+
const first = cmd.words[0];
|
|
217
|
+
if (first === undefined)
|
|
218
|
+
continue;
|
|
219
|
+
if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(first))
|
|
220
|
+
fail("an environment variable set before the command");
|
|
221
|
+
if (first.startsWith("$"))
|
|
222
|
+
fail("a variable used as the command");
|
|
223
|
+
if (/^(eval|exec|source|\.|iex|invoke-expression|invoke-command|icm|start-process|saps|start|call)$/i.test(first)) {
|
|
224
|
+
fail(`${first}, which runs other text as code`);
|
|
225
|
+
}
|
|
226
|
+
if (cmd.words.some((w) => /^-e(nc(odedcommand)?)?$/i.test(w) || /^-command$/i.test(w) || /^-c$/.test(w) && /^(bash|sh|zsh|dash)$/.test(first))) {
|
|
227
|
+
fail("a program told to run a string as code");
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return { commands, unreadable };
|
|
231
|
+
}
|
|
232
|
+
/** The program or cmdlet a command runs, lower-cased, without a directory or a .exe. */
|
|
233
|
+
export function verbOf(cmd) {
|
|
234
|
+
const first = cmd.words[0] ?? "";
|
|
235
|
+
const base = first.split(/[\\/]/).pop() ?? first;
|
|
236
|
+
return base.replace(/\.(exe|cmd|bat|com|ps1)$/i, "").toLowerCase();
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=commandParse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commandParse.js","sourceRoot":"","sources":["../../src/tools/commandParse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* commandPolicy.ts — decisions about a shell command, made from the commands it contains.
|
|
3
|
+
*
|
|
4
|
+
* Built on commandParse.ts. Three things, each of which regular expressions over the raw
|
|
5
|
+
* text could not do:
|
|
6
|
+
*
|
|
7
|
+
* 1. Which commands are plainly harmless, so Sentinel mode does not ask about them.
|
|
8
|
+
* Every run_command was a question, which teaches people to answer "yes" without
|
|
9
|
+
* reading. A command is waved through only when EVERY part of it is a known
|
|
10
|
+
* read-only command with arguments that cannot write or run anything, nothing in it
|
|
11
|
+
* is expanded or unreadable, and it writes no file. Anything else keeps its question.
|
|
12
|
+
* 2. The user's own rules by command prefix: allow, prompt or forbid, with a reason the
|
|
13
|
+
* model is shown ("use X instead").
|
|
14
|
+
* 3. Which protected file a command NAMES, whatever it does with it. The old check only
|
|
15
|
+
* knew the verbs `cat` and `type`, so `cp .env notes.txt` followed by reading the copy,
|
|
16
|
+
* or `curl -F f=@key.pem`, got a secret out. Naming a protected path as something to
|
|
17
|
+
* read, copy out or send is refused; naming it as a destination, or as the target of
|
|
18
|
+
* a listing or a deletion, is not.
|
|
19
|
+
*/
|
|
20
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
21
|
+
import { homedir } from "node:os";
|
|
22
|
+
import { isAbsolute, join, resolve } from "node:path";
|
|
23
|
+
import { parseCommand, verbOf } from "./commandParse.js";
|
|
24
|
+
import { expandHomeWords, guardedPathReason, protectedPathReason } from "./guard.js";
|
|
25
|
+
/** Parse command-rules.md (pure). Lines starting with # and malformed lines are ignored. */
|
|
26
|
+
export function parseCommandRules(text) {
|
|
27
|
+
const rules = [];
|
|
28
|
+
for (const raw of text.split(/\r?\n/)) {
|
|
29
|
+
const line = raw.trim();
|
|
30
|
+
if (!line || line.startsWith("#"))
|
|
31
|
+
continue;
|
|
32
|
+
const [head, ...why] = line.split("::");
|
|
33
|
+
const parts = head.trim().split(/\s+/);
|
|
34
|
+
const decision = parts.shift()?.toLowerCase();
|
|
35
|
+
const alias = decision === "forbidden" ? "forbid" : decision === "ask" ? "prompt" : decision;
|
|
36
|
+
if (alias !== "allow" && alias !== "prompt" && alias !== "forbid")
|
|
37
|
+
continue;
|
|
38
|
+
if (parts.length === 0)
|
|
39
|
+
continue;
|
|
40
|
+
const justification = why.join("::").trim();
|
|
41
|
+
rules.push({ decision: alias, words: parts, ...(justification ? { justification } : {}) });
|
|
42
|
+
}
|
|
43
|
+
return rules;
|
|
44
|
+
}
|
|
45
|
+
const same = (a, b) => a.toLowerCase() === b.toLowerCase();
|
|
46
|
+
/** Does `rule` apply to `cmd`? The program must match, and then the next words in order. */
|
|
47
|
+
export function ruleMatches(rule, cmd) {
|
|
48
|
+
if (rule.words.length === 0 || cmd.words.length < rule.words.length)
|
|
49
|
+
return false;
|
|
50
|
+
if (!same(verbOf({ ...cmd, words: [rule.words[0]] }), verbOf(cmd)))
|
|
51
|
+
return false;
|
|
52
|
+
return rule.words.slice(1).every((w, i) => same(w, cmd.words[i + 1] ?? ""));
|
|
53
|
+
}
|
|
54
|
+
export function ruleVerdict(parsed, rules) {
|
|
55
|
+
let forbid;
|
|
56
|
+
let prompt;
|
|
57
|
+
let allAllowed = parsed.commands.length > 0;
|
|
58
|
+
for (const cmd of parsed.commands) {
|
|
59
|
+
const hits = rules.filter((r) => ruleMatches(r, cmd));
|
|
60
|
+
forbid ??= hits.find((r) => r.decision === "forbid");
|
|
61
|
+
prompt ??= hits.find((r) => r.decision === "prompt");
|
|
62
|
+
// A prompt or forbid rule on the same command beats an allow.
|
|
63
|
+
if (!hits.some((r) => r.decision === "allow") || hits.some((r) => r.decision !== "allow"))
|
|
64
|
+
allAllowed = false;
|
|
65
|
+
}
|
|
66
|
+
return { ...(forbid ? { forbid } : {}), ...(prompt ? { prompt } : {}), allAllowed };
|
|
67
|
+
}
|
|
68
|
+
const anyArgs = () => true;
|
|
69
|
+
/** True when no argument is one of `bad` (also as `--flag=value`). */
|
|
70
|
+
const without = (...bad) => (args) => !args.some((a) => bad.some((b) => a.toLowerCase() === b || a.toLowerCase().startsWith(`${b}=`)));
|
|
71
|
+
/** At most `n` words that are not options: `uniq in out` would write `out`. */
|
|
72
|
+
const positionalsAtMost = (n) => (args) => args.filter((a) => !a.startsWith("-")).length <= n;
|
|
73
|
+
const READ_ONLY = {
|
|
74
|
+
// listing and printing
|
|
75
|
+
ls: anyArgs, dir: anyArgs, pwd: anyArgs, echo: anyArgs, printf: anyArgs, cat: anyArgs, type: anyArgs,
|
|
76
|
+
head: anyArgs, tail: anyArgs, wc: anyArgs, nl: anyArgs, cut: anyArgs, tr: anyArgs, stat: anyArgs, file: anyArgs,
|
|
77
|
+
du: anyArgs, df: anyArgs, tree: anyArgs, which: anyArgs, where: anyArgs, whoami: anyArgs, hostname: anyArgs,
|
|
78
|
+
uname: anyArgs, id: anyArgs, ps: anyArgs, basename: anyArgs, dirname: anyArgs, realpath: anyArgs, readlink: anyArgs,
|
|
79
|
+
cmp: anyArgs, diff: anyArgs, jq: anyArgs,
|
|
80
|
+
uniq: positionalsAtMost(1),
|
|
81
|
+
sort: without("-o", "--output"),
|
|
82
|
+
date: without("-s", "--set"),
|
|
83
|
+
grep: anyArgs, egrep: anyArgs, fgrep: anyArgs,
|
|
84
|
+
rg: without("--pre", "--hostname-bin"),
|
|
85
|
+
find: without("-exec", "-execdir", "-ok", "-okdir", "-delete", "-fprint", "-fprint0", "-fprintf", "-fls"),
|
|
86
|
+
// PowerShell
|
|
87
|
+
"get-childitem": noEnvDrive, gci: noEnvDrive,
|
|
88
|
+
"get-content": anyArgs, gc: anyArgs,
|
|
89
|
+
"get-location": anyArgs, gl: anyArgs,
|
|
90
|
+
"get-item": noEnvDrive, gi: noEnvDrive, "get-itemproperty": noEnvDrive, gp: noEnvDrive,
|
|
91
|
+
"test-path": anyArgs, "resolve-path": anyArgs, rvpa: anyArgs,
|
|
92
|
+
"select-string": anyArgs, sls: anyArgs,
|
|
93
|
+
"measure-object": anyArgs, measure: anyArgs, "select-object": anyArgs, select: anyArgs,
|
|
94
|
+
"sort-object": anyArgs, "group-object": anyArgs, group: anyArgs,
|
|
95
|
+
"format-list": anyArgs, fl: anyArgs, "format-table": anyArgs, ft: anyArgs, "out-string": anyArgs,
|
|
96
|
+
"get-process": anyArgs, gps: anyArgs, "get-service": anyArgs, "get-command": anyArgs, gcm: anyArgs,
|
|
97
|
+
"get-date": anyArgs, "get-help": anyArgs, "get-filehash": anyArgs,
|
|
98
|
+
"write-output": anyArgs, "write-host": anyArgs, write: anyArgs,
|
|
99
|
+
"split-path": anyArgs, "join-path": anyArgs, "compare-object": anyArgs,
|
|
100
|
+
"convertto-json": anyArgs, "convertfrom-json": anyArgs, "where-object": anyArgs,
|
|
101
|
+
};
|
|
102
|
+
/** `Get-ChildItem Env:` lists the environment. */
|
|
103
|
+
function noEnvDrive(args) {
|
|
104
|
+
return !args.some((a) => /^(env|variable|function|alias):?/i.test(a.replace(/^-(path|literalpath)[:=]?/i, "")));
|
|
105
|
+
}
|
|
106
|
+
/** git subcommands that only read, with the options each must not be given. */
|
|
107
|
+
const GIT_READ_ONLY = {
|
|
108
|
+
status: anyArgs, log: anyArgs, diff: anyArgs, show: anyArgs, "ls-files": anyArgs, "ls-tree": anyArgs,
|
|
109
|
+
"rev-parse": anyArgs, "rev-list": anyArgs, describe: anyArgs, blame: anyArgs, shortlog: anyArgs,
|
|
110
|
+
"cat-file": anyArgs, grep: anyArgs, "name-rev": anyArgs, "merge-base": anyArgs, "diff-tree": anyArgs,
|
|
111
|
+
"show-ref": anyArgs, "check-ignore": anyArgs, "count-objects": anyArgs, whatchanged: anyArgs,
|
|
112
|
+
reflog: (args) => !args.some((a) => /^(expire|delete)$/.test(a)),
|
|
113
|
+
remote: (args) => args.length === 0 || args.every((a) => a === "-v" || a === "--verbose") || /^(show|get-url)$/.test(args[0] ?? ""),
|
|
114
|
+
branch: (args) => args.every((a) => /^(-a|-r|-v|-vv|--all|--remotes|--list|--show-current|--verbose|--merged|--no-merged|--contains)$/.test(a)),
|
|
115
|
+
tag: (args) => args.every((a) => /^(-l|--list|-n\d*|--sort=.*)$/.test(a)),
|
|
116
|
+
stash: (args) => /^(list|show)$/.test(args[0] ?? ""),
|
|
117
|
+
worktree: (args) => args[0] === "list",
|
|
118
|
+
};
|
|
119
|
+
/** Options that make an otherwise read-only git command write or run a program. */
|
|
120
|
+
const GIT_BAD_OPTIONS = ["--output", "--ext-diff", "--textconv", "--exec", "--upload-pack", "--receive-pack", "--open-files-in-pager"];
|
|
121
|
+
function gitReadOnly(cmd, gitConfigSafe) {
|
|
122
|
+
if (!gitConfigSafe)
|
|
123
|
+
return false;
|
|
124
|
+
const [, sub, ...args] = cmd.words;
|
|
125
|
+
if (sub === "--version" || sub === "version")
|
|
126
|
+
return args.length === 0;
|
|
127
|
+
const check = sub ? GIT_READ_ONLY[sub] : undefined;
|
|
128
|
+
return !!check && without(...GIT_BAD_OPTIONS)(args) && check(args);
|
|
129
|
+
}
|
|
130
|
+
/** Is this one command a known read-only command, given what it is passed? */
|
|
131
|
+
export function isReadOnly(cmd, gitConfigSafe) {
|
|
132
|
+
if (cmd.writes.length > 0 || cmd.expands || cmd.words.length === 0)
|
|
133
|
+
return false;
|
|
134
|
+
const verb = verbOf(cmd);
|
|
135
|
+
if (verb === "git")
|
|
136
|
+
return gitReadOnly(cmd, gitConfigSafe);
|
|
137
|
+
const check = READ_ONLY[verb];
|
|
138
|
+
return !!check && check(cmd.words.slice(1));
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Whether git in `cwd` would run a program from the repository's own config just to answer a
|
|
142
|
+
* read-only question (fsmonitor, a pager, an external diff or textconv, a filter). A repo that
|
|
143
|
+
* arrived with such a config makes even `git status` a way to run code, so its git commands keep
|
|
144
|
+
* their question. True when it cannot be told: a worktree file, an unreadable config.
|
|
145
|
+
*/
|
|
146
|
+
export function gitConfigRunsPrograms(cwd) {
|
|
147
|
+
const dotGit = join(cwd, ".git");
|
|
148
|
+
if (!existsSync(dotGit))
|
|
149
|
+
return false; // not a repository: git reads only the user's own config
|
|
150
|
+
try {
|
|
151
|
+
const text = readFileSync(join(dotGit, "config"), "utf8");
|
|
152
|
+
return /^\s*(fsmonitor|pager|sshcommand|editor|askpass|external|textconv|command|clean|smudge|process|program|hookspath|path)\s*=|^\s*\[(include|includeIf)\b/im.test(text);
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Sentinel's question can be skipped: every part of the command is read-only or allowed by
|
|
160
|
+
* a user rule, and nothing in it is unreadable. Never true for a command this reader cannot
|
|
161
|
+
* fully read.
|
|
162
|
+
*/
|
|
163
|
+
export function needsNoQuestion(parsed, rules, cwd) {
|
|
164
|
+
if (parsed.unreadable || parsed.commands.length === 0)
|
|
165
|
+
return false;
|
|
166
|
+
const verdict = ruleVerdict(parsed, rules);
|
|
167
|
+
if (verdict.forbid || verdict.prompt)
|
|
168
|
+
return false;
|
|
169
|
+
const gitSafe = !gitConfigRunsPrograms(cwd);
|
|
170
|
+
return parsed.commands.every((cmd) => isReadOnly(cmd, gitSafe) || (cmd.writes.length === 0 && rules.some((r) => r.decision === "allow" && ruleMatches(r, cmd))));
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Programs that run whatever they are handed next: an interpreter, a shell, a launcher, a downloader. A rule on
|
|
174
|
+
* one of these ("allow node") would approve every command that begins with it, so no prefix is ever suggested.
|
|
175
|
+
*/
|
|
176
|
+
const TOO_BROAD = new Set([
|
|
177
|
+
"node", "nodejs", "deno", "bun", "python", "python3", "py", "ruby", "perl", "php", "lua", "java", "dotnet",
|
|
178
|
+
"bash", "sh", "zsh", "fish", "dash", "pwsh", "powershell", "cmd", "npx", "pnpx", "bunx", "uvx", "pipx", "sudo", "doas",
|
|
179
|
+
"env", "xargs", "nohup", "time", "timeout", "start", "ssh", "scp", "sftp", "curl", "wget", "iwr", "irm", "nc", "ncat",
|
|
180
|
+
"rm", "rmdir", "rd", "del", "erase", "remove-item", "ri", "mv", "move", "cp", "copy", "dd", "format", "chmod", "chown",
|
|
181
|
+
"kill", "taskkill", "pkill", "make", "gmake", "find", "awk", "sed",
|
|
182
|
+
]);
|
|
183
|
+
/** Tools whose first word is a program and whose second is the action: the prefix takes both. */
|
|
184
|
+
const TWO_WORD = new Set([
|
|
185
|
+
"git", "npm", "pnpm", "yarn", "cargo", "go", "docker", "podman", "kubectl", "gh", "pip", "pip3", "uv", "poetry",
|
|
186
|
+
"composer", "gradle", "mvn", "terraform", "helm", "rustup", "brew", "apt", "apt-get", "winget", "choco", "flutter", "swift",
|
|
187
|
+
]);
|
|
188
|
+
/**
|
|
189
|
+
* The prefix a "don't ask again" answer would save for this command, or null when none is safe to offer.
|
|
190
|
+
*
|
|
191
|
+
* Only a single, fully readable command that writes no file qualifies. `npm test` becomes `npm test`; a bare
|
|
192
|
+
* `cargo build --release` becomes `cargo build`. A shell, interpreter or launcher, and a command that is itself
|
|
193
|
+
* one of the risky ones, get nothing: the person can still answer yes for this one command.
|
|
194
|
+
*/
|
|
195
|
+
export function suggestAllowPrefix(parsed) {
|
|
196
|
+
if (parsed.unreadable || parsed.commands.length !== 1)
|
|
197
|
+
return null;
|
|
198
|
+
const cmd = parsed.commands[0];
|
|
199
|
+
if (cmd.writes.length > 0 || cmd.expands)
|
|
200
|
+
return null;
|
|
201
|
+
const verb = verbOf(cmd);
|
|
202
|
+
if (!verb || TOO_BROAD.has(verb))
|
|
203
|
+
return null;
|
|
204
|
+
const second = cmd.words[1];
|
|
205
|
+
if (TWO_WORD.has(verb)) {
|
|
206
|
+
if (!second || second.startsWith("-") || /[\\/$%*?]/.test(second))
|
|
207
|
+
return null;
|
|
208
|
+
// `npm run build` is a script name, and `npm run` alone would allow every script in the file.
|
|
209
|
+
if (second.toLowerCase() === "run" || second.toLowerCase() === "exec" || second.toLowerCase() === "x") {
|
|
210
|
+
const third = cmd.words[2];
|
|
211
|
+
return third && !third.startsWith("-") && !/[\\/$%*?]/.test(third) ? `${verb} ${second} ${third}` : null;
|
|
212
|
+
}
|
|
213
|
+
return `${verb} ${second}`;
|
|
214
|
+
}
|
|
215
|
+
return verb;
|
|
216
|
+
}
|
|
217
|
+
// ── protected paths named in a command ──────────────────────────────────────
|
|
218
|
+
/** Verbs that do not read what they are pointed at: a listing, a deletion, a directory change. */
|
|
219
|
+
const NEVER_READS = new Set([
|
|
220
|
+
"ls", "dir", "get-childitem", "gci", "test-path", "mkdir", "md", "new-item", "ni", "touch", "rm", "del", "erase",
|
|
221
|
+
"remove-item", "ri", "rmdir", "rd", "echo", "write-output", "write-host", "write", "pwd", "cd", "chdir",
|
|
222
|
+
"set-location", "sl", "pushd", "popd", "stat", "file", "basename", "dirname",
|
|
223
|
+
]);
|
|
224
|
+
/** Verbs that copy or move: their LAST path is where it goes, which may be a protected file. */
|
|
225
|
+
const COPIES = new Set(["cp", "copy", "copy-item", "cpi", "mv", "move", "move-item", "mi", "ren", "rename", "rename-item", "rni"]);
|
|
226
|
+
/** The candidate paths inside one word: itself, the value of `--flag=value`, and `@file`. */
|
|
227
|
+
function pathCandidates(word) {
|
|
228
|
+
const out = new Set([word]);
|
|
229
|
+
const eq = word.indexOf("=");
|
|
230
|
+
if (eq > 0)
|
|
231
|
+
out.add(word.slice(eq + 1).replace(/^@/, ""));
|
|
232
|
+
if (word.startsWith("@"))
|
|
233
|
+
out.add(word.slice(1));
|
|
234
|
+
const at = word.lastIndexOf("@");
|
|
235
|
+
if (at > 0 && word[at + 1] !== undefined)
|
|
236
|
+
out.add(word.slice(at + 1));
|
|
237
|
+
return [...out].filter((c) => c.length > 0 && !/^[a-z][a-z0-9+.-]*:\/\//i.test(c));
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* The protected file this command names as something to read, copy out or send, as a reason
|
|
241
|
+
* ("`.env` is an environment/secrets file"), or null. Judges what the paths lead to (links
|
|
242
|
+
* and stream spellings resolved), not just the text.
|
|
243
|
+
*/
|
|
244
|
+
export async function protectedArgsReason(parsed, cwd) {
|
|
245
|
+
for (const cmd of parsed.commands) {
|
|
246
|
+
const verb = verbOf(cmd);
|
|
247
|
+
if (NEVER_READS.has(verb))
|
|
248
|
+
continue;
|
|
249
|
+
let args = cmd.words.slice(1).filter((w) => !(w.startsWith("-") && !w.includes("=")));
|
|
250
|
+
if (COPIES.has(verb) && args.length >= 2)
|
|
251
|
+
args = args.slice(0, -1);
|
|
252
|
+
const inputs = [...args, ...cmd.words.slice(1).filter((w) => w.startsWith("-") && w.includes("=")), ...cmd.reads];
|
|
253
|
+
for (const word of inputs) {
|
|
254
|
+
for (const candidate of pathCandidates(word)) {
|
|
255
|
+
const text = protectedPathReason(candidate.replace(/\\/g, "/"));
|
|
256
|
+
if (text)
|
|
257
|
+
return `\`${candidate}\` is ${text}`;
|
|
258
|
+
const abs = resolveWord(candidate, cwd);
|
|
259
|
+
if (!abs || !(/[\\/]/.test(candidate) || /^[.~]/.test(candidate) || existsSync(abs)))
|
|
260
|
+
continue;
|
|
261
|
+
const real = await guardedPathReason(abs);
|
|
262
|
+
if (real)
|
|
263
|
+
return `\`${candidate}\` is ${real}`;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
function resolveWord(word, cwd) {
|
|
270
|
+
const expanded = expandHomeWords(word.startsWith("~") ? word.replace(/^~/, homedir()) : word);
|
|
271
|
+
if (/[$%*?<>|"]/.test(expanded))
|
|
272
|
+
return null;
|
|
273
|
+
return isAbsolute(expanded) ? resolve(expanded) : resolve(cwd, expanded);
|
|
274
|
+
}
|
|
275
|
+
// ── the entry points the tools use ───────────────────────────────────────────
|
|
276
|
+
/** Which shell dialect a run_command call uses. */
|
|
277
|
+
export function dialectFor(args) {
|
|
278
|
+
if (process.platform !== "win32")
|
|
279
|
+
return "posix";
|
|
280
|
+
return args.shell === "cmd" ? "cmd" : "powershell";
|
|
281
|
+
}
|
|
282
|
+
export { parseCommand };
|
|
283
|
+
//# sourceMappingURL=commandPolicy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commandPolicy.js","sourceRoot":"","sources":["../../src/tools/commandPolicy.ts"],"names":[],"mappings":"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"}
|