UNPKG

@gabrielmaialva33/mcp-filesystem

Version:
108 lines 3.2 kB
import { exec } from 'node:child_process'; import { promisify } from 'node:util'; import { logger } from '../../logger/index.js'; import { FileSystemError } from '../../errors/index.js'; const execPromise = promisify(exec); const DEFAULT_TIMEOUT_MS = 30000; const SAFE_COMMAND_REGEX = /^[a-zA-Z0-9_\-./\s]+$/; const FORBIDDEN_COMMANDS = [ 'rm -rf', 'rm -r', 'rmdir', 'dd', 'mkfs', 'format', 'wget', 'curl -O', 'curl --output', 'chmod 777', 'chmod -R 777', 'sudo', 'su', ]; export function isCommandSafe(command) { if (FORBIDDEN_COMMANDS.some((forbidden) => command.includes(forbidden))) { return false; } if (!SAFE_COMMAND_REGEX.test(command)) { return false; } return true; } export async function executeBashCommand(command, options = {}) { if (!isCommandSafe(command)) { throw new FileSystemError(`Command contains forbidden operations or unsafe characters: ${command}`, 'UNSAFE_COMMAND', undefined, { command }); } const execOptions = { cwd: options.workingDir || process.cwd(), timeout: options.timeout || DEFAULT_TIMEOUT_MS, env: options.env ? { ...process.env, ...options.env } : process.env, encoding: 'utf8', maxBuffer: 10 * 1024 * 1024, }; try { await logger.debug(`Executing bash command: ${command}`, { workingDir: execOptions.cwd, timeout: execOptions.timeout, }); const { stdout, stderr } = await execPromise(command, execOptions); return { stdout, stderr, exitCode: 0, }; } catch (error) { await logger.warn(`Command execution failed: ${command}`, { error: error.message, stderr: error.stderr, code: error.code, }); return { stdout: error.stdout || '', stderr: error.stderr || error.message || 'Unknown error', exitCode: error.code || 1, }; } } export const BashCommandArgsSchema = { type: 'object', properties: { command: { type: 'string', description: 'The bash command to execute', }, workingDir: { type: 'string', description: 'Working directory for command execution (must be within allowed directories)', }, timeout: { type: 'number', description: 'Maximum execution time in milliseconds (max 30s)', }, env: { type: 'object', description: 'Additional environment variables for the command', }, }, required: ['command'], }; export async function handleBashCommand(args) { const result = await executeBashCommand(args.command, { workingDir: args.workingDir, timeout: args.timeout, env: args.env, }); const output = [ `Command: ${args.command}`, `Exit Code: ${result.exitCode}`, '', 'STDOUT:', result.stdout || '(empty)', '', 'STDERR:', result.stderr || '(empty)', ].join('\n'); return output; } //# sourceMappingURL=index.js.map