# Desktop Commander MCP allowedDirectories Security Model: Why Terminal Commands Bypass Directory Restrictions

> Discover the Desktop Commander MCP security model and understand why allowedDirectories restrictions fail to block terminal commands. Learn how to secure your system.

- Repository: [Eduard Ruzga/DesktopCommanderMCP](https://github.com/wonderwhy-er/DesktopCommanderMCP)
- Tags: internals
- Published: 2026-07-29

---

**Desktop Commander MCP enforces the `allowedDirectories` restriction only on file-system API operations, while terminal commands execute directly through the OS shell and are only filtered by the optional `blockedCommands` list, allowing unrestricted access to any path the host user can reach.**

The Desktop Commander MCP server implements a dual-layer security architecture that strictly separates file-system access controls from command execution privileges. While the `allowedDirectories` configuration creates a sandbox for file operations in [`src/tools/filesystem.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/filesystem.ts), it does not constrain terminal commands, which inherit the full permissions of the host environment. Understanding this architectural distinction is critical for administrators deploying the tool in production environments.

## How allowedDirectories Enforces File-System Sandboxing

The `allowedDirectories` security model applies exclusively to file-system operations through a validation layer implemented in [`src/tools/filesystem.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/filesystem.ts). Every public file operation—`readFile`, `writeFile`, `listDirectory`, `moveFile`, and `createDirectory`—first invokes the `validatePath` function before executing.

The validation process performs three critical steps: expanding tilde (`~`) characters to the home directory, resolving symlinks and parent directory references (`..`), and checking the resolved absolute path against the list returned by `getAllowedDirs`. If the configured list is empty or contains the root directory (`/` on Unix systems or `c:` on Windows), the check is bypassed entirely and the operation is permitted.

```typescript
// src/tools/filesystem.ts – validatePath implementation
const allowedDirectories = await getAllowedDirs();   // ← reads config.allowedDirectories
if (allowedDirectories.includes('/') || allowedDirectories.length === 0) {
    return true;   // empty or root → unrestricted
}
// Path is accepted only if it is exactly an allowed directory or a sub‑directory of one.

```

This design ensures that file-system APIs cannot escape the configured directories, creating a true sandbox for automated file manipulation.

## Why Terminal Commands Ignore allowedDirectories

Terminal command execution follows a completely separate security path defined in [`src/command-manager.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/command-manager.ts), which does not reference `allowedDirectories` at all. When a command string arrives through the terminal skill, the system extracts executable names using `extractCommands` and validates them against the `blockedCommands` array via `validateCommand`.

The `blockedCommands` list is optional and empty by default, meaning **no commands are blocked** unless explicitly configured. Crucially, this validation checks only command names against the blacklist; it performs no path resolution or directory validation.

```typescript
// src/command-manager.ts – validateCommand implementation
const config = await configManager.getConfig();
const blockedCommands = config.blockedCommands || [];

const allCommands = this.extractCommands(command);
for (const cmd of allCommands) {
    if (blockedCommands.includes(cmd)) {
        return false;           // command is blocked
    }
}
return true;                    // otherwise allowed – no path check

```

The terminal skill forwards the raw command string directly to the OS shell after this optional command check. Because the shell executes with the host user's privileges, commands like `cat /etc/passwd` or `ls /private/var` succeed even when those paths fall outside the `allowedDirectories` list.

## Key Differences Between Security Layers

| Security Feature | Enforcement Scope | Configuration Field | Primary Validation File |
|-----------------|-------------------|---------------------|-------------------------|
| **File-System Access** | Restricts read/write operations to specific directories | `allowedDirectories` | [`src/tools/filesystem.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/filesystem.ts) (`validatePath`) |
| **Command Execution** | Blocks specific command names only | `blockedCommands` | [`src/command-manager.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/command-manager.ts) (`validateCommand`) |

### File-System Sandbox Characteristics

- **Path resolution**: Resolves symlinks and relative paths before validation
- **Root bypass**: Empty array or root path disables restrictions
- **Scope**: Applies only to MCP file-system tool calls

### Command Execution Characteristics

- **Name-based filtering**: Checks only the executable name, not arguments or paths
- **Shell inheritance**: Commands run in the host environment with full user permissions
- **No path validation**: `allowedDirectories` is never checked during command execution

## Configuration Files and Validation Logic

The security model relies on configuration definitions in [`src/config-field-definitions.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/config-field-definitions.ts), which declares both `allowedDirectories` and `blockedCommands` with their respective descriptions. The [`src/config-manager.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/config-manager.ts) file maintains these values in memory, defaulting `allowedDirectories` to an empty array (unrestricted) and `blockedCommands` to an empty array (no blocks).

```typescript
// Conceptual flow showing the security bypass
async function runTerminalCommand(cmd: string) {
    if (!await commandManager.validateCommand(cmd)) {
        throw new Error('Blocked command');
    }
    // No path validation – the OS shell receives the raw string.
    return execShell(cmd);
}

```

This architecture mirrors the design philosophy of many "assistant-in-the-loop" developer tools: file-system operations receive sandboxing to prevent accidental data corruption, while terminal access remains unrestricted to preserve the full power of the command line.

## Summary

- **File-system sandbox**: The `allowedDirectories` configuration restricts only file-system API calls (`readFile`, `writeFile`, etc.) through path validation in [`src/tools/filesystem.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/filesystem.ts).
- **Terminal bypass**: Terminal commands execute through the OS shell without path validation, bypassing the `allowedDirectories` restrictions entirely.
- **Separate command controls**: The only restriction on terminal commands is the optional `blockedCommands` array, which filters by command name rather than directory access.
- **Default permissiveness**: Both configurations default to empty arrays, meaning fresh installations have unrestricted file-system and command execution access unless explicitly configured otherwise.

## Frequently Asked Questions

### Does allowedDirectories prevent terminal commands from accessing sensitive directories?

No. The `allowedDirectories` restriction applies exclusively to file-system API operations in [`src/tools/filesystem.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/filesystem.ts). Terminal commands execute through the OS shell after only checking the `blockedCommands` list in [`src/command-manager.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/command-manager.ts), inheriting the host user's full filesystem permissions regardless of the allowed directories configuration.

### What happens if I set allowedDirectories to an empty array?

When `allowedDirectories` is empty or contains the root directory (`/` or `c:`), the `validatePath` function in [`src/tools/filesystem.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/filesystem.ts) bypasses all path checks and permits file operations anywhere on the system. This is the default configuration behavior.

### How do I restrict which commands can run in Desktop Commander MCP?

Use the `blockedCommands` configuration array defined in [`src/config-field-definitions.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/config-field-definitions.ts). The `commandManager.validateCommand` method extracts command names from the input string and rejects any that match entries in this list. However, this only blocks specific command names; it does not restrict which directories those commands can access.

### Why doesn't the security model restrict terminal commands to allowedDirectories?

The architecture treats file-system APIs and shell execution as fundamentally separate concerns. Enforcing directory restrictions on arbitrary shell commands would require complex sandboxing (such as chroot jails or containerization) beyond the scope of the current whitelist approach. The `blockedCommands` mechanism provides a lightweight alternative for preventing specific dangerous operations without limiting the flexibility of the terminal environment.