@n0zer0d4y/vulcan-file-ops 1.1.1 → 1.1.3
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/CHANGELOG.md +43 -0
- package/README.md +14 -2
- package/dist/tools/filesystem-tools.js +22 -3
- package/dist/tools/shell-tool.js +37 -13
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,49 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.1.3] - 2025-11-13
|
|
9
|
+
|
|
10
|
+
### Security
|
|
11
|
+
|
|
12
|
+
- CRITICAL: Fixed shell execution directory bypass vulnerability that allowed arbitrary command execution in unapproved directories
|
|
13
|
+
- Shell commands without explicit workdir parameter now properly validate process.cwd() against allowed directories
|
|
14
|
+
- All shell executions now require at least one approved directory to be configured
|
|
15
|
+
- Added mandatory directory validation for both explicit and default working directories
|
|
16
|
+
- Enhanced error messages with clear guidance for users
|
|
17
|
+
- This is a breaking change by design for security: users must configure approved directories or provide explicit workdir parameters
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- 7 comprehensive security tests for shell execution directory validation
|
|
22
|
+
- Root Cause Analysis document: local_docs/RCA-Shell-Execution-Directory-Bypass-Vulnerability.md
|
|
23
|
+
- Security fix verification document: local_docs/SECURITY-FIX-VERIFICATION.md
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- Updated execute_shell tool description to explicitly document security requirements
|
|
28
|
+
- Updated 10+ existing tests to comply with enhanced security model
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- Shell execution no longer bypasses directory validation when workdir parameter is omitted
|
|
33
|
+
- Process working directory is now validated against allowed directories in all cases
|
|
34
|
+
|
|
35
|
+
## [1.1.2] - 2025-01-12
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
|
|
39
|
+
- Added defensive string-to-array parsing for `make_directory` tool to handle MCP clients that incorrectly serialize array parameters as stringified JSON
|
|
40
|
+
- Workaround for Claude Desktop serialization issue
|
|
41
|
+
- Zero impact on correctly-functioning MCP clients (Cursor IDE verified)
|
|
42
|
+
- Includes diagnostic logging to identify problematic clients
|
|
43
|
+
- Comprehensive test coverage for stringified arrays and edge cases
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
|
|
47
|
+
- 4 new test cases for MCP client serialization workaround
|
|
48
|
+
- Diagnostic logging when stringified array parameters are detected
|
|
49
|
+
- Root Cause Analysis document in `local_docs/make_directory_batch_failure_rca.md`
|
|
50
|
+
|
|
8
51
|
## [1.1.1] - 2025-11-11
|
|
9
52
|
|
|
10
53
|
### Fixed
|
package/README.md
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
[](https://modelcontextprotocol.io)
|
|
7
7
|
[](https://github.com/RichardLitt/standard-readme)
|
|
8
8
|
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
[](https://mseep.ai/app/n0zer0d4y-vulcan-file-ops)
|
|
9
10
|
|
|
10
11
|
**Transform your desktop AI assistants into powerful development partners.** Vulcan File Ops bridges the gap between conversational AI (Claude Desktop, ChatGPT Desktop, etc.) and your local filesystem, unlocking the same file manipulation capabilities found in AI-powered IDEs like Cursor and Cline. Write code, refactor projects, manage documentation, and perform complex file operations—matching the power of dedicated AI coding assistants. With enterprise-grade security controls, dynamic directory registration, and intelligent tool filtering, you maintain complete control while your AI assistant handles the heavy lifting.
|
|
11
12
|
|
|
@@ -442,6 +443,8 @@ The AI will use the `register_directory` tool to gain access, then perform opera
|
|
|
442
443
|
|
|
443
444
|
Read file contents with flexible modes (full, head, tail, range)
|
|
444
445
|
|
|
446
|
+
**Note:** This tool is limited to single-file operations only. **RECOMMENDED:** Use `read_multiple_files` instead, which supports both single and batch file operations for greater flexibility.
|
|
447
|
+
|
|
445
448
|
**Input:**
|
|
446
449
|
|
|
447
450
|
- `path` (string): File path
|
|
@@ -482,6 +485,8 @@ Batch read multiple files concurrently
|
|
|
482
485
|
|
|
483
486
|
Create or replace file content
|
|
484
487
|
|
|
488
|
+
**Note:** This tool is limited to single-file operations only. **RECOMMENDED:** Use `write_multiple_files` instead, which supports both single and batch file operations for greater flexibility.
|
|
489
|
+
|
|
485
490
|
**Input:**
|
|
486
491
|
|
|
487
492
|
- `path` (string): File path
|
|
@@ -577,6 +582,8 @@ List directory contents with multiple output formats
|
|
|
577
582
|
|
|
578
583
|
Relocate or rename files and directories
|
|
579
584
|
|
|
585
|
+
**Note:** This tool is limited to single-file operations only. **RECOMMENDED:** Use `file_operations` instead, which supports move, copy, and rename operations for both single and batch files with greater flexibility.
|
|
586
|
+
|
|
580
587
|
**Input:**
|
|
581
588
|
|
|
582
589
|
- `source` (string): Source path
|
|
@@ -685,12 +692,16 @@ Execute shell commands with security controls
|
|
|
685
692
|
|
|
686
693
|
- `command` (string): Shell command to execute
|
|
687
694
|
- `description` (string, optional): Command purpose
|
|
688
|
-
- `workdir` (string, optional): Working directory (must be within allowed directories)
|
|
695
|
+
- `workdir` (string, optional): Working directory (must be within allowed directories). If not provided, process.cwd() is used and validated
|
|
689
696
|
- `timeout` (number, optional): Timeout in milliseconds (default: 30000)
|
|
690
697
|
|
|
691
698
|
**Output:** Exit code, stdout, stderr, and execution metadata
|
|
692
699
|
|
|
693
|
-
**Security:**
|
|
700
|
+
**Security:**
|
|
701
|
+
- At least one approved directory must be configured before executing shell commands
|
|
702
|
+
- Working directory (whether explicit or default process.cwd()) is always validated against allowed directories
|
|
703
|
+
- All file/directory paths in command arguments are automatically extracted and validated against allowed directories
|
|
704
|
+
- Commands referencing paths outside approved directories are blocked, preventing directory restriction bypasses
|
|
694
705
|
|
|
695
706
|
### Multi-File Edit Examples
|
|
696
707
|
|
|
@@ -848,6 +859,7 @@ This server has been audited against known vulnerabilities:
|
|
|
848
859
|
- ✅ CVE-2025-54795 (Command Injection) - **PROTECTED**
|
|
849
860
|
- ✅ CVE-2025-53109 (Symlink Attacks) - **PROTECTED**
|
|
850
861
|
- ✅ CVE-2025-53110 (Directory Containment Bypass) - **PROTECTED**
|
|
862
|
+
- ✅ Shell Execution Directory Bypass - **FIXED** (November 2024)
|
|
851
863
|
|
|
852
864
|
For detailed security analysis, see [Vulnerability Research Findings](docs/VULNERABILITY_RESEARCH_FINDINGS.md).
|
|
853
865
|
|
|
@@ -433,10 +433,29 @@ export async function handleFileSystemTool(name, args) {
|
|
|
433
433
|
if (!parsed.success) {
|
|
434
434
|
throw new Error(`Invalid arguments for make_directory: ${parsed.error}`);
|
|
435
435
|
}
|
|
436
|
+
// Defensive handling for MCP clients that may stringify arrays
|
|
437
|
+
// Some MCP clients (e.g., Claude Desktop) incorrectly serialize array parameters
|
|
438
|
+
// as stringified JSON instead of proper arrays. This workaround detects and fixes that.
|
|
439
|
+
let pathsInput = parsed.data.paths;
|
|
440
|
+
// If paths is a string that looks like a JSON array, try to parse it
|
|
441
|
+
if (typeof pathsInput === "string" && pathsInput.trim().startsWith("[")) {
|
|
442
|
+
try {
|
|
443
|
+
const parsedArray = JSON.parse(pathsInput);
|
|
444
|
+
if (Array.isArray(parsedArray)) {
|
|
445
|
+
pathsInput = parsedArray;
|
|
446
|
+
// Log for diagnostics - helps identify which clients have serialization issues
|
|
447
|
+
console.error("[INFO] make_directory: Detected and corrected stringified array parameter");
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
catch {
|
|
451
|
+
// If parsing fails, treat as single path (existing behavior)
|
|
452
|
+
// This handles edge cases like paths literally named "[something]"
|
|
453
|
+
}
|
|
454
|
+
}
|
|
436
455
|
// Normalize to array (single path or multiple paths)
|
|
437
|
-
const pathsToCreate = Array.isArray(
|
|
438
|
-
?
|
|
439
|
-
: [
|
|
456
|
+
const pathsToCreate = Array.isArray(pathsInput)
|
|
457
|
+
? pathsInput
|
|
458
|
+
: [pathsInput];
|
|
440
459
|
// Validate all paths first (atomic - fail before any creation)
|
|
441
460
|
const allowedDirs = getAllowedDirectories();
|
|
442
461
|
const validatedPaths = pathsToCreate.map((dirPath) => {
|
package/dist/tools/shell-tool.js
CHANGED
|
@@ -52,9 +52,14 @@ export function getShellTools() {
|
|
|
52
52
|
description: `Execute shell commands on the host system with security controls. ` +
|
|
53
53
|
`Commands are executed as '${shellConfig.shell} ${shellConfig.args.join(" ")} <command>' on ${shellConfig.platform}. ` +
|
|
54
54
|
`\n\nThe tool captures stdout, stderr, exit codes, and signals. ` +
|
|
55
|
-
`Working directory can be specified (must be within allowed directories). ` +
|
|
56
55
|
`Commands exceeding the timeout will be automatically terminated. ` +
|
|
57
|
-
`\n\n⚠️ SECURITY
|
|
56
|
+
`\n\n⚠️ SECURITY REQUIREMENTS:\n` +
|
|
57
|
+
`- At least ONE approved directory must be configured before executing any shell commands\n` +
|
|
58
|
+
`- Working directory (workdir parameter or process.cwd()) MUST be within allowed directories\n` +
|
|
59
|
+
`- All file/directory paths in command arguments are validated against allowed directories\n` +
|
|
60
|
+
`- Command substitution and dangerous patterns may be restricted\n` +
|
|
61
|
+
`\n` +
|
|
62
|
+
`If no workdir is specified, the server's current working directory will be used and validated.` +
|
|
58
63
|
approvedCommandsText +
|
|
59
64
|
`\n\nIMPORTANT: Always provide a clear description of what the command does and why it's needed.`,
|
|
60
65
|
inputSchema: zodToJsonSchema(ShellCommandArgsSchema),
|
|
@@ -120,17 +125,36 @@ export async function handleShellTool(name, args) {
|
|
|
120
125
|
: ""}` +
|
|
121
126
|
`To approve, add these commands to --approved-commands or .env configuration.`);
|
|
122
127
|
}
|
|
123
|
-
// Validate working directory if provided
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
128
|
+
// SECURITY FIX: Validate working directory ALWAYS (not just if provided)
|
|
129
|
+
// This prevents bypass via process.cwd() when workdir is omitted
|
|
130
|
+
const allowedDirs = getAllowedDirectories();
|
|
131
|
+
// Require at least one approved directory for shell execution
|
|
132
|
+
if (allowedDirs.length === 0) {
|
|
133
|
+
throw new Error(`Access denied: Shell execution requires at least one approved directory.\n` +
|
|
134
|
+
`No allowed directories are currently configured.\n` +
|
|
135
|
+
`\n` +
|
|
136
|
+
`To execute shell commands, you must first configure allowed directories using:\n` +
|
|
137
|
+
` 1. --approved-folders CLI argument when starting the MCP server, OR\n` +
|
|
138
|
+
` 2. register_directory tool to add directories at runtime\n` +
|
|
139
|
+
`\n` +
|
|
140
|
+
`Example: register_directory with path "C:/path/to/your/project"`);
|
|
141
|
+
}
|
|
142
|
+
// Always validate working directory against allowed directories
|
|
143
|
+
let workdir = validatedArgs.workdir || process.cwd();
|
|
144
|
+
try {
|
|
145
|
+
workdir = await validatePath(workdir);
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
throw new Error(`Access denied: Working directory is not within allowed directories.\n` +
|
|
149
|
+
`Attempted directory: ${workdir}\n` +
|
|
150
|
+
`Error: ${error instanceof Error ? error.message : String(error)}\n` +
|
|
151
|
+
`\n` +
|
|
152
|
+
`Allowed directories:\n` +
|
|
153
|
+
allowedDirs.map(d => ` - ${d}`).join('\n') +
|
|
154
|
+
`\n\n` +
|
|
155
|
+
`To execute commands in this directory:\n` +
|
|
156
|
+
` 1. Register the directory using register_directory tool, OR\n` +
|
|
157
|
+
` 2. Specify a workdir parameter within an approved directory`);
|
|
134
158
|
}
|
|
135
159
|
// Extract and validate paths from command arguments
|
|
136
160
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@n0zer0d4y/vulcan-file-ops",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "MCP server that gives Claude Desktop and other AI assistants filesystem superpowers—read, write, edit, and manage files like AI coding assistants",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Lloyd Barcatan",
|