DesktopCommander MCP allowedDirectories Security: Implications and Bypass Techniques

The allowedDirectories setting in DesktopCommander MCP serves as the primary security boundary for filesystem access, where an empty array or root path entry disables all restrictions, and symlink timing attacks can potentially circumvent path validation if the parent directory resolution is bypassed.

DesktopCommander MCP uses the allowedDirectories configuration to sandbox file operations and prevent unauthorized access to sensitive host files. While this mechanism provides essential isolation, misconfigurations or edge cases in the validation logic can expose the entire filesystem to compromise. Understanding how the server validates paths in src/tools/filesystem.ts is critical for securing MCP deployments.

How allowedDirectories Validates Filesystem Access

The core enforcement logic resides in isPathAllowed within src/tools/filesystem.ts (lines 77-98). This function normalizes candidate paths and checks them against the configured allowlist using a strict prefix match.

The validation follows these rules:

  • Empty array ([]): Immediately grants unrestricted access. The check if (allowedDirectories.includes('/') || allowedDirectories.length === 0) short-circuits all restrictions at lines 78-82.
  • Root path (/ on Unix or C: on Windows): Treated identically to an empty array, effectively disabling the sandbox.
  • Specific absolute paths: Only paths that are exactly the allowed directory or its subdirectories are permitted. The comparison normalizes both sides, strips trailing separators, and verifies using startsWith(normalizedAllowedDir + path.sep) to prevent partial string matches at lines 89-105.

The getAllowedDirs function (lines 110-125) reads the user configuration and falls back to the user's home directory if the setting is missing, storing the resolved list back to the config for persistence.

Security Implications of Misconfigured Directories

The allowedDirectories setting controls the attack surface available to MCP clients. When misconfigured, it exposes the host to several risks:

  • Unrestricted access: As documented in src/config-field-definitions.ts (lines 16-20), an empty array means "Desktop Commander can access your entire filesystem." This default permissive behavior prioritizes ease of use over security.
  • Secret exposure: Without directory restrictions, compromised MCP processes can read SSH keys, password stores, and system configuration files.
  • System tampering: Write access to system directories allows attackers to modify shell profiles, install persistence mechanisms, or alter executable paths.

Filesystem Restriction Bypass Techniques

Even with proper configuration, certain patterns can circumvent the sandbox:

The validatePath function (lines 258-285) attempts to mitigate symlink attacks by resolving the real filesystem path before validation. However, a race condition remains possible:

"When the full path doesn't exist (e.g., writing a new file), resolve the parent directory to detect symlinks in the path chain. Without this, an attacker could create a symlink inside an allowed directory pointing to a restricted location, then write to a non-existent file through that symlink — bypassing the directory restriction check." (lines 58-64).

If an attacker creates a symlink within an allowed directory pointing outside the sandbox, and then swaps that symlink after validation but before the file operation executes, the write operation could target arbitrary filesystem locations.

Configuration Tampering

An attacker with access to the configuration manager can simply clear the allowedDirectories array. The test file test/test-allowed-directories.js (lines 11-33) demonstrates that setting the array to empty disables all path checks, granting immediate access to sensitive files like /etc/passwd.

Root Path Inclusion

Adding '/' (or 'C:' on Windows) to the allowed list triggers the early-return logic in isPathAllowed, effectively disabling the security boundary without technically emptying the array.

Practical Code Examples

When properly configured, the server restricts access to designated subtrees:

// Restrict DesktopCommander to the user's home directory only
await configManager.setValue('allowedDirectories', [os.homedir()]);

Attempting to access files outside the allowed list throws an error:

try {
  const content = await readFileFromUrl('file:///etc/passwd');
} catch (e) {
  console.error(e.message); // → Path not allowed: /etc/passwd …
}

A theoretical bypass attempt using symlink timing:

import { execSync } from 'child_process';
const allowed = '/home/user/allowed';
await fs.mkdir(allowed, { recursive: true });
// Create symlink pointing outside the sandbox
await execSync(`ln -s /etc/secret ${allowed}/link`);

// Validation resolves the parent (/home/user/allowed) as safe,
// but if the symlink is swapped between validation and write...
await validatePath(`${allowed}/link`);

Summary

  • DesktopCommander MCP relies on allowedDirectories as its primary security boundary for filesystem operations.
  • Empty arrays or root paths disable all restrictions, granting the server full host filesystem access.
  • The validatePath function resolves parent directories to mitigate symlink attacks, though race conditions remain a theoretical bypass vector.
  • Configuration stored in mutable locations can be cleared by attackers, removing the sandbox entirely.
  • Production deployments should use specific absolute paths with immutable configuration to maintain the principle of least privilege.

Frequently Asked Questions

What happens if allowedDirectories is empty in DesktopCommander MCP?

When allowedDirectories is set to an empty array [], DesktopCommander MCP disables all filesystem restrictions. According to the source code in src/config-field-definitions.ts, this configuration allows the server to "access your entire filesystem," making it suitable only for trusted local development environments.

Yes, under specific timing conditions. While validatePath in src/tools/filesystem.ts resolves the parent directory to detect symlinks pointing outside the allowed tree, a race condition exists where an attacker could swap a benign file for a malicious symlink after validation but before the file operation executes. This could redirect writes to restricted locations like /etc/passwd or system directories.

Why does validatePath check the parent directory before validating the full path?

The parent directory check prevents a specific attack vector where an attacker creates a symlink inside an allowed directory pointing to a restricted location, then attempts to write to a non-existent file through that symlink. By resolving the parent directory's real path first, the server ensures that the directory portion of the path actually resides within the allowed bounds before proceeding with the operation.

Is it safe to include the root path (/) in allowedDirectories?

No, including the root path '/' (or 'C:' on Windows) in allowedDirectories effectively disables the security sandbox. The isPathAllowed function contains an explicit check at lines 78-82 that short-circuits validation when the root path is present, treating it identically to an empty configuration array and granting unrestricted filesystem access.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →