@gaunt-sloth/agent 2.0.0-alpha.2 → 2.0.0-alpha.4

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.
Files changed (42) hide show
  1. package/README.md +9 -0
  2. package/dist/builtInToolsConfig.js +11 -2
  3. package/dist/builtInToolsConfig.js.map +1 -1
  4. package/dist/core/GthDeepAgent.d.ts +75 -0
  5. package/dist/core/GthDeepAgent.js +257 -21
  6. package/dist/core/GthDeepAgent.js.map +1 -1
  7. package/dist/core/deepAgentPermissions.d.ts +29 -11
  8. package/dist/core/deepAgentPermissions.js +67 -26
  9. package/dist/core/deepAgentPermissions.js.map +1 -1
  10. package/dist/mcp/OAuthClientProviderImpl.js +2 -2
  11. package/dist/mcp/OAuthClientProviderImpl.js.map +1 -1
  12. package/dist/middleware/registry.d.ts +1 -1
  13. package/dist/middleware/registry.js +1 -1
  14. package/dist/middleware/types.d.ts +1 -1
  15. package/dist/middleware/types.js +1 -1
  16. package/dist/modules/acpModule.d.ts +5 -2
  17. package/dist/modules/acpModule.js +5 -2
  18. package/dist/modules/acpModule.js.map +1 -1
  19. package/dist/modules/interactiveSessionModule.js +81 -4
  20. package/dist/modules/interactiveSessionModule.js.map +1 -1
  21. package/dist/tools/GthDevToolkit.d.ts +72 -1
  22. package/dist/tools/GthDevToolkit.js +230 -18
  23. package/dist/tools/GthDevToolkit.js.map +1 -1
  24. package/dist/tools/shell/allowlist.d.ts +11 -0
  25. package/dist/tools/shell/allowlist.js +12 -0
  26. package/dist/tools/shell/allowlist.js.map +1 -0
  27. package/dist/tools/shell/arity.d.ts +11 -0
  28. package/dist/tools/shell/arity.js +12 -0
  29. package/dist/tools/shell/arity.js.map +1 -0
  30. package/dist/tools/shell/env.d.ts +22 -0
  31. package/dist/tools/shell/env.js +110 -0
  32. package/dist/tools/shell/env.js.map +1 -0
  33. package/dist/tools/shell/hardline.d.ts +15 -0
  34. package/dist/tools/shell/hardline.js +88 -0
  35. package/dist/tools/shell/hardline.js.map +1 -0
  36. package/dist/tools/shell/normalize.d.ts +10 -0
  37. package/dist/tools/shell/normalize.js +11 -0
  38. package/dist/tools/shell/normalize.js.map +1 -0
  39. package/dist/tools/shell/outputBuffer.d.ts +53 -0
  40. package/dist/tools/shell/outputBuffer.js +157 -0
  41. package/dist/tools/shell/outputBuffer.js.map +1 -0
  42. package/package.json +8 -8
@@ -3,10 +3,109 @@
3
3
  */
4
4
  import { BaseToolkit, tool } from '@langchain/core/tools';
5
5
  import { z } from 'zod';
6
- import { spawn } from 'child_process';
6
+ import { spawn, spawnSync } from 'child_process';
7
7
  import path from 'node:path';
