just-bash-mcp 2.9.0 → 2.9.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 CHANGED
@@ -7,11 +7,11 @@ An MCP (Model Context Protocol) server that provides a sandboxed bash environmen
7
7
 
8
8
  Execute bash commands in a secure, isolated environment with an in-memory virtual filesystem.
9
9
 
10
- Built on top of [`just-bash`](https://github.com/vercel-labs/just-bash) v2.9.6.
10
+ Built on top of [`just-bash`](https://github.com/vercel-labs/just-bash) v2.10.2.
11
11
 
12
- ## What's New in v2.8.0
12
+ ## What's New in v2.9.0
13
13
 
14
- - **Synced with upstream `just-bash` v2.9.6** - Latest security hardening, defense-in-depth, fuzzing, jq fixes, and large file support
14
+ - **Synced with upstream `just-bash` v2.10.2** - Latest upstream commands, APIs, and type exports
15
15
  - **Defense-in-depth mode** - Opt-in monkey-patching of dangerous JS globals (`JUST_BASH_DEFENSE_IN_DEPTH=true`)
16
16
  - **Python support** - Python3 via Pyodide (`JUST_BASH_ENABLE_PYTHON=true`)
17
17
  - **Vercel Sandbox API** - Compatible `bash_sandbox_*` tools for isolated execution
@@ -180,7 +180,8 @@ Get current working directory or environment variables.
180
180
 
181
181
  Compatible with the Vercel Sandbox API:
182
182
 
183
- - `bash_sandbox_run` - Run a command in the sandbox
183
+ - `bash_sandbox_run` - Run a command in the sandbox (optionally include structured output/logs)
184
+ - `bash_sandbox_domain` - Get the sandbox domain/identifier
184
185
  - `bash_sandbox_write_files` - Write multiple files at once
185
186
  - `bash_sandbox_read_file` - Read a file (supports base64 encoding)
186
187
  - `bash_sandbox_mkdir` - Create a directory
@@ -275,7 +276,7 @@ Compatible with the Vercel Sandbox API:
275
276
 
276
277
  ## Upstream API Coverage
277
278
 
278
- This wrapper integrates the full public API surface of `just-bash` v2.9.6:
279
+ This wrapper integrates the full public API surface of `just-bash` v2.10.2:
279
280
 
280
281
  | Category | Exports Used |
281
282
  |----------|-------------|
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "just-bash-mcp",
3
- "version": "2.9.0",
3
+ "version": "2.9.2",
4
4
  "description": "MCP server providing a sandboxed bash environment using just-bash",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -60,14 +60,14 @@
60
60
  },
61
61
  "packageManager": "bun@1.3.8",
62
62
  "dependencies": {
63
- "@modelcontextprotocol/sdk": "^1.26.0",
64
- "just-bash": "^2.9.6",
63
+ "@modelcontextprotocol/sdk": "^1.27.0",
64
+ "just-bash": "^2.10.2",
65
65
  "zod": "^4.3.6"
66
66
  },
67
67
  "devDependencies": {
68
- "@types/node": "^25.2.2",
68
+ "@types/node": "^25.3.0",
69
69
  "oxfmt": "^0.28.0",
70
- "oxlint": "^1.43.0",
70
+ "oxlint": "^1.50.0",
71
71
  "oxlint-tsgolint": "^0.11.5"
72
72
  }
73
73
  }
@@ -3,6 +3,9 @@
3
3
  * Handles environment variable parsing and configuration building
4
4
  */
5
5
 
