# How Desktop Commander MCP Prevents Symlink Traversal Attacks in File Operations

> Desktop Commander MCP prevents symlink traversal attacks using realpath, parent directory validation, and strict allow-list checks. Secure your file operations today.

- Repository: [Eduard Ruzga/DesktopCommanderMCP](https://github.com/wonderwhy-er/DesktopCommanderMCP)
- Tags: best-practices
- Published: 2026-08-01

---

**Desktop Commander MCP blocks symlink traversal attacks by resolving all paths to their canonical locations using `fs.realpath`, validating parent directories for non-existent targets, and enforcing strict allow-list checks before any file operation executes.**

Desktop Commander MCP implements a robust defense against symlink-based directory traversal attacks through its core filesystem validation layer. The `validatePath` function in [`src/tools/filesystem.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/filesystem.ts) applies multiple security checks to ensure AI agents can only access explicitly permitted directories, even when malicious symlinks are present within the allowed tree.

## Real-Path Resolution Blocks Symlink Redirection

The first line of defense occurs in [`src/tools/filesystem.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/filesystem.ts) at lines 39-47, where the `validatePath` function calls `fs.realpath` on the supplied absolute path. This system call resolves every component of the path chain—including intermediate symbolic links—to their **canonical filesystem targets** before any read or write operation proceeds.

## Handling Non-Existent Targets via Parent Directory Validation

When creating new files or directories that do not yet exist, the validation logic walks up the directory tree to find the deepest existing ancestor. As implemented in lines 58-86 of [`src/tools/filesystem.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/filesystem.ts), the code resolves this parent directory using `fs.realpath` and then reconstructs the intended path. This prevents attackers from exploiting a symlink placed in an allowed directory that points to a restricted location, then writing through a non-existent sub-path.

## Strict Allow-List Enforcement with isPathAllowed

After resolving the canonical path, the `isPathAllowed` function (lines 77-100) performs a normalized comparison against the configured `allowedDirectories`. The check uses **lower-cased paths with trailing-separator guards** to prevent partial-name matches, ensuring that `/home/user/projects` does not inadvertently permit access to `/home/user/projects-backup`.

## Explicit Rejection and Security Event Logging

If the resolved path falls outside all allowed directories, the system throws an explicit error and logs a `server_path_validation_error` event, as shown in lines 92-99. This **fail-closed approach** ensures that any attempt to traverse outside the sandbox—whether through symlinks, path normalization tricks, or parent directory references—results in immediate termination of the operation.

## Automated Security Testing

The repository includes a dedicated test suite in [`test/test-symlink-security.js`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/test/test-symlink-security.js) (lines 13-30) that simulates realistic attack scenarios. These tests create both directory and file symlinks pointing outside the allowed tree and assert that `validatePath` correctly blocks access, providing continuous verification of the security controls as documented in [`SECURITY.md`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/SECURITY.md) (lines 23-27).

## Configuration and Implementation Examples

To configure the security boundaries:

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

// Restrict operations to a specific safe directory
await configManager.setValue('allowedDirectories', ['/home/claude/projects']);

// Valid access within allowed directory
const safePath = await validatePath('projects/readme.md');
// Returns: '/home/claude/projects/readme.md'

```

Attack scenario demonstration:

```typescript
// Attempting to access a malicious symlink pointing to /etc/passwd
try {
  await validatePath('projects/link_to_passwd');
} catch (e) {
  console.error(e.message); 
  // Output: "Path not allowed: projects/link_to_passwd ..."
}

```

Run the security tests:

```bash
npm run test:test-symlink-security

# or

node test/test-symlink-security.js

```

## Summary

- **Canonical path resolution**: All paths are resolved using `fs.realpath` in [`src/tools/filesystem.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/filesystem.ts) before validation, eliminating symlink redirection.
- **Parent directory fallback**: For non-existent targets, the system validates the deepest existing ancestor to prevent symlink-based write attacks.
- **Strict allow-list checking**: The `isPathAllowed` function enforces configured boundaries with normalized, case-insensitive comparisons.
- **Comprehensive test coverage**: The [`test/test-symlink-security.js`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/test/test-symlink-security.js) suite continuously validates protection against symlink traversal vectors.
- **Security policy documentation**: Implementation details are documented in [`SECURITY.md`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/SECURITY.md) as a known risk mitigation.

## Frequently Asked Questions

### How does Desktop Commander MCP handle symlinks that point to allowed directories from outside locations?

When a symlink exists outside the allowed directories but points inside, the `validatePath` function resolves the symlink target using `fs.realpath`. Since the resolution happens before the allow-list check, the resulting canonical path must still fall within the configured `allowedDirectories` to proceed. If the symlink originates from a blocked location, the resolved path validation will fail.

### Can an attacker bypass the security by creating a symlink to a parent directory within an allowed folder?

No. The parent directory validation logic in [`src/tools/filesystem.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/filesystem.ts) (lines 58-86) resolves the deepest existing ancestor using `fs.realpath` before reconstructing the target path. If an attacker places a symlink named "parent" pointing to `/` inside an allowed directory, attempting to write to "parent/etc/passwd" would resolve the symlink to `/` and immediately fail the allow-list check.

### What happens if the allowed directory configuration contains symlinks?

The system normalizes all paths before comparison using `fs.realpath`. If the allowed directory itself contains symlinks, they are resolved to their canonical targets during the validation process, ensuring that the security boundaries align with actual filesystem locations rather than symlink aliases.

### Is the symlink protection tested automatically in CI/CD?

Yes. The repository includes [`test/test-symlink-security.js`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/test/test-symlink-security.js) which creates realistic symlink attack scenarios and asserts that `validatePath` blocks them. These tests should be run using `npm run test:test-symlink-security` or `node test/test-symlink-security.js` to verify that directory traversal protection remains effective across code changes.