8
- import { displayInfo, displayError } from '@gaunt-sloth/core/utils/consoleUtils.js';
9
- import { stdout } from '@gaunt-sloth/core/utils/systemUtils.js';
8
+ import { displayInfo, displayError, displayWarning } from '@gaunt-sloth/core/utils/consoleUtils.js';
9
+ import { getShellMaxOutputBytes, getShellTimeoutMs, isShellToolEnabled, } from '@gaunt-sloth/core/config.js';
10
+ import { stdout, getCurrentWorkDir } from '@gaunt-sloth/core/utils/systemUtils.js';
11
+ import { checkHardline } from '#src/tools/shell/hardline.js';
12
+ import { buildScrubbedEnv } from '#src/tools/shell/env.js';
13
+ import { OutputBuffer } from '#src/tools/shell/outputBuffer.js';
14
+ // Grace period (ms) between SIGTERM and the escalation to SIGKILL when a command
15
+ // exceeds its timeout. Mirrors opencode's `forceKillAfter` (3s).
16
+ const KILL_GRACE_MS = 3_000;
17
+ /**
18
+ * EXT-20: a run_* command that did NOT exit cleanly (non-zero exit code, or was killed for
19
+ * exceeding the timeout). Carries the FULL model-facing body text ({@link output}) so the
20
+ * softening middleware ({@link GthDeepShellExitSoftening}) can hand the model the exact same
21
+ * observation it saw before — the only change is the tool result's status flips to `'error'`,
22
+ * which drives the ✗ (`isError`) glyph.
23
+ *
24
+ * `executeCommand` previously `resolve()`d on a non-zero exit, so the LangChain `ToolMessage`
25
+ * stayed `status: 'success'` and every failure rendered a ✓. Throwing this typed error instead
26
+ * lets the deep-agent middleware convert it into an error `ToolMessage`. A clean exit (`code === 0`)
27
+ * still `resolve()`s; a spawn-level `child.on('error')` still rejects with a plain `Error`.
28
+ */
29
+ export class ShellCommandFailedError extends Error {
30
+ /** The full model-facing body (command echo + `<COMMAND_OUTPUT>` + the failure/timeout tail). */
31
+ output;
32
+ /** The process exit code; `null` when the command was killed (timeout) and never exited cleanly. */
33
+ exitCode;
34
+ /** The exact command string that was executed. */
35
+ command;
36
+ /** The run_* tool name that invoked the command (e.g. `run_tests`, `run_shell_command`). */
37
+ toolName;
38
+ constructor(params) {
39
+ // Use the full body as the Error message so any generic logger/handler still surfaces the
40
+ // real command output rather than an opaque wrapper string.
41
+ super(params.output);
42
+ this.name = 'ShellCommandFailedError';
43
+ this.output = params.output;
44
+ this.exitCode = params.exitCode;
45
+ this.command = params.command;
46
+ this.toolName = params.toolName;
47
+ }
48
+ }
49
+ /**
50
+ * Kill the child AND its descendants on timeout.
51
+ *
52
+ * POSIX: the child is spawned `detached`, so it leads its own process group;
53
+ * signalling the NEGATIVE pid (`-pid`) delivers to the whole group — otherwise a
54
+ * shell's children (e.g. a spawned server) would be orphaned and keep running.
55
+ *
56
+ * Windows (EXT-15): there are no POSIX process groups — `process.kill(-pid)`
57
+ * throws `EINVAL`, and `child.kill()` only terminates the `cmd.exe` wrapper while
58
+ * grandchildren keep the piped stdio handles open, so `'close'` never fires and
59
+ * the tool Promise hangs forever (silently cancelling Windows CI). Use `taskkill
60
+ * /T` to kill the whole tree by pid; `/F` (force) mirrors POSIX SIGKILL, while a
61
+ * graceful taskkill mirrors SIGTERM. Swallows the races where it has already exited.
62
+ *
63
+ * Exported for unit testing the platform branch without a Windows host.
64
+ */
65
+ export function killProcessGroup(child, signal) {
66
+ if (typeof child.pid !== 'number')
67
+ return;
68
+ if (process.platform === 'win32') {
69
+ // No process groups on Windows; taskkill /T walks the whole tree by pid.
70
+ const args = ['/PID', String(child.pid), '/T'];
71
+ if (signal === 'SIGKILL')
72
+ args.push('/F');
73
+ // IMPORTANT: spawnSync does NOT throw when it fails to spawn (e.g. ENOENT if taskkill is
74
+ // missing from PATH) — unlike execSync, it returns an object with an `error` property. So a
75
+ // try/catch would never reach the fallback. Inspect `res.error` explicitly and fall back to
76
+ // the direct child kill (best effort). A non-zero exit (process already gone) is NOT a spawn
77
+ // failure, so it correctly does not trigger the fallback. (`res?.` tolerates test mocks.)
78
+ const res = spawnSync('taskkill', args, { stdio: 'ignore', windowsHide: true });
79
+ if (res?.error) {
80
+ try {
81
+ child.kill(signal);
82
+ }
83
+ catch {
84
+ // Already exited — nothing to do.
85
+ }
86
+ }
87
+ return;
88
+ }
89
+ try {
90
+ // Negative pid → signal the entire process group.
91
+ process.kill(-child.pid, signal);
92
+ return;
93
+ }
94
+ catch (e) {
95
+ const code = e?.code;
96
+ // ESRCH: already gone. EPERM: group-kill not permitted — fall through to the
97
+ // direct child kill below. Anything else: also fall back rather than throw.
98
+ if (code === 'ESRCH')
99
+ return;
100
+ }
101
+ // Fallback: kill just the child (best effort).
102
+ try {
103
+ child.kill(signal);
104
+ }
105
+ catch {
106
+ // Already exited — nothing to do.
107
+ }
108
+ }
10
109
  // Helper function to create a tool with dev type