6
+ import { readFileSync } from "node:fs";
7
+ import { dirname, join } from "node:path";
8
+ import { fileURLToPath } from "node:url";
6
9
  import {
7
10
  type BashLogger,
8
11
  type BashOptions,
@@ -10,8 +13,6 @@ import {
10
13
  type DefenseInDepthConfig,
11
14
  type MountConfig,
12
15
  type NetworkConfig,
13
- type TraceCallback,
14
- type TraceEvent,
15
16
  OverlayFs,
16
17
  ReadWriteFs,
17
18
  SecurityViolationLogger,
@@ -19,7 +20,16 @@ import {
19
20
  } from "just-bash";
20
21
 
21
22
  // Re-export upstream types used by other modules
22
- export type { DefenseInDepthConfig, TraceCallback, TraceEvent };
23
+ export type { DefenseInDepthConfig };
24
+
25
+ export interface TraceEvent {
26
+ category: string;
27
+ name: string;
28
+ durationMs: number;
29
+ details?: Record<string, unknown>;
30
+ }
31
+
32
+ export type TraceCallback = (event: TraceEvent) => void;
23
33
 
24
34
  // ============================================================================
25
35
  // Types
@@ -92,6 +102,22 @@ export interface Config {
92
102
  readonly ALLOWED_COMMANDS: CommandName[] | undefined;
93
103
  }
94
104
 
105
+ function readPackageVersion(relativePath: string): string {
106
+ try {
107
+ const __dirname = dirname(fileURLToPath(import.meta.url));
108
+ const packagePath = join(__dirname, relativePath);
109
+ const packageJson = JSON.parse(readFileSync(packagePath, "utf-8")) as { version?: string };
110
+ return packageJson.version || "unknown";
111
+ } catch {
112
+ return "unknown";
113
+ }
114
+ }
115
+
116
+ export const WRAPPER_VERSION = readPackageVersion("../../package.json");
117
+ export const UPSTREAM_JUST_BASH_VERSION = readPackageVersion(
118
+ "../../node_modules/just-bash/package.json",
119
+ );
120
+
95
121
  function getAllowedMethods(): HttpMethod[] {
96
122
  const methods = parseEnvStringArray("JUST_BASH_ALLOWED_METHODS");
97
123
  return methods.length > 0 ? (methods as HttpMethod[]) : ["GET", "HEAD"];
@@ -111,7 +137,7 @@ function parseEnvOptionalInt(key: string): number | undefined {
111
137
 
112
138
  export const config: Config = {
113
139
  // Server info
114
- VERSION: "2.8.0",
140
+ VERSION: WRAPPER_VERSION,
115
141
  SERVER_NAME: "just-bash-mcp",
116
142
 
117
143
  // Filesystem configuration
@@ -187,7 +213,7 @@ export const bashLogger: BashLogger | undefined = config.ENABLE_LOGGING
187
213
  }
188
214
  : undefined;
189
215
 
190
- export const traceCallback: TraceCallback | undefined = config.ENABLE_TRACING
216
+ export const traceCallback: BashOptions["trace"] = config.ENABLE_TRACING
191
217
  ? (event: TraceEvent) => {
192
218
  if (event.details) {
193
219
  console.error(
@@ -226,7 +252,7 @@ export function buildDefenseInDepthConfig(): DefenseInDepthConfig | false {
226
252
  return {
227
253
  enabled: true,
228
254
  auditMode: config.DEFENSE_IN_DEPTH_AUDIT,
229
- onViolation: (violation) => {
255
+ onViolation: (violation: { type: string; target: string; details: string }) => {
230
256
  violationLogger.record(violation);
231
257
  consoleCallback?.(violation);
232
258
  },
@@ -6,9 +6,6 @@
6
6
  * SecurityViolationLogger for defense-in-depth violation reporting.
7
7
  */
8
8
 
9
- import { readFileSync } from "node:fs";
10
- import { dirname, join } from "node:path";
11
- import { fileURLToPath } from "node:url";
12
9
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
13
10
  import {
14
11
  type AllCommandName,
@@ -24,27 +21,12 @@ import {
24
21
  ENVIRONMENT_VARIABLES,
25
22
  FEATURES,
26
23
  parseMountsConfig,
24
+ UPSTREAM_JUST_BASH_VERSION,
27
25
  violationLogger,
28
26
  } from "../config/index.ts";
29
27
  import { createErrorResponse, createJsonResponse } from "../utils/index.ts";
30
28
  import { getDefenseInDepthBox, getPersistentBash } from "./bash-instance.ts";
31
29
 
32
- function getUpstreamVersion(): string {
33
- try {
34
- // Resolve the just-bash package directory relative to this module
35
- const __dirname = dirname(fileURLToPath(import.meta.url));
36
- const pkgPath = join(__dirname, "..", "..", "node_modules", "just-bash", "package.json");
37
- const pkg: { version: string } = JSON.parse(readFileSync(pkgPath, "utf-8")) as {
38
- version: string;
39
- };
40
- return pkg.version;
41
- } catch {
42
- return "unknown";
43
- }
44
- }
45
-
46
- const UPSTREAM_VERSION = getUpstreamVersion();
47
-
48
30
  /**
49
31
  * Register information tools with the MCP server
50
32
  */
@@ -98,7 +80,7 @@ export function registerInfoTools(server: McpServer): void {
98
80
 
99
81
  const info = {
100
82
  version: config.VERSION,
101
- upstreamVersion: UPSTREAM_VERSION,
83
+ upstreamVersion: UPSTREAM_JUST_BASH_VERSION,
102
84
  fsMode,
103
85
  fsRoot: config.READ_WRITE_ROOT || config.OVERLAY_ROOT || null,
104
86
  overlayReadOnly: config.OVERLAY_ROOT ? config.OVERLAY_READ_ONLY : null,
@@ -15,6 +15,7 @@ import {
15
15
  RedirectNotAllowedError,
16
16
  SecurityViolationError,
17
17
  TooManyRedirectsError,
18
+ type OutputMessage,
18
19
  } from "just-bash";
19
20
  import { z } from "zod/v4";
20
21
  import { config } from "../config/index.ts";
@@ -61,16 +62,28 @@ export function registerSandboxTools(server: McpServer): void {
61
62
  command: z.string().describe("The command to execute"),
62
63
  cwd: z.string().optional().describe("Working directory for the command"),
63
64
  env: z.record(z.string(), z.string()).optional().describe("Environment variables to set"),
65
+ includeOutput: z
66
+ .boolean()
67
+ .optional()
68
+ .describe("Include structured output messages from SandboxCommand.output()"),
69
+ includeLogs: z
70
+ .boolean()
71
+ .optional()
72
+ .describe("Include execution logs from SandboxCommand.logs()"),
64
73
  },
65
74
  },
66
75
  async ({
67
76
  command,
68
77
  cwd,
69
78
  env,
79
+ includeOutput = false,
80
+ includeLogs = false,
70
81
  }: {
71
82
  command: string;
72
83
  cwd?: string;
73
84
  env?: Record<string, string>;
85
+ includeOutput?: boolean;
86
+ includeLogs?: boolean;
74
87
  }) => {
75
88
  try {
76
89
  const sandbox = await getPersistentSandbox();
@@ -79,20 +92,55 @@ export function registerSandboxTools(server: McpServer): void {
79
92
  const stdout = await cmd.stdout();
80
93
  const stderr = await cmd.stderr();
81
94
 
82
- return createJsonResponse(
83
- {
84
- stdout: truncateOutput(stdout, config.MAX_OUTPUT_LENGTH, "stdout"),
85
- stderr: truncateOutput(stderr, config.MAX_OUTPUT_LENGTH, "stderr"),
86
- exitCode: result.exitCode,
87
- },
88
- result.exitCode !== 0,
89
- );
95
+ const response: {
96
+ stdout: string;
97
+ stderr: string;
98
+ exitCode: number;
99
+ output?: string;
100
+ logs?: OutputMessage[];
101
+ } = {
102
+ stdout: truncateOutput(stdout, config.MAX_OUTPUT_LENGTH, "stdout"),
103
+ stderr: truncateOutput(stderr, config.MAX_OUTPUT_LENGTH, "stderr"),
104
+ exitCode: result.exitCode,
105
+ };
106
+
107
+ if (includeOutput) {
108
+ response.output = truncateOutput(await cmd.output(), config.MAX_OUTPUT_LENGTH, "stdout");
109
+ }
110
+ if (includeLogs) {
111
+ const logs: OutputMessage[] = [];
112
+ for await (const message of cmd.logs()) {
113
+ logs.push(message);
114
+ }
115
+ response.logs = logs;
116
+ }
117
+
118
+ return createJsonResponse(response, result.exitCode !== 0);
90
119
  } catch (error) {
91
120
  return classifyError(error, "Sandbox error");
92
121
  }
93
122
  },
94
123
  );
95
124
 
125
+ // ========================================================================
126
+ // bash_sandbox_domain - Get sandbox domain
127
+ // ========================================================================
128
+ server.registerTool(
129
+ "bash_sandbox_domain",
130
+ {
131
+ description: "Get the current sandbox domain/identifier.",
132
+ inputSchema: {},
133
+ },
134
+ async () => {
135
+ try {
136
+ const sandbox = await getPersistentSandbox();
137
+ return createJsonResponse({ domain: sandbox.domain });
138
+ } catch (error) {
139
+ return classifyError(error, "Domain error");
140
+ }
141
+ },
142
+ );
143
+
96
144
  // ========================================================================
97
145
  // bash_sandbox_write_files - Write multiple files
98
146
  // ========================================================================
package/src/types.ts CHANGED
@@ -1,111 +1,7 @@
1
1
  /**
2
- * Re-export all upstream just-bash types for downstream consumers.
2
+ * Exact passthrough of the upstream just-bash public API.
3
3
  *
4
- * This barrel module provides a single import point for all types from
5
- * the just-bash package, so consumers of just-bash-mcp don't need to
6
- * depend on just-bash directly.
7
- *
8
- * Covers the full upstream API surface:
9
- * - Core: Bash, BashOptions, ExecOptions, BashExecResult, ExecResult
10
- * - Commands: CommandName, AllCommandName, NetworkCommandName, PythonCommandName
11
- * - Custom commands: CustomCommand, LazyCommand, defineCommand, Command, CommandContext
12
- * - Filesystem: IFileSystem, InMemoryFs, OverlayFs, ReadWriteFs, MountableFs + all types
13
- * - Network: NetworkConfig, error classes
14
- * - Sandbox: Sandbox, SandboxCommand, SandboxOptions, OutputMessage, WriteFilesInput
15
- * - Security: DefenseInDepthBox, SecurityViolationLogger, SecurityViolationError + types
16
- * - Trace: TraceEvent, TraceCallback
4
+ * Keeping this as a wildcard export guarantees this wrapper stays 1:1 with
5
+ * whatever the installed just-bash version exposes.
17
6
  */
18
-
19
- // ============================================================================
20
- // Core
21
- // ============================================================================
22
- export type { BashLogger, BashOptions, ExecOptions, ExecutionLimits } from "just-bash";
23
- export { Bash } from "just-bash";
24
-
25
- // ============================================================================
26
- // Result types
27
- // ============================================================================
28
- export type { BashExecResult, Command, CommandContext, ExecResult, IFileSystem } from "just-bash";
29
-
30
- // ============================================================================
31
- // Trace types (from upstream, not locally redefined)
32
- // ============================================================================
33
- export type { TraceCallback, TraceEvent } from "just-bash";
34
-
35
- // ============================================================================
36
- // Command registry
37
- // ============================================================================
38
- export type { AllCommandName, CommandName, NetworkCommandName, PythonCommandName } from "just-bash";
39
- export { getCommandNames, getNetworkCommandNames, getPythonCommandNames } from "just-bash";
40
-
41
- // ============================================================================
42
- // Custom commands
43
- // ============================================================================
44
- export type { CustomCommand, LazyCommand } from "just-bash";
45
- export { defineCommand } from "just-bash";
46
-
47
- // ============================================================================
48
- // Filesystem types
49
- // ============================================================================
50
- export type {
51
- BufferEncoding,
52
- CpOptions,
53
- DirectoryEntry,
54
- FileContent,
55
- FileEntry,
56
- FileInit,
57
- FileSystemFactory,
58
- FsEntry,
59
- FsStat,
60
- InitialFiles,
61
- MkdirOptions,
62
- MountableFsOptions,
63
- MountConfig,
64
- OverlayFsOptions,
65
- ReadWriteFsOptions,
66
- RmOptions,
67
- SymlinkEntry,
68
- } from "just-bash";
69
-
70
- // ============================================================================
71
- // Filesystem implementations
72
- // ============================================================================
73
- export { InMemoryFs, MountableFs, OverlayFs, ReadWriteFs } from "just-bash";
74
-
75
- // ============================================================================
76
- // Network
77
- // ============================================================================
78
- export type { NetworkConfig } from "just-bash";
79
- export {
80
- NetworkAccessDeniedError,
81
- RedirectNotAllowedError,
82
- TooManyRedirectsError,
83
- } from "just-bash";
84
-
85
- // ============================================================================
86
- // Sandbox (Vercel Sandbox compatible API)
87
- // ============================================================================
88
- export type {
89
- OutputMessage,
90
- SandboxCommandFinished,
91
- SandboxOptions,
92
- WriteFilesInput,
93
- } from "just-bash";
94
- export { Sandbox, SandboxCommand } from "just-bash";
95
-
96
- // ============================================================================
97
- // Security / Defense-in-Depth
98
- // ============================================================================
99
- export type {
100
- DefenseInDepthConfig,
101
- DefenseInDepthHandle,
102
- DefenseInDepthStats,
103
- SecurityViolation,
104
- SecurityViolationType,
105
- } from "just-bash";
106
- export {
107
- createConsoleViolationCallback,
108
- DefenseInDepthBox,
109
- SecurityViolationError,
110
- SecurityViolationLogger,
111
- } from "just-bash";
7
+ export * from "just-bash";
@@ -1,705 +0,0 @@
1
- /**
2
- * Ambient type declarations for just-bash.
3
- *
4
- * The upstream just-bash v2.9.6 ships .d.ts files but its internal
5
- * re-exports use relative .js paths (e.g., "./Bash.js", "./fs/interface.js")
6
- * that don't resolve under moduleResolution: "nodenext" because the package
7
- * bundles everything into dist/bundle/index.js. TypeScript can't follow the
8
- * type chain from the barrel index.d.ts through to the leaf .d.ts files.
9
- *
10
- * This ambient module declaration provides complete types for all public
11
- * exports of just-bash v2.9.6, derived from the upstream .d.ts sources.
12
- * It should be updated when the upstream package is bumped.
13
- */
14
-
15
- declare module "just-bash" {
16
- // ========================================================================
17
- // Trace types (from types.d.ts)
18
- // ========================================================================
19
-
20
- interface TraceEvent {
21
- category: string;
22
- name: string;
23
- durationMs: number;
24
- details?: Record<string, unknown>;
25
- }
26
-
27
- type TraceCallback = (event: TraceEvent) => void;
28
-
29
- // ========================================================================
30
- // Core result types (from types.d.ts)
31
- // ========================================================================
32
-
33
- interface ExecResult {
34
- stdout: string;
35
- stderr: string;
36
- exitCode: number;
37
- env?: Record<string, string>;
38
- }
39
-
40
- interface BashExecResult extends ExecResult {
41
- env: Record<string, string>;
42
- }
43
-
44
- interface FeatureCoverageWriter {
45
- hit(feature: string): void;
46
- }
47
-
48
- // ========================================================================
49
- // Filesystem types (from fs/interface.d.ts)
50
- // ========================================================================
51
-
52
- type BufferEncoding = "utf8" | "utf-8" | "ascii" | "binary" | "base64" | "hex" | "latin1";
53
- type FileContent = string | Uint8Array;
54
-
55
- interface ReadFileOptions {
56
- encoding?: BufferEncoding | null;
57
- }
58
- interface WriteFileOptions {
59
- encoding?: BufferEncoding;
60
- }
61
-
62
- interface FileEntry {
63
- type: "file";
64
- content: string | Uint8Array;
65
- mode: number;
66
- mtime: Date;
67
- }
68
- interface DirectoryEntry {
69
- type: "directory";
70
- mode: number;
71
- mtime: Date;
72
- }
73
- interface SymlinkEntry {
74
- type: "symlink";
75
- target: string;
76
- mode: number;
77
- mtime: Date;
78
- }
79
- type FsEntry = FileEntry | DirectoryEntry | SymlinkEntry;
80
-
81
- interface DirentEntry {
82
- name: string;
83
- isFile: boolean;
84
- isDirectory: boolean;
85
- isSymbolicLink: boolean;
86
- }
87
- interface FsStat {
88
- isFile: boolean;
89
- isDirectory: boolean;
90
- isSymbolicLink: boolean;
91
- mode: number;
92
- size: number;
93
- mtime: Date;
94
- }
95
- interface MkdirOptions {
96
- recursive?: boolean;
97
- }
98
- interface RmOptions {
99
- recursive?: boolean;
100
- force?: boolean;
101
- }
102
- interface CpOptions {
103
- recursive?: boolean;
104
- }
105
-
106
- interface IFileSystem {
107
- readFile(path: string, options?: ReadFileOptions | BufferEncoding): Promise<string>;
108
- readFileBuffer(path: string): Promise<Uint8Array>;
109
- writeFile(
110
- path: string,
111
- content: FileContent,
112
- options?: WriteFileOptions | BufferEncoding,
113
- ): Promise<void>;
114
- appendFile(
115
- path: string,
116
- content: FileContent,
117
- options?: WriteFileOptions | BufferEncoding,
118
- ): Promise<void>;
119
- exists(path: string): Promise<boolean>;
120
- stat(path: string): Promise<FsStat>;
121
- mkdir(path: string, options?: MkdirOptions): Promise<void>;
122
- readdir(path: string): Promise<string[]>;
123
- readdirWithFileTypes?(path: string): Promise<DirentEntry[]>;
124
- rm(path: string, options?: RmOptions): Promise<void>;
125
- cp(src: string, dest: string, options?: CpOptions): Promise<void>;
126
- mv(src: string, dest: string): Promise<void>;
127
- resolvePath(base: string, path: string): string;
128
- getAllPaths(): string[];
129
- chmod(path: string, mode: number): Promise<void>;
130
- symlink(target: string, linkPath: string): Promise<void>;
131
- link(existingPath: string, newPath: string): Promise<void>;
132
- readlink(path: string): Promise<string>;
133
- lstat(path: string): Promise<FsStat>;
134
- realpath(path: string): Promise<string>;
135
- utimes(path: string, atime: Date, mtime: Date): Promise<void>;
136
- }
137
-
138
- interface FileInit {
139
- content: FileContent;
140
- mode?: number;
141
- mtime?: Date;
142
- }
143
- type InitialFiles = Record<string, FileContent | FileInit>;
144
- type FileSystemFactory = (initialFiles?: InitialFiles) => IFileSystem;
145
-
146
- // ========================================================================
147
- // Execution limits (from limits.d.ts)
148
- // ========================================================================
149
-
150
- interface ExecutionLimits {
151
- maxCallDepth?: number;
152
- maxCommandCount?: number;
153
- maxLoopIterations?: number;
154
- maxAwkIterations?: number;
155
- maxSedIterations?: number;
156
- maxJqIterations?: number;
157
- maxSqliteTimeoutMs?: number;
158
- maxPythonTimeoutMs?: number;
159
- maxGlobOperations?: number;
160
- maxStringLength?: number;
161
- maxArrayElements?: number;
162
- maxHeredocSize?: number;
163
- maxSubstitutionDepth?: number;
164
- }
165
-
166
- function resolveLimits(userLimits?: ExecutionLimits): Required<ExecutionLimits>;
167
-
168
- // ========================================================================
169
- // Command types (from types.d.ts)
170
- // ========================================================================
171
-
172
- interface CommandExecOptions {
173
- env?: Record<string, string>;
174
- cwd: string;
175
- }
176
-
177
- interface CommandContext {
178
- fs: IFileSystem;
179
- cwd: string;
180
- env: Map<string, string>;
181
- exportedEnv?: Record<string, string>;
182
- stdin: string;
183
- limits?: Required<ExecutionLimits>;
184
- trace?: TraceCallback;
185
- exec?: (command: string, options: CommandExecOptions) => Promise<ExecResult>;
186
- fetch?: SecureFetch;
187
- getRegisteredCommands?: () => string[];
188
- sleep?: (ms: number) => Promise<void>;
189
- fileDescriptors?: Map<number, string>;
190
- xpgEcho?: boolean;
191
- substitutionDepth?: number;
192
- coverage?: FeatureCoverageWriter;
193
- }
194
-
195
- interface Command {
196
- name: string;
197
- execute(args: string[], ctx: CommandContext): Promise<ExecResult>;
198
- }
199
-
200
- type CommandRegistry = Map<string, Command>;
201
-
202
- // ========================================================================
203
- // Command registry (from commands/registry.d.ts)
204
- // ========================================================================
205
-
206
- type CommandName =
207
- | "echo"
208
- | "cat"
209
- | "printf"
210
- | "ls"
211
- | "mkdir"
212
- | "rmdir"
213
- | "touch"
214
- | "rm"
215
- | "cp"
216
- | "mv"
217
- | "ln"
218
- | "chmod"
219
- | "pwd"
220
- | "readlink"
221
- | "head"
222
- | "tail"
223
- | "wc"
224
- | "stat"
225
- | "grep"
226
- | "fgrep"
227
- | "egrep"
228
- | "rg"
229
- | "sed"
230
- | "awk"
231
- | "sort"
232
- | "uniq"
233
- | "comm"
234
- | "cut"
235
- | "paste"
236
- | "tr"
237
- | "rev"
238
- | "nl"
239
- | "fold"
240
- | "expand"
241
- | "unexpand"
242
- | "strings"
243
- | "split"
244
- | "column"
245
- | "join"
246
- | "tee"
247
- | "find"
248
- | "basename"
249
- | "dirname"
250
- | "tree"
251
- | "du"
252
- | "env"
253
- | "printenv"
254
- | "alias"
255
- | "unalias"
256
- | "history"
257
- | "xargs"
258
- | "true"
259
- | "false"
260
- | "clear"
261
- | "bash"
262
- | "sh"
263
- | "jq"
264
- | "base64"
265
- | "diff"
266
- | "date"
267
- | "sleep"
268
- | "timeout"
269
- | "seq"
270
- | "expr"
271
- | "md5sum"
272
- | "sha1sum"
273
- | "sha256sum"
274
- | "file"
275
- | "html-to-markdown"
276
- | "help"
277
- | "which"
278
- | "tac"
279
- | "hostname"
280
- | "od"
281
- | "gzip"
282
- | "gunzip"
283
- | "zcat"
284
- | "tar"
285
- | "yq"
286
- | "xan"
287
- | "sqlite3"
288
- | "time"
289
- | "whoami";
290
-
291
- type NetworkCommandName = "curl";
292
- type PythonCommandName = "python3" | "python";
293
- type AllCommandName = CommandName | NetworkCommandName | PythonCommandName;
294
-
295
- function getCommandNames(): string[];
296
- function getNetworkCommandNames(): string[];
297
- function getPythonCommandNames(): string[];
298
-
299
- // ========================================================================
300
- // Network types (from network/types.d.ts)
301
- // ========================================================================
302
-
303
- type HttpMethod = "GET" | "HEAD" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS";
304
-
305
- interface NetworkConfig {
306
- allowedUrlPrefixes?: string[];
307
- allowedMethods?: HttpMethod[];
308
- dangerouslyAllowFullInternetAccess?: boolean;
309
- maxRedirects?: number;
310
- timeoutMs?: number;
311
- maxResponseSize?: number;
312
- }
313
-
314
- interface FetchResult {
315
- status: number;
316
- statusText: string;
317
- headers: Record<string, string>;
318
- body: string;
319
- url: string;
320
- }
321
-
322
- interface SecureFetchOptions {
323
- method?: string;
324
- headers?: Record<string, string>;
325
- body?: string;
326
- followRedirects?: boolean;
327
- timeoutMs?: number;
328
- }
329
-
330
- type SecureFetch = (url: string, options?: SecureFetchOptions) => Promise<FetchResult>;
331
-
332
- function createSecureFetch(config: NetworkConfig): SecureFetch;
333
-
334
- class NetworkAccessDeniedError extends Error {
335
- constructor(url: string);
336
- }
337
- class TooManyRedirectsError extends Error {
338
- constructor(maxRedirects: number);
339
- }
340
- class RedirectNotAllowedError extends Error {
341
- constructor(url: string);
342
- }
343
-
344
- // ========================================================================
345
- // Custom commands (from custom-commands.d.ts)
346
- // ========================================================================
347
-
348
- type CustomCommand = Command | LazyCommand;
349
-
350
- interface LazyCommand {
351
- name: string;
352
- load: () => Promise<Command>;
353
- }
354
-
355
- function isLazyCommand(cmd: CustomCommand): cmd is LazyCommand;
356
- function defineCommand(
357
- name: string,
358
- execute: (args: string[], ctx: CommandContext) => Promise<ExecResult>,
359
- ): Command;
360
- function createLazyCustomCommand(lazy: LazyCommand): Command;
361
-
362
- // ========================================================================
363
- // Bash class (from Bash.d.ts)
364
- // ========================================================================
365
-
366
- interface BashLogger {
367
- info(message: string, data?: Record<string, unknown>): void;
368
- debug(message: string, data?: Record<string, unknown>): void;
369
- }
370
-
371
- interface BashOptions {
372
- files?: InitialFiles;
373
- env?: Record<string, string>;
374
- cwd?: string;
375
- fs?: IFileSystem;
376
- executionLimits?: ExecutionLimits;
377
- /** @deprecated Use executionLimits.maxCallDepth instead */
378
- maxCallDepth?: number;
379
- /** @deprecated Use executionLimits.maxCommandCount instead */
380
- maxCommandCount?: number;
381
- /** @deprecated Use executionLimits.maxLoopIterations instead */
382
- maxLoopIterations?: number;
383
- network?: NetworkConfig;
384
- python?: boolean;
385
- commands?: CommandName[];
386
- sleep?: (ms: number) => Promise<void>;
387
- customCommands?: CustomCommand[];
388
- logger?: BashLogger;
389
- trace?: TraceCallback;
390
- defenseInDepth?: DefenseInDepthConfig | boolean;
391
- coverage?: FeatureCoverageWriter;
392
- }
393
-
394
- interface ExecOptions {
395
- env?: Record<string, string>;
396
- cwd?: string;
397
- rawScript?: boolean;
398
- }
399
-
400
- class Bash {
401
- readonly fs: IFileSystem;
402
- constructor(options?: BashOptions);
403
- registerCommand(command: Command): void;
404
- exec(commandLine: string, options?: ExecOptions): Promise<BashExecResult>;
405
- readFile(path: string): Promise<string>;
406
- writeFile(path: string, content: string): Promise<void>;
407
- getCwd(): string;
408
- getEnv(): Record<string, string>;
409
- }
410
-
411
- // ========================================================================
412
- // Filesystem implementations
413
- // ========================================================================
414
-
415
- class InMemoryFs implements IFileSystem {
416
- constructor(initialFiles?: InitialFiles);
417
- writeFileSync(
418
- path: string,
419
- content: FileContent,
420
- options?: WriteFileOptions | BufferEncoding,
421
- metadata?: { mode?: number; mtime?: Date },
422
- ): void;
423
- mkdirSync(path: string, options?: MkdirOptions): void;
424
- readFile(path: string, options?: ReadFileOptions | BufferEncoding): Promise<string>;
425
- readFileBuffer(path: string): Promise<Uint8Array>;
426
- writeFile(
427
- path: string,
428
- content: FileContent,
429
- options?: WriteFileOptions | BufferEncoding,
430
- ): Promise<void>;
431
- appendFile(
432
- path: string,
433
- content: FileContent,
434
- options?: WriteFileOptions | BufferEncoding,
435
- ): Promise<void>;
436
- exists(path: string): Promise<boolean>;
437
- stat(path: string): Promise<FsStat>;
438
- lstat(path: string): Promise<FsStat>;
439
- mkdir(path: string, options?: MkdirOptions): Promise<void>;
440
- readdir(path: string): Promise<string[]>;
441
- readdirWithFileTypes(path: string): Promise<DirentEntry[]>;
442
- rm(path: string, options?: RmOptions): Promise<void>;
443
- cp(src: string, dest: string, options?: CpOptions): Promise<void>;
444
- mv(src: string, dest: string): Promise<void>;
445
- getAllPaths(): string[];
446
- resolvePath(base: string, path: string): string;
447
- chmod(path: string, mode: number): Promise<void>;
448
- symlink(target: string, linkPath: string): Promise<void>;
449
- link(existingPath: string, newPath: string): Promise<void>;
450
- readlink(path: string): Promise<string>;
451
- realpath(path: string): Promise<string>;
452
- utimes(path: string, atime: Date, mtime: Date): Promise<void>;
453
- }
454
-
455
- interface OverlayFsOptions {
456
- root: string;
457
- mountPoint?: string;
458
- readOnly?: boolean;
459
- maxFileReadSize?: number;
460
- }
461
-
462
- class OverlayFs implements IFileSystem {
463
- constructor(options: OverlayFsOptions);
464
- getMountPoint(): string;
465
- mkdirSync(path: string, options?: MkdirOptions): void;
466
- writeFileSync(path: string, content: string | Uint8Array): void;
467
- readFile(path: string, options?: ReadFileOptions | BufferEncoding): Promise<string>;
468
- readFileBuffer(path: string): Promise<Uint8Array>;
469
- writeFile(
470
- path: string,
471
- content: FileContent,
472
- options?: WriteFileOptions | BufferEncoding,
473
- ): Promise<void>;
474
- appendFile(
475
- path: string,
476
- content: FileContent,
477
- options?: WriteFileOptions | BufferEncoding,
478
- ): Promise<void>;
479
- exists(path: string): Promise<boolean>;
480
- stat(path: string): Promise<FsStat>;
481
- lstat(path: string): Promise<FsStat>;
482
- mkdir(path: string, options?: MkdirOptions): Promise<void>;
483
- readdir(path: string): Promise<string[]>;
484
- readdirWithFileTypes(path: string): Promise<DirentEntry[]>;
485
- rm(path: string, options?: RmOptions): Promise<void>;
486
- cp(src: string, dest: string, options?: CpOptions): Promise<void>;
487
- mv(src: string, dest: string): Promise<void>;
488
- resolvePath(base: string, path: string): string;
489
- getAllPaths(): string[];
490
- chmod(path: string, mode: number): Promise<void>;
491
- symlink(target: string, linkPath: string): Promise<void>;
492
- link(existingPath: string, newPath: string): Promise<void>;
493
- readlink(path: string): Promise<string>;
494
- realpath(path: string): Promise<string>;
495
- utimes(path: string, atime: Date, mtime: Date): Promise<void>;
496
- }
497
-
498
- interface ReadWriteFsOptions {
499
- root: string;
500
- maxFileReadSize?: number;
501
- }
502
-
503
- class ReadWriteFs implements IFileSystem {
504
- constructor(options: ReadWriteFsOptions);
505
- readFile(path: string, options?: ReadFileOptions | BufferEncoding): Promise<string>;
506
- readFileBuffer(path: string): Promise<Uint8Array>;
507
- writeFile(
508
- path: string,
509
- content: FileContent,
510
- options?: WriteFileOptions | BufferEncoding,
511
- ): Promise<void>;
512
- appendFile(
513
- path: string,
514
- content: FileContent,
515
- options?: WriteFileOptions | BufferEncoding,
516
- ): Promise<void>;
517
- exists(path: string): Promise<boolean>;
518
- stat(path: string): Promise<FsStat>;
519
- lstat(path: string): Promise<FsStat>;
520
- mkdir(path: string, options?: MkdirOptions): Promise<void>;
521
- readdir(path: string): Promise<string[]>;
522
- readdirWithFileTypes(path: string): Promise<DirentEntry[]>;
523
- rm(path: string, options?: RmOptions): Promise<void>;
524
- cp(src: string, dest: string, options?: CpOptions): Promise<void>;
525
- mv(src: string, dest: string): Promise<void>;
526
- resolvePath(base: string, path: string): string;
527
- getAllPaths(): string[];
528
- chmod(path: string, mode: number): Promise<void>;
529
- symlink(target: string, linkPath: string): Promise<void>;
530
- link(existingPath: string, newPath: string): Promise<void>;
531
- readlink(path: string): Promise<string>;
532
- realpath(path: string): Promise<string>;
533
- utimes(path: string, atime: Date, mtime: Date): Promise<void>;
534
- }
535
-
536
- interface MountConfig {
537
- mountPoint: string;
538
- filesystem: IFileSystem;
539
- }
540
-
541
- interface MountableFsOptions {
542
- base?: IFileSystem;
543
- mounts?: MountConfig[];
544
- }
545
-
546
- class MountableFs implements IFileSystem {
547
- constructor(options?: MountableFsOptions);
548
- mount(mountPoint: string, filesystem: IFileSystem): void;
549
- unmount(mountPoint: string): void;
550
- getMounts(): ReadonlyArray<{ mountPoint: string; filesystem: IFileSystem }>;
551
- isMountPoint(path: string): boolean;
552
- readFile(path: string, options?: ReadFileOptions | BufferEncoding): Promise<string>;
553
- readFileBuffer(path: string): Promise<Uint8Array>;
554
- writeFile(
555
- path: string,
556
- content: FileContent,
557
- options?: WriteFileOptions | BufferEncoding,
558
- ): Promise<void>;
559
- appendFile(
560
- path: string,
561
- content: FileContent,
562
- options?: WriteFileOptions | BufferEncoding,
563
- ): Promise<void>;
564
- exists(path: string): Promise<boolean>;
565
- stat(path: string): Promise<FsStat>;
566
- lstat(path: string): Promise<FsStat>;
567
- mkdir(path: string, options?: MkdirOptions): Promise<void>;
568
- readdir(path: string): Promise<string[]>;
569
- rm(path: string, options?: RmOptions): Promise<void>;
570
- cp(src: string, dest: string, options?: CpOptions): Promise<void>;
571
- mv(src: string, dest: string): Promise<void>;
572
- resolvePath(base: string, path: string): string;
573
- getAllPaths(): string[];
574
- chmod(path: string, mode: number): Promise<void>;
575
- symlink(target: string, linkPath: string): Promise<void>;
576
- link(existingPath: string, newPath: string): Promise<void>;
577
- readlink(path: string): Promise<string>;
578
- realpath(path: string): Promise<string>;
579
- utimes(path: string, atime: Date, mtime: Date): Promise<void>;
580
- }
581
-
582
- // ========================================================================
583
- // Sandbox (from sandbox/)
584
- // ========================================================================
585
-
586
- interface OutputMessage {
587
- type: "stdout" | "stderr";
588
- data: string;
589
- timestamp: Date;
590
- }
591
-
592
- class SandboxCommand {
593
- readonly cmdId: string;
594
- readonly cwd: string;
595
- readonly startedAt: Date;
596
- exitCode: number | undefined;
597
- logs(): AsyncGenerator<OutputMessage, void, unknown>;
598
- wait(): Promise<SandboxCommandFinished>;
599
- output(): Promise<string>;
600
- stdout(): Promise<string>;
601
- stderr(): Promise<string>;
602
- kill(): Promise<void>;
603
- }
604
-
605
- interface SandboxCommandFinished extends SandboxCommand {
606
- exitCode: number;
607
- }
608
-
609
- interface SandboxOptions {
610
- cwd?: string;
611
- env?: Record<string, string>;
612
- timeoutMs?: number;
613
- fs?: IFileSystem;
614
- overlayRoot?: string;
615
- maxCallDepth?: number;
616
- maxCommandCount?: number;
617
- maxLoopIterations?: number;
618
- network?: NetworkConfig;
619
- }
620
-
621
- interface WriteFilesInput {
622
- [path: string]:
623
- | string
624
- | {
625
- content: string;
626
- encoding?: "utf-8" | "base64";
627
- };
628
- }
629
-
630
- class Sandbox {
631
- static create(opts?: SandboxOptions): Promise<Sandbox>;
632
- runCommand(
633
- cmd: string,
634
- opts?: { cwd?: string; env?: Record<string, string> },
635
- ): Promise<SandboxCommand>;
636
- writeFiles(files: WriteFilesInput): Promise<void>;
637
- readFile(path: string, encoding?: "utf-8" | "base64"): Promise<string>;
638
- mkDir(path: string, opts?: { recursive?: boolean }): Promise<void>;
639
- stop(): Promise<void>;
640
- extendTimeout(ms: number): Promise<void>;
641
- get domain(): string | undefined;
642
- get bashEnvInstance(): Bash;
643
- }
644
-
645
- // ========================================================================
646
- // Security / Defense-in-Depth
647
- // ========================================================================
648
-
649
- type SecurityViolationType = string;
650
-
651
- interface SecurityViolation {
652
- type: SecurityViolationType;
653
- target: string;
654
- details: string;
655
- }
656
-
657
- interface DefenseInDepthConfig {
658
- enabled?: boolean;
659
- auditMode?: boolean;
660
- onViolation?: (violation: SecurityViolation) => void;
661
- }
662
-
663
- interface DefenseInDepthHandle {
664
- run<T>(fn: () => T): T;
665
- deactivate(): void;
666
- executionId: string;
667
- }
668
-
669
- interface DefenseInDepthStats {
670
- violationsBlocked: number;
671
- violations: SecurityViolation[];
672
- activeTimeMs: number;
673
- refCount: number;
674
- }
675
-
676
- class DefenseInDepthBox {
677
- constructor(config: DefenseInDepthConfig);
678
- updateConfig(config: DefenseInDepthConfig): void;
679
- activate(): DefenseInDepthHandle;
680
- forceDeactivate(): void;
681
- isActive(): boolean;
682
- getStats(): DefenseInDepthStats;
683
- clearViolations(): void;
684
- }
685
-
686
- class SecurityViolationError extends Error {
687
- violation: SecurityViolation;
688
- name: "SecurityViolationError";
689
- constructor(message: string);
690
- }
691
-
692
- class SecurityViolationLogger {
693
- constructor();
694
- record(violation: SecurityViolation): void;
695
- getViolations(): SecurityViolation[];
696
- getViolationsByType(type: SecurityViolationType): SecurityViolation[];
697
- getSummary(): Array<{ type: string; count: number }>;
698
- getTotalCount(): number;
699
- hasViolations(): boolean;
700
- clear(): void;
701
- createCallback(): (violation: SecurityViolation) => void;
702
- }
703
-
704
- function createConsoleViolationCallback(): (violation: SecurityViolation) => void;
705
- }