# How to Configure Allowed Directories and Access Restrictions in Desktop Commander MCP

> Secure your Desktop Commander MCP by configuring allowed directories and access restrictions. Learn how to enforce path validation for read and write operations.

- Repository: [Eduard Ruzga/DesktopCommanderMCP](https://github.com/wonderwhy-er/DesktopCommanderMCP)
- Tags: how-to-guide
- Published: 2026-07-28

---

**Desktop Commander MCP restricts file-system access through the `allowedDirectories` array in its server configuration, enforcing path validation before any read or write operation.**

The `wonderwhy-er/DesktopCommanderMCP` repository implements a configurable security sandbox that limits which directories the Model Context Protocol (MCP) server can access. By manipulating the `allowedDirectories` setting, you can lock down file operations to specific project folders or grant unrestricted system access.

## Understanding the Configuration System

The security model centers on the **ConfigManager** singleton defined in [`src/config-manager.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/config-manager.ts). This module persists server settings to a [`config.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/config.json) file and maintains the **ServerConfig** schema.

According to the source code at lines 9-13, the configuration interface includes an optional `allowedDirectories` property:

```typescript
interface ServerConfig {
  allowedDirectories?: string[];
  // ... other settings
}

```

If the configuration file omits this property, the system initializes an empty array (`[]`) at line 182, which historically meant no restrictions. However, the filesystem tools implement additional fallback logic for safer defaults.

## How Path Validation Works

All file operations route through [`src/tools/filesystem.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/filesystem.ts), which implements a three-stage validation pipeline:

### Normalization and Subdirectory Checking

The `validatePath()` function expands `~` to the user's home directory, resolves absolute paths, and delegates access control to `isPathAllowed()` (lines 77-95). The validation logic follows these rules:

- **Full access mode**: If `allowedDirectories` contains `"/"` or is empty, validation short-circuits and grants access.
- **Directory comparison**: Each allowed path is normalized (lowercased on Windows, trailing separators stripped) and the target is checked for exact equality or subdirectory membership using `startsWith(normalizedAllowedDir + path.sep)`.
- **Windows drive support**: An entry like `c:` grants access to the entire C: drive.

The `getAllowedDirs()` function (lines 113-125) retrieves the current array from ConfigManager. If the configuration is missing, it falls back to the user's home directory and persists that default immediately.

### Symlink Security Handling

To prevent directory traversal attacks via symbolic links, the resolver at lines 58-71 implements a defensive strategy:

1. Attempt `fs.realpath` on the target path.
2. If the target does not exist (ENOENT), resolve the parent directory's real path and re-append the filename.
3. Validate the final canonical path against the allowed list before any write operation occurs.

This ensures attackers cannot place a symlink inside an allowed directory that points outside the whitelist.

## Setting Up Allowed Directories

You can configure restrictions via the JSON config file or programmatically through the ConfigManager API.

### Configuration via config.json

Edit the server configuration file to specify absolute paths:

```json
{
  "allowedDirectories": [
    "/home/alice/projects",
    "/var/log/app-data",
    "~/Documents"
  ]
}

```

Restart the server after modifying this file, or use the web UI component located in [`src/ui/config-editor/src/app.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/ui/config-editor/src/app.ts) to update settings dynamically.

### Programmatic Configuration

Tools and integrations can modify restrictions at runtime using the ConfigManager singleton:

```typescript
import { configManager } from './config-manager.js';

// Restrict to specific project directories
await configManager.setValue('allowedDirectories', [
  '/home/user/workspace',
  '~/Downloads'
]);

```

For non-blocking updates that don't await disk persistence:

```typescript
configManager.setValueNonBlocking('allowedDirectories', ['/tmp/sandbox']);

```

### Granting Full Access

To remove all directory restrictions, set the array to empty or include the root path:

```typescript
// Method 1: Empty array (no restrictions)
await configManager.setValue('allowedDirectories', []);

// Method 2: Root access (Unix)
await configManager.setValue('allowedDirectories', ['/']);

// Method 3: Full drive access (Windows)
await configManager.setValue('allowedDirectories', ['c:']);

```

## Security Enforcement and Error Handling

When `isPathAllowed()` returns `false`, the system throws a validation error at lines 91-100 that includes the configured whitelist for debugging. The error is captured for telemetry via `capture('server_path_validation_error', …)` before aborting the operation.

You can manually verify path permissions before operations:

```typescript
import { isPathAllowed } from './tools/filesystem.js';

const permitted = await isPathAllowed('/sensitive/etc/passwd');
if (!permitted) {
  console.error('Access denied: Path outside allowed directories');
  process.exit(1);
}

```

## Summary

- Desktop Commander MCP uses the `allowedDirectories` array in [`config.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/config.json) to whitelist accessible paths.
- The **ConfigManager** singleton handles persistence, while [`src/tools/filesystem.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/filesystem.ts) enforces validation through `validatePath()` and `isPathAllowed()`.
- Path validation normalizes entries, supports Windows drive letters, and checks for subdirectory membership.
- Symlink attacks are mitigated by resolving parent directories when targets don't exist.
- Configure restrictions via JSON, web UI, or programmatically using `configManager.setValue()`.

## Frequently Asked Questions

### How do I restrict Desktop Commander MCP to a single project folder?

Add the absolute path to your project directory to the `allowedDirectories` array in [`config.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/config.json). The server will block any file operation outside that directory tree. For example: `["/home/user/myproject"]` permits access to `/home/user/myproject` and all subdirectories, but denies access to `/home/user/other`.

### What happens if I leave allowedDirectories empty?

An empty array historically grants full system access on some versions, but recent implementations in [`src/tools/filesystem.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/filesystem.ts) fall back to the user's home directory when the array is undefined or empty. To ensure unrestricted access, explicitly set the array to `["/"]` on Unix or `["c:"]` on Windows.

### Does Desktop Commander MCP follow symbolic links outside allowed directories?

No. The validation logic in [`src/tools/filesystem.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/filesystem.ts) resolves the canonical path using `fs.realpath` before checking permissions. If a symlink points outside the allowed directory tree, the resolved path fails the `isPathAllowed()` check and the operation is aborted with a validation error.

### Can I update allowed directories without restarting the server?

Yes. Use `configManager.setValue('allowedDirectories', [...])` for synchronous persistence, or `setValueNonBlocking()` for immediate in-memory updates. The web UI in [`src/ui/config-editor/src/app.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/ui/config-editor/src/app.ts) also supports live configuration changes without requiring a server restart.