11
110
  function createGthTool(fn, config, gthDevType) {
12
111
  const toolInstance = tool(fn, config);
@@ -21,13 +120,23 @@ const RunBuildArgsSchema = z.object({});
21
120
  const RunSingleTestArgsSchema = z.object({
22
121
  testPath: z.string().describe('Relative path to the test file to run'),
23
122
  });
123
+ const RunShellCommandArgsSchema = z.object({
124
+ command: z.string().describe('The shell command to run'),
125
+ });
24
126
  const TEST_PATH_PLACEHOLDER = '${testPath}';
25
127
  export default class GthDevToolkit extends BaseToolkit {
26
128
  tools;
27
129
  commands;
28
- constructor(commands = {}) {
130
+ /**
131
+ * The active command, threaded through so the EXT-12 absent-config default for the shell
132
+ * tool (ON in `code`, OFF elsewhere) is resolved consistently with the deep agent's
133
+ * interrupt wiring. Omitted → historical OFF-by-default behaviour.
134
+ */
135
+ command;
136
+ constructor(commands = {}, command) {
29
137
  super();
30
138
  this.commands = commands;
139
+ this.command = command;
31
140
  this.tools = this.createTools();
32
141
  }
33
142
  /**
@@ -93,45 +202,132 @@ export default class GthDevToolkit extends BaseToolkit {
93
202
  throw new Error('No test command configured');
94
203
  }
95
204
  }
205
+ /**
206
+ * Execute a shell command with the EXT-9 Tier-1 hardening applied:
207
+ * 1. stdin closed + timeout + process-group kill (no hang on interactive
208
+ * commands; runaway commands are killed group-wide on timeout),
209
+ * 2. output capped with a head/tail window + temp-file spillover,
210
+ * 3. provider/LLM credentials scrubbed from the child env,
211
+ * 4. an unbypassable hardline blocklist (refuses catastrophic commands BEFORE
212
+ * spawn — fires even when confirmation is bypassed by yolo).
213
+ *
214
+ * Resolves with a model-facing string on a CLEAN exit (`code === 0`). EXT-20: a non-zero exit
215
+ * and a timeout-kill instead REJECT with a {@link ShellCommandFailedError} that carries the FULL
216
+ * model-facing body — the deep-agent {@link GthDeepShellExitSoftening} middleware converts that
217
+ * throw into an error `ToolMessage` (status:'error' → ✗) while preserving the output, so the
218
+ * model still sees the killed-after-N / exit-code message and can continue. Spawn-level failures
219
+ * (`child.on('error')`) still reject with a plain `Error`.
220
+ */
96
221
  async executeCommand(command, toolName) {
97
222
  displayInfo(`\n🔧 Executing ${toolName}: ${command}`);
223
+ // (4) Hardline blocklist — checked here so it fires regardless of yolo,
224
+ // allow-lists, or any confirmation path. Refuse WITHOUT executing.
225
+ const hardline = checkHardline(command);
226
+ if (hardline) {
227
+ const refusal = `Refusing to execute '${command}': blocked by hardline safety policy ` +
228
+ `(${hardline.description}). This is a catastrophic, non-recoverable command ` +
229
+ `and is blocked even when command confirmation is disabled.`;
230
+ displayWarning(`\n⛔ ${refusal}`);
231
+ return refusal;
232
+ }
233
+ const timeoutMs = getShellTimeoutMs(this.commands);
234
+ const maxOutputBytes = getShellMaxOutputBytes(this.commands);
98
235
  return new Promise((resolve, reject) => {
99
236
  const child = spawn(command, {
100
237
  shell: true,
238
+ // EXT-22 (S4): spawn in the SAME directory the deepagents FilesystemBackend is rooted at,
239
+ // so the shell tool and the fs tools (ls/read_file/write_file/edit_file/glob/grep) operate
240
+ // on one path namespace instead of diverging. That backend is constructed with
241
+ // `rootDir: getCurrentWorkDir()` (GthDeepAgent.ts init), so getCurrentWorkDir() IS the
242
+ // fs-backend root on the local code/chat runner. getCurrentWorkDir() =
243
+ // `process.env.INIT_CWD ?? process.cwd()` (core systemUtils); it only diverges from bare
244
+ // process.cwd() when INIT_CWD is set (npm-bin / IDE-spawned launches) — exactly the
245
+ // POSIX-latent divergence S4 closes. Evaluated at call time.
246
+ cwd: getCurrentWorkDir(),
247
+ // (1) Never let the child block on stdin (e.g. git commit opening $EDITOR).
248
+ stdio: ['ignore', 'pipe', 'pipe'],
249
+ // (1) POSIX: own process group so we can kill the whole tree on timeout
250
+ // (see killProcessGroup). No-op/harmful on Windows, which uses taskkill /T.
251
+ detached: process.platform !== 'win32',
252
+ // (3) Child env with provider/LLM credentials removed.
253
+ env: buildScrubbedEnv(),
101
254
  });
102
- let output = '';
103
- // Capture output if available (when stdio is not 'inherit')
255
+ // (2) Bounded capture for the returned message; live streaming is uncapped.
256
+ const buffer = new OutputBuffer(maxOutputBytes);
257
+ let timedOut = false;
258
+ let settled = false;
259
+ let killTimer;
260
+ const timeoutTimer = setTimeout(() => {
261
+ timedOut = true;
262
+ killProcessGroup(child, 'SIGTERM');
263
+ // Escalate to SIGKILL after a short grace if it didn't die.
264
+ killTimer = setTimeout(() => killProcessGroup(child, 'SIGKILL'), KILL_GRACE_MS);
265
+ // killTimer must not keep the event loop alive on its own.
266
+ killTimer.unref?.();
267
+ }, timeoutMs);
268
+ timeoutTimer.unref?.();
269
+ const clearTimers = () => {
270
+ clearTimeout(timeoutTimer);
271
+ if (killTimer)
272
+ clearTimeout(killTimer);
273
+ };
104
274
  if (child.stdout) {
105
275
  child.stdout.on('data', (data) => {
106
276
  const chunk = data.toString();
107
277
  stdout.write(chunk);
108
- output += chunk;
278
+ buffer.append(chunk);
109
279
  });
110
280
  }
111
281
  if (child.stderr) {
112
282
  child.stderr.on('data', (data) => {
113
283
  const chunk = data.toString();
114
284
  stdout.write(chunk);
115
- output += chunk;
285
+ buffer.append(chunk);
116
286
  });
117
287
  }
118
288
  child.on('close', (code) => {
289
+ if (settled)
290
+ return;
291
+ settled = true;
292
+ clearTimers();
293
+ const captured = buffer.finalize();
294
+ const body = `Executing '${command}'...\n\n` +
295
+ `<COMMAND_OUTPUT>\n` +
296
+ captured.text +
297
+ `</COMMAND_OUTPUT>\n`;
298
+ if (timedOut) {
299
+ // EXT-20: a timeout-kill is a failure — reject so the deep-agent middleware flips the
300
+ // tool result to status:'error' (✗). The FULL body is preserved on the error so the
301
+ // model's observation is unchanged except for the status.
302
+ reject(new ShellCommandFailedError({
303
+ output: body +
304
+ `\n\nCommand '${command}' was killed after exceeding the ${Math.round(timeoutMs / 1000)}s timeout. ` +
305
+ `If it legitimately needs longer, increase the shell timeout in config.`,
306
+ exitCode: null,
307
+ command,
308
+ toolName,
309
+ }));
310
+ return;
311
+ }
119
312
  if (code === 0) {
120
- resolve(`Executing '${command}'...\n\n` +
121
- `<COMMAND_OUTPUT>\n` +
122
- output +
123
- `</COMMAND_OUTPUT>\n` +
124
- `\n\nCommand '${command}' completed successfully`);
313
+ resolve(body + `\n\nCommand '${command}' completed successfully`);
125
314
  }
126
315
  else {
127
- resolve(`Executing '${command}'...\n\n` +
128
- `<COMMAND_OUTPUT>\n` +
129
- output +
130
- `</COMMAND_OUTPUT>\n` +
131
- `\n\nCommand '${command}' exited with code ${code}`);
316
+ // EXT-20: a non-zero exit is a failure — reject (was resolve) so the softening
317
+ // middleware surfaces the ✗ (isError) signal while preserving the full output body.
318
+ reject(new ShellCommandFailedError({
319
+ output: body + `\n\nCommand '${command}' exited with code ${code}`,
320
+ exitCode: code,
321
+ command,
322
+ toolName,
323
+ }));
132
324
  }
133
325
  });
134
326
  child.on('error', (error) => {
327
+ if (settled)
328
+ return;
329
+ settled = true;
330
+ clearTimers();
135
331
  const errorMsg = `Failed to execute command '${command}': ${error.message}`;
136
332
  displayError(errorMsg);
137
333
  reject(new Error(errorMsg));
@@ -183,6 +379,22 @@ export default class GthDevToolkit extends BaseToolkit {
183
379
  schema: RunBuildArgsSchema,
184
380
  }, 'execute'));
185
381
  }
382
+ // Opt-in general-purpose shell tool. Unlike the fixed run_* commands, the model supplies
383
+ // the command, so the guardrail is the per-command confirmation dialog wired by the deep
384
+ // agent (createDeepAgent `interruptOn`), not a parameter sanitizer — a real shell command
385
+ // legitimately contains pipes / `$` / `;`, so validateParameterValue must NOT be applied.
386
+ if (isShellToolEnabled(this.commands, this.command)) {
387
+ tools.push(createGthTool(async (args) => {
388
+ return await this.executeCommand(args.command, 'run_shell_command');
389
+ }, {
390
+ name: 'run_shell_command',
391
+ description: 'Run an arbitrary shell command in the project working directory and return its ' +
392
+ 'combined stdout/stderr and exit status. Use for any task the fixed run_* tools do ' +
393
+ 'not cover (e.g. git, package managers, file inspection). Each call is subject to ' +
394
+ 'human approval before it runs unless approval has been disabled.',
395
+ schema: RunShellCommandArgsSchema,
396
+ }, 'execute'));
397
+ }
186
398
  return tools;
187
399
  }
188
400
  }
@@ -1 +1 @@
1
- {"version":3,"file":"GthDevToolkit.js","sourceRoot":"","sources":["../../src/tools/GthDevToolkit.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"GthDevToolkit.js","sourceRoot":"","sources":["../../src/tools/GthDevToolkit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @module tools/shell/allowlist
3
+ *
4
+ * Re-export of the EXT-9 Tier-2 allow-list engine. The implementation lives in
5
+ * `@gaunt-sloth/core` (`core/shell/allowlist`) because the core {@link GthAgentRunner}
6
+ * owns the per-instance session store and the loaded persisted store and consults
7
+ * `matchesApproval` before prompting (core cannot import from `@gaunt-sloth/agent`).
8
+ *
9
+ * See the core module for the exact safe-bin / anti-widening matching rule.
10
+ */
11
+ export { matchesApproval, hasWideningFlag, AllowlistStore, PersistedAllowlist, type ApprovalScope, type ApprovalStores, } from '@gaunt-sloth/core/core/shell/allowlist.js';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @module tools/shell/allowlist
3
+ *
4
+ * Re-export of the EXT-9 Tier-2 allow-list engine. The implementation lives in
5
+ * `@gaunt-sloth/core` (`core/shell/allowlist`) because the core {@link GthAgentRunner}
6
+ * owns the per-instance session store and the loaded persisted store and consults
7
+ * `matchesApproval` before prompting (core cannot import from `@gaunt-sloth/agent`).
8
+ *
9
+ * See the core module for the exact safe-bin / anti-widening matching rule.
10
+ */
11
+ export { matchesApproval, hasWideningFlag, AllowlistStore, PersistedAllowlist, } from '@gaunt-sloth/core/core/shell/allowlist.js';
12
+ //# sourceMappingURL=allowlist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allowlist.js","sourceRoot":"","sources":["../../../src/tools/shell/allowlist.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EACL,eAAe,EACf,eAAe,EACf,cAAc,EACd,kBAAkB,GAGnB,MAAM,2CAA2C,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @module tools/shell/arity
3
+ *
4
+ * Re-export of the EXT-9 Tier-2 command classifier. The implementation lives in
5
+ * `@gaunt-sloth/core` (`core/shell/arity`) because the core {@link GthAgentRunner}
6
+ * must consult it BEFORE prompting (and core cannot import from `@gaunt-sloth/agent`).
7
+ * This stable agent-side path is kept for tests and any agent-layer consumers.
8
+ *
9
+ * See the core module for the arity table scope and the anti-injection fail-closed rule.
10
+ */
11
+ export { classifyCommand, tokenize, meaningfulPrefixTokens, type CommandClassification, } from '@gaunt-sloth/core/core/shell/arity.js';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @module tools/shell/arity
3
+ *
4
+ * Re-export of the EXT-9 Tier-2 command classifier. The implementation lives in
5
+ * `@gaunt-sloth/core` (`core/shell/arity`) because the core {@link GthAgentRunner}
6
+ * must consult it BEFORE prompting (and core cannot import from `@gaunt-sloth/agent`).
7
+ * This stable agent-side path is kept for tests and any agent-layer consumers.
8
+ *
9
+ * See the core module for the arity table scope and the anti-injection fail-closed rule.
10
+ */
11
+ export { classifyCommand, tokenize, meaningfulPrefixTokens, } from '@gaunt-sloth/core/core/shell/arity.js';
12
+ //# sourceMappingURL=arity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arity.js","sourceRoot":"","sources":["../../../src/tools/shell/arity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EACL,eAAe,EACf,QAAQ,EACR,sBAAsB,GAEvB,MAAM,uCAAuC,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Explicit blocklist of LLM-provider and cloud credentials. Covers the providers
3
+ * gaunt-sloth (and its consumers) can be configured against, plus the standard
4
+ * cloud secret-bearing vars. Matched case-insensitively.
5
+ */
6
+ export declare const CREDENTIAL_BLOCKLIST: ReadonlyArray<string>;
7
+ /**
8
+ * Allow-list of credential-shaped names that must survive the wildcard sweep
9
+ * because gaunt-sloth legitimately depends on them. Matched case-insensitively.
10
+ */
11
+ export declare const CREDENTIAL_ALLOWLIST: ReadonlyArray<string>;
12
+ /**
13
+ * True when an env var name should be scrubbed from the child environment.
14
+ * Exported for testing.
15
+ */
16
+ export declare function shouldScrubEnvVar(name: string): boolean;
17
+ /**
18
+ * Build the child environment for a spawned shell command: a copy of the parent
19
+ * env with LLM/cloud credentials removed. Defaults to the live `process.env`
20
+ * (via systemUtils); a source can be injected for testing.
21
+ */
22
+ export declare function buildScrubbedEnv(source?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
@@ -0,0 +1,110 @@
1
+ /**
2
+ * @module tools/shell/env
3
+ *
4
+ * Credential scrubbing for the shell tool's child environment. By default a
5
+ * spawned child inherits `process.env` verbatim, so an approved (or yolo'd)
6
+ * command can `echo $ANTHROPIC_API_KEY` and exfiltrate the operator's LLM/cloud
7
+ * credentials. {@link buildScrubbedEnv} returns a copy of the parent env with
8
+ * those credentials removed before spawn.
9
+ *
10
+ * Policy (deliberately scoped):
11
+ * - Strip LLM provider keys and cloud-provider secrets (the explicit blocklist +
12
+ * a wildcard sweep for `*_API_KEY` / `*_TOKEN` / `*_SECRET` / `*SECRET_KEY`).
13
+ * - LEAVE generic dev env intact (PATH, HOME, SHELL, LANG, npm/pnpm config, …)
14
+ * so normal commands still work.
15
+ * - LEAVE `GITHUB_TOKEN` / `GH_TOKEN` intact: gaunt-sloth's content/requirement
16
+ * providers shell out to `gh` (`gh pr diff`, `gh issue view`), so stripping
17
+ * these would break first-class workflows. They are explicitly allow-listed
18
+ * against the wildcard `*_TOKEN` sweep.
19
+ *
20
+ * Patterned after hermes-agent `_HERMES_PROVIDER_ENV_BLOCKLIST` (tools/environments/local.py)
21
+ * — but narrower: we only own the provider/cloud-secret floor.
22
+ */
23
+ import { env as processEnv } from '@gaunt-sloth/core/utils/systemUtils.js';
24
+ /**
25
+ * Explicit blocklist of LLM-provider and cloud credentials. Covers the providers
26
+ * gaunt-sloth (and its consumers) can be configured against, plus the standard
27
+ * cloud secret-bearing vars. Matched case-insensitively.
28
+ */
29
+ export const CREDENTIAL_BLOCKLIST = [
30
+ // LLM providers
31
+ 'ANTHROPIC_API_KEY',
32
+ 'ANTHROPIC_AUTH_TOKEN',
33
+ 'CLAUDE_CODE_OAUTH_TOKEN',
34
+ 'OPENAI_API_KEY',
35
+ 'GOOGLE_API_KEY',
36
+ 'GEMINI_API_KEY',
37
+ 'GOOGLE_APPLICATION_CREDENTIALS',
38
+ 'GROQ_API_KEY',
39
+ 'XAI_API_KEY',
40
+ 'DEEPSEEK_API_KEY',
41
+ 'MISTRAL_API_KEY',
42
+ 'OPENROUTER_API_KEY',
43
+ 'COHERE_API_KEY',
44
+ 'TOGETHER_API_KEY',
45
+ 'PERPLEXITY_API_KEY',
46
+ 'FIREWORKS_API_KEY',
47
+ // Azure OpenAI
48
+ 'AZURE_OPENAI_API_KEY',
49
+ 'AZURE_API_KEY',
50
+ // Cloud provider secrets (AWS / GCP)
51
+ 'AWS_SECRET_ACCESS_KEY',
52
+ 'AWS_SESSION_TOKEN',
53
+ 'AWS_ACCESS_KEY_ID',
54
+ ];
55
+ /**
56
+ * Allow-list of credential-shaped names that must survive the wildcard sweep
57
+ * because gaunt-sloth legitimately depends on them. Matched case-insensitively.
58
+ */
59
+ export const CREDENTIAL_ALLOWLIST = [
60
+ // `gh` CLI auth — used by the github content/requirement providers.
61
+ 'GITHUB_TOKEN',
62
+ 'GH_TOKEN',
63
+ ];
64
+ // Wildcard sweep: any var whose name ends in one of these suffixes is treated as
65
+ // a secret and stripped (unless allow-listed). Catches provider keys we didn't
66
+ // enumerate (e.g. a new `FOO_API_KEY`).
67
+ const SECRET_SUFFIXES = [
68
+ /_API_KEY$/i,
69
+ /_SECRET_ACCESS_KEY$/i,
70
+ /_SECRET_KEY$/i,
71
+ /_SECRET$/i,
72
+ /_TOKEN$/i,
73
+ ];
74
+ function isAllowlisted(name) {
75
+ return CREDENTIAL_ALLOWLIST.some((a) => a.toUpperCase() === name.toUpperCase());
76
+ }
77
+ function isBlocklisted(name) {
78
+ return CREDENTIAL_BLOCKLIST.some((b) => b.toUpperCase() === name.toUpperCase());
79
+ }
80
+ function matchesSecretSuffix(name) {
81
+ return SECRET_SUFFIXES.some((re) => re.test(name));
82
+ }
83
+ /**
84
+ * True when an env var name should be scrubbed from the child environment.
85
+ * Exported for testing.
86
+ */
87
+ export function shouldScrubEnvVar(name) {
88
+ if (isAllowlisted(name))
89
+ return false;
90
+ if (isBlocklisted(name))
91
+ return true;
92
+ return matchesSecretSuffix(name);
93
+ }
94
+ /**
95
+ * Build the child environment for a spawned shell command: a copy of the parent
96
+ * env with LLM/cloud credentials removed. Defaults to the live `process.env`
97
+ * (via systemUtils); a source can be injected for testing.
98
+ */
99
+ export function buildScrubbedEnv(source = processEnv) {
100
+ const scrubbed = {};
101
+ for (const [key, value] of Object.entries(source)) {
102
+ if (value === undefined)
103
+ continue;
104
+ if (shouldScrubEnvVar(key))
105
+ continue;
106
+ scrubbed[key] = value;
107
+ }
108
+ return scrubbed;
109
+ }
110
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../../src/tools/shell/env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,GAAG,IAAI,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAE3E;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAA0B;IACzD,gBAAgB;IAChB,mBAAmB;IACnB,sBAAsB;IACtB,yBAAyB;IACzB,gBAAgB;IAChB,gBAAgB;IAChB,gBAAgB;IAChB,gCAAgC;IAChC,cAAc;IACd,aAAa;IACb,kBAAkB;IAClB,iBAAiB;IACjB,oBAAoB;IACpB,gBAAgB;IAChB,kBAAkB;IAClB,oBAAoB;IACpB,mBAAmB;IACnB,eAAe;IACf,sBAAsB;IACtB,eAAe;IACf,qCAAqC;IACrC,uBAAuB;IACvB,mBAAmB;IACnB,mBAAmB;CACpB,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAA0B;IACzD,oEAAoE;IACpE,cAAc;IACd,UAAU;CACX,CAAC;AAEF,iFAAiF;AACjF,+EAA+E;AAC/E,wCAAwC;AACxC,MAAM,eAAe,GAAG;IACtB,YAAY;IACZ,sBAAsB;IACtB,eAAe;IACf,WAAW;IACX,UAAU;CACX,CAAC;AAEF,SAAS,aAAa,CAAC,IAAY;IACjC,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;AAClF,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IACjC,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;AAClF,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAY;IACvC,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACrD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,IAAI,aAAa,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACtC,IAAI,aAAa,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,OAAO,mBAAmB,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAA4B,UAAU;IACrE,MAAM,QAAQ,GAAsB,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAClC,IAAI,iBAAiB,CAAC,GAAG,CAAC;YAAE,SAAS;QACrC,QAAQ,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACxB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Hardline patterns: [regex, human description]. Matched case-insensitively
3
+ * against the normalized command.
4
+ */
5
+ export declare const HARDLINE_PATTERNS: ReadonlyArray<readonly [RegExp, string]>;
6
+ export interface HardlineMatch {
7
+ /** Human-readable reason the command was refused. */
8
+ description: string;
9
+ }
10
+ /**
11
+ * Check a raw command against the hardline blocklist. Normalizes first so
12
+ * obfuscated variants are caught. Returns the match (with a description) when the
13
+ * command is catastrophic, or `null` when it is allowed to proceed.
14
+ */
15
+ export declare function checkHardline(command: string): HardlineMatch | null;
@@ -0,0 +1,88 @@
1
+ /**
2
+ * @module tools/shell/hardline
3
+ *
4
+ * Unbypassable hardline blocklist for the shell tool. These are catastrophic,
5
+ * non-recoverable commands (wipe the root filesystem, format a disk, overwrite a
6
+ * raw block device, fork-bomb, take the host down). They are refused inside
7
+ * `executeCommand` itself — BEFORE spawn — so the refusal fires regardless of
8
+ * yolo (`shellYolo`), any allow-list, or the confirmation path. yolo deliberately
9
+ * bypasses the *confirmation*; it does NOT bypass this floor.
10
+ *
11
+ * Recoverable-but-costly operations (e.g. `git reset --hard`, `rm -rf ./build`,
12
+ * `chmod -R 777 ./dir`, `curl | sh`) are intentionally NOT here — those are what
13
+ * the confirmation dialog / yolo are for.
14
+ *
15
+ * Patterns match the NORMALIZED command ({@link ./normalize.js}) so obfuscation
16
+ * (ANSI/fullwidth/backslash splits/whitespace padding) cannot bypass them.
17
+ *
18
+ * Patterned after hermes-agent `tools/approval.py` HARDLINE_PATTERNS.
19
+ */
20
+ import { normalizeCommand } from '#src/tools/shell/normalize.js';
21
+ // Matches a position where the shell would begin parsing a NEW command: start of
22
+ // string, after a separator (; & | newline), after `$(` or backtick, optionally
23
+ // consuming leading wrappers (sudo/env VAR=VAL/exec/nohup/setsid/time). Used by
24
+ // the shutdown-family patterns so they don't false-positive on `echo reboot`.
25
+ const CMD_POS = '(?:^|[;&|\\n`]|\\$\\()' +
26
+ '\\s*' +
27
+ '(?:sudo\\s+(?:-[^\\s]+\\s+)*)?' +
28
+ '(?:env\\s+(?:\\w+=\\S*\\s+)*)?' +
29
+ '(?:(?:exec|nohup|setsid|time)\\s+)*' +
30
+ '\\s*';
31
+ /**
32
+ * Hardline patterns: [regex, human description]. Matched case-insensitively
33
+ * against the normalized command.
34
+ */
35
+ export const HARDLINE_PATTERNS = [
36
+ // rm -rf targeting the root filesystem (`/`, `/*`).
37
+ [/\brm\s+(?:-[^\s]*\s+)*\/\s*\*?\s*(?:$|[;&|])/, 'recursive delete of root filesystem'],
38
+ // rm -rf targeting protected system directories (with optional /* suffix).
39
+ [
40
+ /\brm\s+(?:-[^\s]*\s+)*(?:\/(?:home|root|etc|usr|var|bin|sbin|boot|lib|lib64|opt|sys|proc))(?:\/\*)?\s*(?:$|[;&|])/,
41
+ 'recursive delete of system directory',
42
+ ],
43
+ // rm -rf targeting the home directory (~ or $HOME).
44
+ // Note: patterns match the LOWERCASED normalized command, so $HOME → $home.
45
+ [
46
+ /\brm\s+(?:-[^\s]*\s+)*(?:~|\$home)(?:\/\*)?\s*(?:$|[;&|])/,
47
+ 'recursive delete of home directory',
48
+ ],
49
+ // Filesystem format.
50
+ [/\bmkfs(?:\.[a-z0-9]+)?\b/, 'format filesystem (mkfs)'],
51
+ // dd writing to a raw block device.
52
+ [/\bdd\b[^\n]*\bof=\/dev\/(?:sd|nvme|hd|mmcblk|vd|xvd)[a-z0-9]*/, 'dd to raw block device'],
53
+ // Shell redirection to a raw block device (`> /dev/sda`).
54
+ [/>\s*\/dev\/(?:sd|nvme|hd|mmcblk|vd|xvd)[a-z0-9]*\b/, 'redirect to raw block device'],
55
+ // Classic fork bomb `:(){ :|:& };:`.
56
+ [/:\s*\(\s*\)\s*\{\s*:\s*\|\s*:\s*&\s*\}\s*;\s*:/, 'fork bomb'],
57
+ // chmod -R 777 / (recursive world-writable on root).
58
+ [
59
+ /\bchmod\s+(?:-[^\s]*\s+)*(?:-r|--recursive)\s+(?:-[^\s]*\s+)*777\s+\//,
60
+ 'recursive chmod 777 of root',
61
+ ],
62
+ // Kill every process on the system (`kill -1`, `kill -9 -1`).
63
+ [/\bkill\s+(?:-[^\s]+\s+)*-1\b/, 'kill all processes'],
64
+ // System shutdown / reboot — anchored to a command position so `echo reboot`
65
+ // and `grep shutdown log` don't trip it.
66
+ [new RegExp(CMD_POS + '(?:shutdown|reboot|halt|poweroff)\\b'), 'system shutdown/reboot'],
67
+ [new RegExp(CMD_POS + 'init\\s+[06]\\b'), 'init 0/6 (shutdown/reboot)'],
68
+ [
69
+ new RegExp(CMD_POS + 'systemctl\\s+(?:poweroff|reboot|halt|kexec)\\b'),
70
+ 'systemctl poweroff/reboot',
71
+ ],
72
+ [new RegExp(CMD_POS + 'telinit\\s+[06]\\b'), 'telinit 0/6 (shutdown/reboot)'],
73
+ ];
74
+ /**
75
+ * Check a raw command against the hardline blocklist. Normalizes first so
76
+ * obfuscated variants are caught. Returns the match (with a description) when the
77
+ * command is catastrophic, or `null` when it is allowed to proceed.
78
+ */
79
+ export function checkHardline(command) {
80
+ const normalized = normalizeCommand(command).toLowerCase();
81
+ for (const [pattern, description] of HARDLINE_PATTERNS) {
82
+ if (pattern.test(normalized)) {
83
+ return { description };
84
+ }
85
+ }
86
+ return null;
87
+ }
88
+ //# sourceMappingURL=hardline.js.map