just-bash-mcp 2.7.0 → 2.9.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.
Files changed (49) hide show
  1. package/README.md +58 -4
  2. package/package.json +24 -22
  3. package/src/config/index.ts +402 -0
  4. package/{build/index.js → src/index.ts} +12 -6
  5. package/src/just-bash-security.d.ts +705 -0
  6. package/src/tools/bash-instance.ts +212 -0
  7. package/src/tools/exec-tools.ts +165 -0
  8. package/src/tools/file-tools.ts +206 -0
  9. package/src/tools/index.ts +45 -0
  10. package/src/tools/info-tools.ts +175 -0
  11. package/src/tools/sandbox-tools.ts +217 -0
  12. package/src/types.ts +111 -0
  13. package/src/utils/index.ts +84 -0
  14. package/tsconfig.json +18 -0
  15. package/build/config/index.d.ts +0 -79
  16. package/build/config/index.d.ts.map +0 -1
  17. package/build/config/index.js +0 -178
  18. package/build/config/index.js.map +0 -1
  19. package/build/index.d.ts +0 -12
  20. package/build/index.d.ts.map +0 -1
  21. package/build/index.js.map +0 -1
  22. package/build/tools/bash-instance.d.ts +0 -26
  23. package/build/tools/bash-instance.d.ts.map +0 -1
  24. package/build/tools/bash-instance.js +0 -106
  25. package/build/tools/bash-instance.js.map +0 -1
  26. package/build/tools/exec-tools.d.ts +0 -10
  27. package/build/tools/exec-tools.d.ts.map +0 -1
  28. package/build/tools/exec-tools.js +0 -98
  29. package/build/tools/exec-tools.js.map +0 -1
  30. package/build/tools/file-tools.d.ts +0 -10
  31. package/build/tools/file-tools.d.ts.map +0 -1
  32. package/build/tools/file-tools.js +0 -171
  33. package/build/tools/file-tools.js.map +0 -1
  34. package/build/tools/index.d.ts +0 -15
  35. package/build/tools/index.d.ts.map +0 -1
  36. package/build/tools/index.js +0 -29
  37. package/build/tools/index.js.map +0 -1
  38. package/build/tools/info-tools.d.ts +0 -10
  39. package/build/tools/info-tools.d.ts.map +0 -1
  40. package/build/tools/info-tools.js +0 -95
  41. package/build/tools/info-tools.js.map +0 -1
  42. package/build/tools/sandbox-tools.d.ts +0 -10
  43. package/build/tools/sandbox-tools.d.ts.map +0 -1
  44. package/build/tools/sandbox-tools.js +0 -124
  45. package/build/tools/sandbox-tools.js.map +0 -1
  46. package/build/utils/index.d.ts +0 -52
  47. package/build/utils/index.d.ts.map +0 -1
  48. package/build/utils/index.js +0 -56
  49. package/build/utils/index.js.map +0 -1
