Skip to main content
Glama
shell-tool.test.ts23.5 kB
import { describe, test, expect, beforeEach } from "@jest/globals"; import { initializeShellTool, handleShellTool, getApprovedCommands, } from "../tools/shell-tool.js"; import { setAllowedDirectories } from "../utils/lib.js"; import os from "os"; describe("Shell Tool", () => { beforeEach(() => { // Initialize with some approved commands initializeShellTool(["ls", "pwd", "echo", "cat"]); setAllowedDirectories([os.tmpdir()]); }); test("executes approved command", async () => { const result = await handleShellTool("execute_shell", { command: "echo test", description: "Test echo command", workdir: os.tmpdir(), // Specify workdir within allowed directory }); expect(result.content).toHaveLength(1); expect(result.content[0].type).toBe("text"); expect(result.content[0].text).toContain("test"); expect(result.content[0].text).toContain("Exit Code: 0"); expect(result.isError).toBe(false); }, 10000); test("rejects unapproved command without requiresApproval flag", async () => { await expect( handleShellTool("execute_shell", { command: "sudo apt install", requiresApproval: false, }) ).rejects.toThrow("Command not in approved list"); }); test("rejects unapproved command with requiresApproval flag", async () => { await expect( handleShellTool("execute_shell", { command: "rm -rf /tmp/test", requiresApproval: true, }) ).rejects.toThrow("Command not in approved list"); }); test("rejects dangerous command even if root is approved", async () => { await expect( handleShellTool("execute_shell", { command: "rm -rf /tmp/test", requiresApproval: false, }) ).rejects.toThrow("Command not in approved list"); }); test("validates working directory", async () => { await expect( handleShellTool("execute_shell", { command: "echo test", workdir: "/unauthorized/path", }) ).rejects.toThrow("Working directory is not within allowed directories"); }); test("respects timeout", async () => { // Add platform-specific commands to approved list for this test const sleepCmd = os.platform() === "win32" ? "Start-Sleep" : "sleep"; initializeShellTool(["ls", "pwd", "echo", "cat", sleepCmd]); const command = os.platform() === "win32" ? "Start-Sleep -Seconds 5" : "sleep 5"; const result = await handleShellTool("execute_shell", { command, timeout: 1000, workdir: os.tmpdir(), // Specify workdir within allowed directory }); expect(result.content[0].text).toContain("TIMEOUT"); expect(result.isError).toBe(true); }, 10000); test("includes command description in result", async () => { const result = await handleShellTool("execute_shell", { command: "echo test", description: "This is a test command", workdir: os.tmpdir(), // Specify workdir within allowed directory }); expect(result.content[0].text).toContain("This is a test command"); }); test("reports non-zero exit codes as errors", async () => { // Add 'exit' to approved commands for this test initializeShellTool(["ls", "pwd", "echo", "cat", "exit"]); const command = os.platform() === "win32" ? "exit 1" : "exit 1"; const result = await handleShellTool("execute_shell", { command, workdir: os.tmpdir(), // Specify workdir within allowed directory }); expect(result.content[0].text).toContain("Exit Code: 1"); expect(result.isError).toBe(true); }); test("rejects command with command substitution", async () => { await expect( handleShellTool("execute_shell", { command: "echo $(whoami)", }) ).rejects.toThrow("Command substitution"); }); test("blocks command injection via approved commands (CVE-2025-54795 pattern)", async () => { // This test verifies that command injection attempts through approved commands // are blocked when unapproved commands are detected in the chain // Pattern: echo test; rm -rf /tmp; echo done // Even though echo is approved, the unapproved rm/del command should be blocked if (os.platform() !== "win32") { // On Unix, test with rm -rf (not in approved list) const injectedCommand = "echo test; rm -rf /tmp/*; echo done"; // Should be rejected because rm is not in approved list await expect( handleShellTool("execute_shell", { command: injectedCommand, requiresApproval: false, }) ).rejects.toThrow("Command not in approved list"); } else { // On Windows, test with del (not in approved list) const injectedCommand = "echo test; del /s /q C:\\tmp\\*; echo done"; // Should be rejected because del is not in approved list await expect( handleShellTool("execute_shell", { command: injectedCommand, requiresApproval: false, }) ).rejects.toThrow("Command not in approved list"); } }); test("blocks unapproved commands when requiresApproval is true", async () => { // This test verifies that unapproved commands are blocked regardless of requiresApproval flag const injectedCommand = "echo test; unapproved_command; echo done"; // Should be rejected because extractRootCommands will detect "unapproved_command" // which is not in the approved list await expect( handleShellTool("execute_shell", { command: injectedCommand, requiresApproval: true, }) ).rejects.toThrow("Command not in approved list"); }); test("rejects empty command", async () => { await expect( handleShellTool("execute_shell", { command: "", }) ).rejects.toThrow(); }); test("throws error for unknown tool name", async () => { await expect( handleShellTool("unknown_tool", { command: "echo test", }) ).rejects.toThrow("Unknown shell tool"); }); test("getApprovedCommands returns initialized commands", () => { const commands = getApprovedCommands(); expect(commands).toContain("ls"); expect(commands).toContain("pwd"); expect(commands).toContain("echo"); expect(commands).toContain("cat"); }); test("executes command in specified working directory", async () => { const testDir = os.tmpdir(); const command = os.platform() === "win32" ? "pwd" : "pwd"; const result = await handleShellTool("execute_shell", { command, workdir: testDir, }); expect(result.content[0].text).toContain(testDir); }); test("captures both stdout and stderr", async () => { // Add Write-Error to approved commands for Windows test if (os.platform() === "win32") { initializeShellTool(["ls", "pwd", "echo", "cat", "Write-Error"]); } const command = os.platform() === "win32" ? "echo stdout; Write-Error 'stderr'" : "echo stdout && echo stderr >&2"; const result = await handleShellTool("execute_shell", { command, workdir: os.tmpdir(), // Specify workdir within allowed directory }); expect(result.content[0].text).toContain("Standard Output"); expect(result.content[0].text).toContain("Standard Error"); }); test("handles chained commands when all roots approved", async () => { const command = os.platform() === "win32" ? "echo first; echo second" : "echo first && echo second"; const result = await handleShellTool("execute_shell", { command, workdir: os.tmpdir(), // Specify workdir within allowed directory }); expect(result.content[0].text).toContain("first"); expect(result.content[0].text).toContain("second"); expect(result.isError).toBe(false); }); test("rejects chained commands when any root not approved", async () => { const command = os.platform() === "win32" ? "echo test; sudo apt install" : "echo test && sudo apt install"; await expect( handleShellTool("execute_shell", { command, }) ).rejects.toThrow("Command not in approved list"); }); test("includes working directory in result", async () => { const result = await handleShellTool("execute_shell", { command: "echo test", workdir: os.tmpdir(), // Specify workdir within allowed directory }); expect(result.content[0].text).toContain("Working Directory:"); }); test("includes command in result", async () => { const result = await handleShellTool("execute_shell", { command: "echo hello world", workdir: os.tmpdir(), // Specify workdir within allowed directory }); expect(result.content[0].text).toContain("Command: echo hello world"); }); test("formats result with proper sections", async () => { const result = await handleShellTool("execute_shell", { command: "echo test", workdir: os.tmpdir(), // Specify workdir within allowed directory }); const text = result.content[0].text; expect(text).toContain("Shell Command Execution Result:"); expect(text).toContain("--- Standard Output ---"); expect(text).toContain("--- Standard Error ---"); expect(text).toContain("Exit Code:"); }); // Security Fix Tests: Shell Execution Directory Bypass Vulnerability describe("Security Fix: Directory Validation", () => { test("rejects shell execution when no approved directories configured", async () => { // Setup: Clear all allowed directories to simulate no configuration setAllowedDirectories([]); await expect( handleShellTool("execute_shell", { command: "echo test", description: "Test command without approved directories", }) ).rejects.toThrow("at least one approved directory"); }); test("validates process.cwd() when workdir not provided", async () => { // Setup: Set allowed directory to something that's NOT process.cwd() // Use a very specific path that won't match current working directory const nonMatchingDir = os.platform() === "win32" ? "C:\\NonExistentSecureDirectory123456" : "/nonexistent-secure-directory-123456"; setAllowedDirectories([nonMatchingDir]); // When workdir is NOT provided, process.cwd() should be validated // and rejected since it's not in the allowed directories await expect( handleShellTool("execute_shell", { command: "echo test", description: "Test without workdir parameter", // No workdir provided - should validate process.cwd() }) ).rejects.toThrow("Working directory is not within allowed directories"); }); test("accepts command with workdir in approved directory", async () => { // Setup: Approved directory const approvedDir = os.tmpdir(); setAllowedDirectories([approvedDir]); const result = await handleShellTool("execute_shell", { command: "echo test", workdir: approvedDir, description: "Test with approved workdir", }); expect(result.isError).toBe(false); expect(result.content[0].text).toContain("Exit Code: 0"); }); test("rejects command with workdir outside approved directories", async () => { // Setup: Approved directory setAllowedDirectories([os.tmpdir()]); // Try to execute in unauthorized directory const unauthorizedDir = os.platform() === "win32" ? "C:\\Windows\\System32" : "/etc"; await expect( handleShellTool("execute_shell", { command: "echo test", workdir: unauthorizedDir, description: "Test with unapproved workdir", }) ).rejects.toThrow("Working directory is not within allowed directories"); }); test("provides helpful error message when directory not approved", async () => { setAllowedDirectories([os.tmpdir()]); const unauthorizedDir = os.platform() === "win32" ? "C:\\Windows" : "/usr"; try { await handleShellTool("execute_shell", { command: "echo test", workdir: unauthorizedDir, }); // Should not reach here expect(true).toBe(false); } catch (error) { const errorMessage = (error as Error).message; // Verify error message includes helpful information expect(errorMessage).toContain("Access denied"); expect(errorMessage).toContain("Allowed directories:"); expect(errorMessage).toContain(os.tmpdir()); expect(errorMessage).toContain("register_directory"); } }); test("provides helpful error message when no directories configured", async () => { setAllowedDirectories([]); try { await handleShellTool("execute_shell", { command: "echo test", }); // Should not reach here expect(true).toBe(false); } catch (error) { const errorMessage = (error as Error).message; // Verify error message includes helpful guidance expect(errorMessage).toContain("Access denied"); expect(errorMessage).toContain("at least one approved directory"); expect(errorMessage).toContain("--approved-folders"); expect(errorMessage).toContain("register_directory"); } }); test("CVE Fix: prevents arbitrary execution via process.cwd() bypass", async () => { // This test specifically validates the CVE fix // Previously, omitting workdir would bypass directory validation // Setup: Configure specific allowed directory const allowedDir = os.tmpdir(); setAllowedDirectories([allowedDir]); // Scenario 1: Command with explicit workdir in allowed directory - should work const result1 = await handleShellTool("execute_shell", { command: "echo allowed", workdir: allowedDir, }); expect(result1.isError).toBe(false); // Scenario 2: Command without workdir - should validate process.cwd() // If process.cwd() is not in allowed directories, it should fail // Note: This test might pass or fail depending on where tests run from // The important thing is that validation HAPPENS, not that it's blocked try { await handleShellTool("execute_shell", { command: "echo test", // No workdir - will use and validate process.cwd() }); // If we reach here, process.cwd() must be within allowed directories // which is valid behavior - the key is that validation occurred } catch (error) { // If we catch an error, it should be about directory validation const errorMessage = (error as Error).message; expect(errorMessage).toContain("Working directory is not within allowed directories"); } }); }); // Security Fix Tests: Command Approval Bypass Vulnerability describe("Security Fix: Strict Command Whitelist Enforcement", () => { beforeEach(() => { // Initialize with approved commands initializeShellTool(["ls", "pwd", "echo", "cat"]); setAllowedDirectories([os.tmpdir()]); }); test("blocks unapproved non-dangerous command (whoami)", async () => { await expect( handleShellTool("execute_shell", { command: "whoami", workdir: os.tmpdir(), }) ).rejects.toThrow("Command not in approved list"); }); test("blocks unapproved non-dangerous command (hostname)", async () => { await expect( handleShellTool("execute_shell", { command: "hostname", workdir: os.tmpdir(), }) ).rejects.toThrow("Command not in approved list"); }); test("blocks Windows dir command (not in approved list)", async () => { if (os.platform() === "win32") { await expect( handleShellTool("execute_shell", { command: "dir", workdir: os.tmpdir(), }) ).rejects.toThrow("Command not in approved list"); } }); test("blocks Windows type command (not in approved list)", async () => { if (os.platform() === "win32") { await expect( handleShellTool("execute_shell", { command: "type test.txt", workdir: os.tmpdir(), }) ).rejects.toThrow("Command not in approved list"); } }); test("blocks Windows copy command (not in approved list)", async () => { if (os.platform() === "win32") { await expect( handleShellTool("execute_shell", { command: "copy file1.txt file2.txt", workdir: os.tmpdir(), }) ).rejects.toThrow("Command not in approved list"); } }); test("blocks Windows move command (not in approved list)", async () => { if (os.platform() === "win32") { await expect( handleShellTool("execute_shell", { command: "move file1.txt file2.txt", workdir: os.tmpdir(), }) ).rejects.toThrow("Command not in approved list"); } }); test("blocks Windows ren command (not in approved list)", async () => { if (os.platform() === "win32") { await expect( handleShellTool("execute_shell", { command: "ren file1.txt file2.txt", workdir: os.tmpdir(), }) ).rejects.toThrow("Command not in approved list"); } }); test("blocks Windows del command without /s flag (not in approved list)", async () => { if (os.platform() === "win32") { await expect( handleShellTool("execute_shell", { command: "del test.txt", workdir: os.tmpdir(), }) ).rejects.toThrow("Command not in approved list"); } }); test("blocks Windows mkdir command (not in approved list)", async () => { if (os.platform() === "win32") { await expect( handleShellTool("execute_shell", { command: "mkdir newdir", workdir: os.tmpdir(), }) ).rejects.toThrow("Command not in approved list"); } }); test("blocks Windows rmdir command (not in approved list)", async () => { if (os.platform() === "win32") { await expect( handleShellTool("execute_shell", { command: "rmdir emptydir", workdir: os.tmpdir(), }) ).rejects.toThrow("Command not in approved list"); } }); test("blocks Windows ipconfig command (not in approved list)", async () => { if (os.platform() === "win32") { await expect( handleShellTool("execute_shell", { command: "ipconfig", workdir: os.tmpdir(), }) ).rejects.toThrow("Command not in approved list"); } }); test("allows approved commands to execute", async () => { const result = await handleShellTool("execute_shell", { command: "echo approved", workdir: os.tmpdir(), }); expect(result.isError).toBe(false); expect(result.content[0].text).toContain("approved"); }); test("allows multiple approved commands in chain", async () => { const command = os.platform() === "win32" ? "echo first; echo second" : "echo first && echo second"; const result = await handleShellTool("execute_shell", { command, workdir: os.tmpdir(), }); expect(result.isError).toBe(false); expect(result.content[0].text).toContain("first"); }); test("error message includes list of approved commands", async () => { try { await handleShellTool("execute_shell", { command: "whoami", workdir: os.tmpdir(), }); fail("Should have thrown error"); } catch (error) { const errorMessage = (error as Error).message; expect(errorMessage).toContain("Approved commands:"); expect(errorMessage).toContain("ls"); expect(errorMessage).toContain("pwd"); expect(errorMessage).toContain("echo"); expect(errorMessage).toContain("cat"); } }); test("error message identifies specific unapproved command", async () => { try { await handleShellTool("execute_shell", { command: "whoami", workdir: os.tmpdir(), }); fail("Should have thrown error"); } catch (error) { const errorMessage = (error as Error).message; expect(errorMessage).toContain("Unapproved commands: whoami"); expect(errorMessage).toContain("Access denied"); } }); test("blocks unapproved command even with requiresApproval=false", async () => { // This is the critical bug fix test // Previously, requiresApproval=false would allow execution await expect( handleShellTool("execute_shell", { command: "whoami", requiresApproval: false, workdir: os.tmpdir(), }) ).rejects.toThrow("Command not in approved list"); }); test("blocks dangerous pattern on approved command without explicit approval", async () => { // Add 'rm' to approved commands initializeShellTool(["ls", "pwd", "echo", "cat", "rm"]); // 'rm' is approved, but 'rm -rf' is dangerous and requires explicit approval await expect( handleShellTool("execute_shell", { command: "rm -rf /tmp/test", requiresApproval: false, // No explicit approval workdir: os.tmpdir(), }) ).rejects.toThrow("Dangerous command pattern detected"); }); test("allows dangerous pattern on approved command with explicit approval", async () => { // Add platform-specific delete command to approved commands const deleteCmd = os.platform() === "win32" ? "del" : "rm"; initializeShellTool(["ls", "pwd", "echo", "cat", deleteCmd]); // Create a test file to delete const testFile = `${os.tmpdir()}/test-delete-${Date.now()}.txt`; require("fs").writeFileSync(testFile, "test"); // Delete command is approved and requiresApproval=true, should work const command = os.platform() === "win32" ? `del ${testFile}` : `rm ${testFile}`; const result = await handleShellTool("execute_shell", { command, requiresApproval: true, workdir: os.tmpdir(), }); // Command is approved with explicit approval, should succeed expect(result.isError).toBe(false); }); test("regression: all examples from RCA should now be blocked", async () => { // Reset to the exact approved list from the RCA initializeShellTool(["npm", "node", "git", "ls", "pwd", "cat", "echo"]); const unapprovedCommands = [ "whoami", "hostname", ...(os.platform() === "win32" ? [ "dir", "type test.txt", "copy a.txt b.txt", "move a.txt b.txt", "ren a.txt b.txt", "del test.txt", "mkdir newdir", "rmdir olddir", "ipconfig", ] : []), ]; for (const cmd of unapprovedCommands) { await expect( handleShellTool("execute_shell", { command: cmd, workdir: os.tmpdir(), }) ).rejects.toThrow("Command not in approved list"); } }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/n0zer0d4y/vulcan-file-ops'

If you have feedback or need assistance with the MCP directory API, please join our Discord server