package/README.md CHANGED
@@ -7,15 +7,20 @@ 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.5.2.
10
+ Built on top of [`just-bash`](https://github.com/vercel-labs/just-bash) v2.9.6.
11
11
 
12
- ## What's New in v2.1.0
12
+ ## What's New in v2.8.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
15
+ - **Defense-in-depth mode** - Opt-in monkey-patching of dangerous JS globals (`JUST_BASH_DEFENSE_IN_DEPTH=true`)
16
+ - **Python support** - Python3 via Pyodide (`JUST_BASH_ENABLE_PYTHON=true`)
17
+ - **Vercel Sandbox API** - Compatible `bash_sandbox_*` tools for isolated execution
18
+ - **oxlint/oxfmt toolchain** - Replaced tsc/biome with faster oxlint and oxfmt
19
+ - **Configurable limits** - Fine-grained control over glob ops, string length, array size, heredoc size, and more
14
20
  - **`rg` (ripgrep)** - Fast regex search with `--files`, `-d`, `--stats`, `-t markdown`
15
21
  - **`tar`** - Archive support with compression
16
22
  - **MountableFS** - Mount multiple filesystems at different paths
17
23
  - **ReadWriteFS** - Direct read-write access to real directories
18
- - **Multi-level glob patterns** - Improved `**/*.ts` style matching
19
24
 
20
25
  ## Features
21
26
 
@@ -120,6 +125,16 @@ Add to your MCP settings:
120
125
  | `JUST_BASH_MAX_CALL_DEPTH` | Maximum function recursion depth | `100` |
121
126
  | `JUST_BASH_MAX_COMMAND_COUNT` | Maximum total commands per execution | `10000` |
122
127
  | `JUST_BASH_MAX_LOOP_ITERATIONS` | Maximum iterations per loop | `10000` |
128
+ | `JUST_BASH_ENABLE_PYTHON` | Enable Python3 via Pyodide (`true`/`false`) | `false` |
129
+ | `JUST_BASH_DEFENSE_IN_DEPTH` | Enable defense-in-depth mode (`true`/`false`) | `false` |
130
+ | `JUST_BASH_DEFENSE_IN_DEPTH_AUDIT` | Audit mode: log violations but don't block | `false` |
131
+ | `JUST_BASH_DEFENSE_IN_DEPTH_LOG` | Log violations to console | `false` |
132
+ | `JUST_BASH_OVERLAY_READ_ONLY` | OverlayFS read-only mode | `false` |
133
+ | `JUST_BASH_MAX_RESPONSE_SIZE` | Max network response body size (bytes) | `10485760` |
134
+ | `JUST_BASH_MAX_FILE_READ_SIZE` | Max file read size for OverlayFs/ReadWriteFs | `10485760` |
135
+ | `JUST_BASH_ALLOWED_COMMANDS` | Comma-separated command allow-list | all |
136
+ | `JUST_BASH_ENABLE_LOGGING` | Enable execution logging | `false` |
137
+ | `JUST_BASH_ENABLE_TRACING` | Enable performance tracing | `false` |
123
138
 
124
139
  ## Tools
125
140
 
@@ -149,9 +164,28 @@ Reset the persistent bash environment, clearing all files and state.
149
164
 
150
165
  File operations in the persistent environment.
151
166
 
167
+ ### `bash_direct_read` / `bash_direct_write`
168
+
169
+ Direct filesystem read/write operations (bypass shell execution).
170
+
152
171
  ### `bash_info`
153
172
 
154
- Get information about the bash environment configuration.
173
+ Get information about the bash environment configuration, including defense-in-depth violation stats.
174
+
175
+ ### `bash_get_cwd` / `bash_get_env`
176
+
177
+ Get current working directory or environment variables.
178
+
179
+ ### Vercel Sandbox API
180
+
181
+ Compatible with the Vercel Sandbox API:
182
+
183
+ - `bash_sandbox_run` - Run a command in the sandbox
184
+ - `bash_sandbox_write_files` - Write multiple files at once
185
+ - `bash_sandbox_read_file` - Read a file (supports base64 encoding)
186
+ - `bash_sandbox_mkdir` - Create a directory
187
+ - `bash_sandbox_stop` - Stop and clean up the sandbox
188
+ - `bash_sandbox_reset` - Reset the sandbox state
155
189
 
156
190
  ## Supported Commands
157
191
 
@@ -235,6 +269,26 @@ Get information about the bash environment configuration.
235
269
  - Execution limits protect against infinite loops and recursion
236
270
  - No binary/WASM execution
237
271
  - Network disabled by default; when enabled, URL and method allow-lists enforced
272
+ - **Defense-in-depth mode** (opt-in): Monkey-patches dangerous JS globals (`Function`, `eval`, `setTimeout`, `process`, etc.) during script execution to block escape vectors
273
+ - **SecurityViolationLogger**: Tracks all defense-in-depth violations with full stats accessible via `bash_info`
274
+ - **Rich network error classification**: `NetworkAccessDeniedError`, `TooManyRedirectsError`, `RedirectNotAllowedError` for precise error messages
275
+
276
+ ## Upstream API Coverage
277
+
278
+ This wrapper integrates the full public API surface of `just-bash` v2.9.6:
279
+
280
+ | Category | Exports Used |
281
+ |----------|-------------|
282
+ | Core | `Bash`, `BashOptions`, `ExecOptions`, `BashExecResult` |
283
+ | Commands | `CommandName`, `AllCommandName`, `getCommandNames`, `getNetworkCommandNames`, `getPythonCommandNames` |
284
+ | Custom Commands | `defineCommand`, `CustomCommand`, `LazyCommand` |
285
+ | Filesystem | `InMemoryFs`, `OverlayFs`, `ReadWriteFs`, `MountableFs`, `IFileSystem` |
286
+ | Network | `NetworkConfig`, `NetworkAccessDeniedError`, `TooManyRedirectsError`, `RedirectNotAllowedError` |
287
+ | Sandbox | `Sandbox`, `SandboxCommand`, `SandboxOptions`, `OutputMessage` |
288
+ | Security | `DefenseInDepthBox`, `SecurityViolationLogger`, `SecurityViolationError`, `createConsoleViolationCallback` |
289
+ | Trace | `TraceCallback`, `TraceEvent` |
290
+
291
+ All types are re-exported from `src/types.ts` for downstream consumers.
238
292
 
239
293
  ## License
240
294
 
package/package.json CHANGED
@@ -1,33 +1,33 @@
1
1
  {
2
2
  "name": "just-bash-mcp",
3
- "version": "2.7.0",
3
+ "version": "2.9.0",
4
4
  "description": "MCP server providing a sandboxed bash environment using just-bash",
5
5
  "type": "module",
6
- "main": "./build/index.js",
7
- "types": "./build/index.d.ts",
6
+ "main": "./src/index.ts",
8
7
  "exports": {
9
8
  ".": {
10
- "types": "./build/index.d.ts",
11
- "import": "./build/index.js"
9
+ "import": "./src/index.ts"
12
10
  }
13
11
  },
14
12
  "bin": {
15
- "just-bash-mcp": "build/index.js"
13
+ "just-bash-mcp": "src/index.ts"
16
14
  },
17
15
  "files": [
18
- "build",
16
+ "src",
17
+ "tsconfig.json",
19
18
  "README.md",
20
19
  "LICENSE"
21
20
  ],
22
21
  "scripts": {
23
- "build": "tsc",
24
- "start": "node build/index.js",
25
- "dev": "bun src/index.ts",
26
- "typecheck": "bun tsc --noEmit",
27
- "lint": "bunx @biomejs/biome@latest lint",
28
- "format": "bunx @biomejs/biome@latest format --write",
29
- "check": "bunx @biomejs/biome@latest check --write",
30
- "prepublishOnly": "bun run build"
22
+ "start": "node src/index.ts",
23
+ "dev": "node --watch src/index.ts",
24
+ "lint": "oxlint --type-aware",
25
+ "lint:fix": "oxlint --type-aware --fix",
26
+ "typecheck": "oxlint --type-aware --type-check",
27
+ "format": "oxfmt --write src/",
28
+ "format:check": "oxfmt --check src/",
29
+ "check": "oxlint --type-aware --type-check && oxfmt --check src/",
30
+ "ci": "oxlint --type-aware --type-check && oxfmt --check src/"
31
31
  },
32
32
  "keywords": [
33
33
  "mcp",
@@ -56,16 +56,18 @@
56
56
  },
57
57
  "homepage": "https://github.com/dalist1/just-bash-mcp#readme",
58
58
  "engines": {
59
- "node": ">=18.0.0"
59
+ "node": ">=22.0.0"
60
60
  },
61
+ "packageManager": "bun@1.3.8",
61
62
  "dependencies": {
62
- "@modelcontextprotocol/sdk": "^1.25.2",
63
- "just-bash": "^2.7.0",
64
- "zod": "^4.3.5"
63
+ "@modelcontextprotocol/sdk": "^1.26.0",
64
+ "just-bash": "^2.9.6",
65
+ "zod": "^4.3.6"
65
66
  },
66
67
  "devDependencies": {
67
- "@biomejs/biome": "^2.3.11",
68
- "@types/node": "^25.0.6",
69
- "typescript": "^5.9.3"
68
+ "@types/node": "^25.2.2",
69
+ "oxfmt": "^0.28.0",
70
+ "oxlint": "^1.43.0",
71
+ "oxlint-tsgolint": "^0.11.5"
70
72
  }
71
73
  }
@@ -0,0 +1,402 @@
1
+ /**
2
+ * Configuration module for just-bash-mcp
3
+ * Handles environment variable parsing and configuration building
4
+ */
5
+
6
+ import {
7
+ type BashLogger,
8
+ type BashOptions,
9
+ type CommandName,
10
+ type DefenseInDepthConfig,
11
+ type MountConfig,
12
+ type NetworkConfig,
13
+ type TraceCallback,
14
+ type TraceEvent,
15
+ OverlayFs,
16
+ ReadWriteFs,
17
+ SecurityViolationLogger,
18
+ createConsoleViolationCallback,
19
+ } from "just-bash";
20
+
21
+ // Re-export upstream types used by other modules
22
+ export type { DefenseInDepthConfig, TraceCallback, TraceEvent };
23
+
24
+ // ============================================================================
25
+ // Types
26
+ // ============================================================================
27
+
28
+ export type HttpMethod = "GET" | "HEAD" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS";
29
+
30
+ // ============================================================================
31
+ // Environment Variable Parsing
32
+ // ============================================================================
33
+
34
+ function parseEnvString(key: string, defaultValue: string): string {
35
+ return process.env[key] || defaultValue;
36
+ }
37
+
38
+ function parseEnvBoolean(key: string, defaultValue: boolean): boolean {
39
+ return process.env[key] === "true" ? true : defaultValue;
40
+ }
41
+
42
+ function parseEnvInt(key: string, defaultValue: number): number {
43
+ const value = process.env[key];
44
+ if (!value) return defaultValue;
45
+ const parsed = Number.parseInt(value, 10);
46
+ return Number.isNaN(parsed) ? defaultValue : parsed;
47
+ }
48
+
49
+ function parseEnvStringArray(key: string): string[] {
50
+ return process.env[key]?.split(",").filter(Boolean) || [];
51
+ }
52
+
53
+ // ============================================================================
54
+ // Configuration Constants
55
+ // ============================================================================
56
+
57
+ export interface Config {
58
+ readonly VERSION: string;
59
+ readonly SERVER_NAME: string;
60
+ readonly OVERLAY_ROOT: string | undefined;
61
+ readonly READ_WRITE_ROOT: string | undefined;
62
+ readonly MOUNTS_CONFIG: string | undefined;
63
+ readonly INITIAL_CWD: string;
64
+ readonly ALLOW_NETWORK: boolean;
65
+ readonly ALLOWED_URL_PREFIXES: string[];
66
+ readonly ALLOWED_METHODS: HttpMethod[];
67
+ readonly MAX_REDIRECTS: number;
68
+ readonly NETWORK_TIMEOUT_MS: number;
69
+ readonly MAX_RESPONSE_SIZE: number | undefined;
70
+ readonly MAX_CALL_DEPTH: number;
71
+ readonly MAX_COMMAND_COUNT: number;
72
+ readonly MAX_LOOP_ITERATIONS: number;
73
+ readonly MAX_AWK_ITERATIONS: number;
74
+ readonly MAX_SED_ITERATIONS: number;
75
+ readonly MAX_JQ_ITERATIONS: number;
76
+ readonly MAX_GLOB_OPERATIONS: number;
77
+ readonly MAX_STRING_LENGTH: number;
78
+ readonly MAX_ARRAY_ELEMENTS: number;
79
+ readonly MAX_HEREDOC_SIZE: number;
80
+ readonly MAX_SUBSTITUTION_DEPTH: number;
81
+ readonly MAX_SQLITE_TIMEOUT_MS: number;
82
+ readonly MAX_PYTHON_TIMEOUT_MS: number;
83
+ readonly MAX_OUTPUT_LENGTH: number;
84
+ readonly MAX_FILE_READ_SIZE: number | undefined;
85
+ readonly ENABLE_LOGGING: boolean;
86
+ readonly ENABLE_TRACING: boolean;
87
+ readonly ENABLE_PYTHON: boolean;
88
+ readonly ENABLE_DEFENSE_IN_DEPTH: boolean;
89
+ readonly DEFENSE_IN_DEPTH_AUDIT: boolean;
90
+ readonly DEFENSE_IN_DEPTH_LOG: boolean;
91
+ readonly OVERLAY_READ_ONLY: boolean;
92
+ readonly ALLOWED_COMMANDS: CommandName[] | undefined;
93
+ }
94
+
95
+ function getAllowedMethods(): HttpMethod[] {
96
+ const methods = parseEnvStringArray("JUST_BASH_ALLOWED_METHODS");
97
+ return methods.length > 0 ? (methods as HttpMethod[]) : ["GET", "HEAD"];
98
+ }
99
+
100
+ function getAllowedCommands(): CommandName[] | undefined {
101
+ const commands = parseEnvStringArray("JUST_BASH_ALLOWED_COMMANDS");
102
+ return commands.length > 0 ? (commands as CommandName[]) : undefined;
103
+ }
104
+
105
+ function parseEnvOptionalInt(key: string): number | undefined {
106
+ const value = process.env[key];
107
+ if (!value) return undefined;
108
+ const parsed = Number.parseInt(value, 10);
109
+ return Number.isNaN(parsed) ? undefined : parsed;
110
+ }
111
+
112
+ export const config: Config = {
113
+ // Server info
114
+ VERSION: "2.8.0",
115
+ SERVER_NAME: "just-bash-mcp",
116
+
117
+ // Filesystem configuration
118
+ OVERLAY_ROOT: process.env.JUST_BASH_OVERLAY_ROOT,
119
+ READ_WRITE_ROOT: process.env.JUST_BASH_READ_WRITE_ROOT,
120
+ MOUNTS_CONFIG: process.env.JUST_BASH_MOUNTS,
121
+ INITIAL_CWD: parseEnvString("JUST_BASH_CWD", "/home/user"),
122
+
123
+ // Network configuration
124
+ ALLOW_NETWORK: parseEnvBoolean("JUST_BASH_ALLOW_NETWORK", false),
125
+ ALLOWED_URL_PREFIXES: parseEnvStringArray("JUST_BASH_ALLOWED_URLS"),
126
+ ALLOWED_METHODS: getAllowedMethods(),
127
+ MAX_REDIRECTS: parseEnvInt("JUST_BASH_MAX_REDIRECTS", 20),
128
+ NETWORK_TIMEOUT_MS: parseEnvInt("JUST_BASH_NETWORK_TIMEOUT_MS", 30000),
129
+ MAX_RESPONSE_SIZE: parseEnvOptionalInt("JUST_BASH_MAX_RESPONSE_SIZE"),
130
+
131
+ // Execution limits
132
+ MAX_CALL_DEPTH: parseEnvInt("JUST_BASH_MAX_CALL_DEPTH", 100),
133
+ MAX_COMMAND_COUNT: parseEnvInt("JUST_BASH_MAX_COMMAND_COUNT", 10000),
134
+ MAX_LOOP_ITERATIONS: parseEnvInt("JUST_BASH_MAX_LOOP_ITERATIONS", 10000),
135
+ MAX_AWK_ITERATIONS: parseEnvInt("JUST_BASH_MAX_AWK_ITERATIONS", 10000),
136
+ MAX_SED_ITERATIONS: parseEnvInt("JUST_BASH_MAX_SED_ITERATIONS", 10000),
137
+ MAX_JQ_ITERATIONS: parseEnvInt("JUST_BASH_MAX_JQ_ITERATIONS", 10000),
138
+ MAX_GLOB_OPERATIONS: parseEnvInt("JUST_BASH_MAX_GLOB_OPERATIONS", 100000),
139
+ MAX_STRING_LENGTH: parseEnvInt("JUST_BASH_MAX_STRING_LENGTH", 10485760),
140
+ MAX_ARRAY_ELEMENTS: parseEnvInt("JUST_BASH_MAX_ARRAY_ELEMENTS", 100000),
141
+ MAX_HEREDOC_SIZE: parseEnvInt("JUST_BASH_MAX_HEREDOC_SIZE", 10485760),
142
+ MAX_SUBSTITUTION_DEPTH: parseEnvInt("JUST_BASH_MAX_SUBSTITUTION_DEPTH", 50),
143
+ MAX_SQLITE_TIMEOUT_MS: parseEnvInt("JUST_BASH_MAX_SQLITE_TIMEOUT_MS", 5000),
144
+ MAX_PYTHON_TIMEOUT_MS: parseEnvInt("JUST_BASH_MAX_PYTHON_TIMEOUT_MS", 30000),
145
+
146
+ // Output limits
147
+ MAX_OUTPUT_LENGTH: parseEnvInt("JUST_BASH_MAX_OUTPUT_LENGTH", 30000),
148
+
149
+ // Filesystem limits
150
+ MAX_FILE_READ_SIZE: parseEnvOptionalInt("JUST_BASH_MAX_FILE_READ_SIZE"),
151
+
152
+ // Debugging
153
+ ENABLE_LOGGING: parseEnvBoolean("JUST_BASH_ENABLE_LOGGING", false),
154
+ ENABLE_TRACING: parseEnvBoolean("JUST_BASH_ENABLE_TRACING", false),
155
+
156
+ // Feature flags
157
+ ENABLE_PYTHON: parseEnvBoolean("JUST_BASH_ENABLE_PYTHON", false),
158
+ ENABLE_DEFENSE_IN_DEPTH: parseEnvBoolean("JUST_BASH_DEFENSE_IN_DEPTH", false),
159
+ DEFENSE_IN_DEPTH_AUDIT: parseEnvBoolean("JUST_BASH_DEFENSE_IN_DEPTH_AUDIT", false),
160
+ DEFENSE_IN_DEPTH_LOG: parseEnvBoolean("JUST_BASH_DEFENSE_IN_DEPTH_LOG", false),
161
+ OVERLAY_READ_ONLY: parseEnvBoolean("JUST_BASH_OVERLAY_READ_ONLY", false),
162
+
163
+ // Command filtering
164
+ ALLOWED_COMMANDS: getAllowedCommands(),
165
+ };
166
+
167
+ // ============================================================================
168
+ // Logger and Trace Callback
169
+ // ============================================================================
170
+
171
+ export const bashLogger: BashLogger | undefined = config.ENABLE_LOGGING
172
+ ? {
173
+ info(message: string, data?: Record<string, unknown>): void {
174
+ if (data) {
175
+ console.error(`[just-bash] INFO: ${message}`, data);
176
+ } else {
177
+ console.error(`[just-bash] INFO: ${message}`);
178
+ }
179
+ },
180
+ debug(message: string, data?: Record<string, unknown>): void {
181
+ if (data) {
182
+ console.error(`[just-bash] DEBUG: ${message}`, data);
183
+ } else {
184
+ console.error(`[just-bash] DEBUG: ${message}`);
185
+ }
186
+ },
187
+ }
188
+ : undefined;
189
+
190
+ export const traceCallback: TraceCallback | undefined = config.ENABLE_TRACING
191
+ ? (event: TraceEvent) => {
192
+ if (event.details) {
193
+ console.error(
194
+ `[just-bash] TRACE: ${event.category}/${event.name} ${event.durationMs}ms`,
195
+ JSON.stringify(event.details),
196
+ );
197
+ } else {
198
+ console.error(`[just-bash] TRACE: ${event.category}/${event.name} ${event.durationMs}ms`);
199
+ }
200
+ }
201
+ : undefined;
202
+
203
+ // ============================================================================
204
+ // Defense-in-Depth Configuration
205
+ // ============================================================================
206
+
207
+ /**
208
+ * Shared SecurityViolationLogger instance for tracking violations across
209
+ * all Bash instances. Exposed so info-tools can report violation stats.
210
+ */
211
+ export const violationLogger = new SecurityViolationLogger();
212
+
213
+ /**
214
+ * Build the defense-in-depth configuration from environment variables.
215
+ * Returns `false` when disabled, or a full DefenseInDepthConfig object.
216
+ */
217
+ export function buildDefenseInDepthConfig(): DefenseInDepthConfig | false {
218
+ if (!config.ENABLE_DEFENSE_IN_DEPTH) {
219
+ return false;
220
+ }
221
+
222
+ const consoleCallback = config.DEFENSE_IN_DEPTH_LOG
223
+ ? createConsoleViolationCallback()
224
+ : undefined;
225
+
226
+ return {
227
+ enabled: true,
228
+ auditMode: config.DEFENSE_IN_DEPTH_AUDIT,
229
+ onViolation: (violation) => {
230
+ violationLogger.record(violation);
231
+ consoleCallback?.(violation);
232
+ },
233
+ };
234
+ }
235
+
236
+ // ============================================================================
237
+ // Configuration Builders
238
+ // ============================================================================
239
+
240
+ export function buildNetworkConfig(): NetworkConfig | undefined {
241
+ if (!config.ALLOW_NETWORK) {
242
+ return undefined;
243
+ }
244
+
245
+ if (config.ALLOWED_URL_PREFIXES.length > 0) {
246
+ return {
247
+ allowedUrlPrefixes: config.ALLOWED_URL_PREFIXES,
248
+ allowedMethods: config.ALLOWED_METHODS,
249
+ maxRedirects: config.MAX_REDIRECTS,
250
+ timeoutMs: config.NETWORK_TIMEOUT_MS,
251
+ ...(config.MAX_RESPONSE_SIZE !== undefined && {
252
+ maxResponseSize: config.MAX_RESPONSE_SIZE,
253
+ }),
254
+ };
255
+ }
256
+
257
+ return {
258
+ dangerouslyAllowFullInternetAccess: true,
259
+ maxRedirects: config.MAX_REDIRECTS,
260
+ timeoutMs: config.NETWORK_TIMEOUT_MS,
261
+ ...(config.MAX_RESPONSE_SIZE !== undefined && {
262
+ maxResponseSize: config.MAX_RESPONSE_SIZE,
263
+ }),
264
+ };
265
+ }
266
+
267
+ export function buildExecutionLimits(): NonNullable<BashOptions["executionLimits"]> {
268
+ return {
269
+ maxCallDepth: config.MAX_CALL_DEPTH,
270
+ maxCommandCount: config.MAX_COMMAND_COUNT,
271
+ maxLoopIterations: config.MAX_LOOP_ITERATIONS,
272
+ maxAwkIterations: config.MAX_AWK_ITERATIONS,
273
+ maxSedIterations: config.MAX_SED_ITERATIONS,
274
+ maxJqIterations: config.MAX_JQ_ITERATIONS,
275
+ maxGlobOperations: config.MAX_GLOB_OPERATIONS,
276
+ maxStringLength: config.MAX_STRING_LENGTH,
277
+ maxArrayElements: config.MAX_ARRAY_ELEMENTS,
278
+ maxHeredocSize: config.MAX_HEREDOC_SIZE,
279
+ maxSubstitutionDepth: config.MAX_SUBSTITUTION_DEPTH,
280
+ maxSqliteTimeoutMs: config.MAX_SQLITE_TIMEOUT_MS,
281
+ maxPythonTimeoutMs: config.MAX_PYTHON_TIMEOUT_MS,
282
+ };
283
+ }
284
+
285
+ export function parseMountsConfig(): MountConfig[] {
286
+ if (!config.MOUNTS_CONFIG) return [];
287
+ try {
288
+ const parsed: unknown = JSON.parse(config.MOUNTS_CONFIG);
289
+ if (!Array.isArray(parsed)) return [];
290
+ return parsed.map(
291
+ (mount: { mountPoint: string; root: string; type?: string; readOnly?: boolean }) => {
292
+ const fsType = mount.type || "overlay";
293
+ const maxFileReadSize = config.MAX_FILE_READ_SIZE;
294
+ const filesystem =
295
+ fsType === "readwrite"
296
+ ? new ReadWriteFs({
297
+ root: mount.root,
298
+ ...(maxFileReadSize !== undefined && { maxFileReadSize }),
299
+ })
300
+ : new OverlayFs({
301
+ root: mount.root,
302
+ readOnly: mount.readOnly,
303
+ ...(maxFileReadSize !== undefined && { maxFileReadSize }),
304
+ });
305
+ return { mountPoint: mount.mountPoint, filesystem };
306
+ },
307
+ );
308
+ } catch {
309
+ return [];
310
+ }
311
+ }
312
+
313
+ // ============================================================================
314
+ // Environment Variables Documentation
315
+ // ============================================================================
316
+
317
+ export const ENVIRONMENT_VARIABLES = {
318
+ JUST_BASH_OVERLAY_ROOT: "Real directory to mount as overlay (read from disk, write to memory)",
319
+ JUST_BASH_OVERLAY_READ_ONLY:
320
+ "If true, all writes to overlay filesystem throw errors (default: false)",
321
+ JUST_BASH_READ_WRITE_ROOT: "Real directory with read-write access",
322
+ JUST_BASH_MOUNTS: "JSON array of mount configurations (supports type, readOnly fields)",
323
+ JUST_BASH_CWD: "Initial working directory (default: /home/user)",
324
+ JUST_BASH_ALLOW_NETWORK: "Enable network access (default: false)",
325
+ JUST_BASH_ALLOWED_URLS: "Comma-separated URL prefixes to allow",
326
+ JUST_BASH_ALLOWED_METHODS: "Comma-separated HTTP methods (default: GET,HEAD)",
327
+ JUST_BASH_ALLOWED_COMMANDS: "Comma-separated list of allowed commands",
328
+ JUST_BASH_MAX_REDIRECTS: "Max HTTP redirects (default: 20)",
329
+ JUST_BASH_NETWORK_TIMEOUT_MS: "Network timeout in ms (default: 30000)",
330
+ JUST_BASH_MAX_RESPONSE_SIZE: "Max network response body size in bytes (default: 10MB)",
331
+ JUST_BASH_MAX_CALL_DEPTH: "Max recursion depth (default: 100)",
332
+ JUST_BASH_MAX_COMMAND_COUNT: "Max commands per execution (default: 10000)",
333
+ JUST_BASH_MAX_LOOP_ITERATIONS: "Max bash loop iterations (default: 10000)",
334
+ JUST_BASH_MAX_AWK_ITERATIONS: "Max AWK while/for loop iterations (default: 10000)",
335
+ JUST_BASH_MAX_SED_ITERATIONS: "Max sed branch loop iterations (default: 10000)",
336
+ JUST_BASH_MAX_JQ_ITERATIONS: "Max jq loop iterations (default: 10000)",
337
+ JUST_BASH_MAX_GLOB_OPERATIONS: "Max glob filesystem operations (default: 100000)",
338
+ JUST_BASH_MAX_STRING_LENGTH: "Max string length in bytes (default: 10485760 = 10MB)",
339
+ JUST_BASH_MAX_ARRAY_ELEMENTS: "Max array elements (default: 100000)",
340
+ JUST_BASH_MAX_HEREDOC_SIZE: "Max heredoc size in bytes (default: 10485760 = 10MB)",
341
+ JUST_BASH_MAX_SUBSTITUTION_DEPTH: "Max command substitution nesting depth (default: 50)",
342
+ JUST_BASH_MAX_SQLITE_TIMEOUT_MS: "SQLite timeout in ms (default: 5000)",
343
+ JUST_BASH_MAX_PYTHON_TIMEOUT_MS: "Python timeout in ms (default: 30000)",
344
+ JUST_BASH_MAX_OUTPUT_LENGTH: "Max output length (default: 30000)",
345
+ JUST_BASH_MAX_FILE_READ_SIZE:
346
+ "Max file read size in bytes for OverlayFs/ReadWriteFs (default: 10MB)",
347
+ JUST_BASH_ENABLE_LOGGING: "Enable debug logging (default: false)",
348
+ JUST_BASH_ENABLE_TRACING: "Enable performance tracing (default: false)",
349
+ JUST_BASH_ENABLE_PYTHON: "Enable python3/python commands via Pyodide (default: false)",
350
+ JUST_BASH_DEFENSE_IN_DEPTH:
351
+ "Enable defense-in-depth mode that patches dangerous JS globals (default: false)",
352
+ JUST_BASH_DEFENSE_IN_DEPTH_AUDIT:
353
+ "Audit mode: log violations but don't block them (default: false, requires DEFENSE_IN_DEPTH=true)",
354
+ JUST_BASH_DEFENSE_IN_DEPTH_LOG:
355
+ "Log violations to console via createConsoleViolationCallback (default: false)",
356
+ } as const;
357
+
358
+ // ============================================================================
359
+ // Command Categories Documentation
360
+ // ============================================================================
361
+
362
+ export const COMMAND_CATEGORIES = {
363
+ fileOperations: "cat, cp, file, ln, ls, mkdir, mv, readlink, rm, rmdir, split, stat, touch, tree",
364
+ textProcessing:
365
+ "awk, base64, column, comm, cut, diff, expand, fold, grep (egrep, fgrep), head, join, md5sum, nl, od, paste, printf, rev, rg (ripgrep), sed, sha1sum, sha256sum, sort, strings, tac, tail, tr, unexpand, uniq, wc, xargs",
366
+ dataProcessing:
367
+ "jq (JSON), python3/python (Python via Pyodide), sqlite3 (SQLite), xan (CSV), yq (YAML/XML/TOML/CSV)",
368
+ compression: "gzip (gunzip, zcat), tar",
369
+ navigation:
370
+ "basename, cd, dirname, du, echo, env, export, find, hostname, printenv, pwd, tee, whoami",
371
+ shellUtilities:
372
+ "alias, bash, chmod, clear, date, expr, false, help, history, seq, sh, sleep, time, timeout, true, unalias, which",
373
+ network: "curl, html-to-markdown (when network enabled)",
374
+ } as const;
375
+
376
+ // ============================================================================
377
+ // Features Documentation
378
+ // ============================================================================
379
+
380
+ export const FEATURES = {
381
+ customCommands:
382
+ "Define custom TypeScript commands using defineCommand() from just-bash, supports lazy-loading via LazyCommand",
383
+ rawScript: "Preserve leading whitespace in scripts (useful for here-docs)",
384
+ logger: "Optional execution logging via BashLogger interface",
385
+ trace: "Performance profiling via TraceCallback (upstream type)",
386
+ commandFilter: "Restrict available commands via JUST_BASH_ALLOWED_COMMANDS env var",
387
+ sandboxApi:
388
+ "Vercel Sandbox compatible API via bash_sandbox_* tools (run, write, read, mkdir, stop, reset)",
389
+ python: "Python support via Pyodide (opt-in via JUST_BASH_ENABLE_PYTHON=true)",
390
+ defenseInDepth:
391
+ "Defense-in-depth with SecurityViolationLogger, audit mode, and console logging (opt-in via JUST_BASH_DEFENSE_IN_DEPTH=true)",
392
+ overlayReadOnly:
393
+ "Read-only overlay filesystem mode (opt-in via JUST_BASH_OVERLAY_READ_ONLY=true)",
394
+ networkResponseSize:
395
+ "Configurable max network response body size via JUST_BASH_MAX_RESPONSE_SIZE",
396
+ fileReadSizeLimit:
397
+ "Configurable max file read size for OverlayFs/ReadWriteFs via JUST_BASH_MAX_FILE_READ_SIZE",
398
+ networkErrorHandling:
399
+ "Rich network error classification: NetworkAccessDeniedError, TooManyRedirectsError, RedirectNotAllowedError",
400
+ securityViolationTracking:
401
+ "SecurityViolationLogger tracks all defense-in-depth violations with stats via bash_info",
402
+ } as const;
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+
2
3
  /**
3
4
  * just-bash-mcp - MCP Server for sandboxed bash execution
4
5
  *
@@ -8,23 +9,28 @@
8
9
  * @see https://github.com/vercel-labs/just-bash
9
10
  * @see https://modelcontextprotocol.io
10
11
  */
12
+
11
13
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
12
14
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
13
- import { config } from "./config/index.js";
14
- import { registerAllTools } from "./tools/index.js";
15
+
16
+ import { config } from "./config/index.ts";
17
+ import { registerAllTools } from "./tools/index.ts";
18
+
15
19
  // ============================================================================
16
20
  // Server Initialization
17
21
  // ============================================================================
22
+
18
23
  const server = new McpServer({
19
- name: config.SERVER_NAME,
20
- version: config.VERSION,
24
+ name: config.SERVER_NAME,
25
+ version: config.VERSION,
21
26
  });
27
+
22
28
  // Register all tools with the server
23
29
  registerAllTools(server);
30
+
24
31
  // ============================================================================
25
32
  // Start Server
26
33
  // ============================================================================
34
+
27
35
  const transport = new StdioServerTransport();
28
36
  await server.connect(transport);
29
- console.error(`${config.SERVER_NAME} server v${config.VERSION} running on stdio`);
30
- //# sourceMappingURL=index.js.map