github wonderwhy-er/DesktopCommanderMCP v0.2.41
Release Notes — v0.2.41

4 hours ago

🔒 Security: directory traversal via symlink bypass — fixed

A symlink inside an allowed directory pointing to a restricted location could bypass isPathAllowed() when the target file didn't yet exist — fs.realpath() failed with ENOENT and the allowlist check fell back to the unresolved path. validatePath() now resolves the deepest existing ancestor and reconstructs the real path before checking the allowlist, so a symlink at /projects/evil → /etc/ can no longer trick a write of /projects/evil/crontab into landing at /etc/crontab.

Reported and patched by @sorlen008 — thank you. Fixed in #398 — closes #219 (open ~7 months).

🛟 Excel: read_file now accepts SheetName!A1:B2 range syntax

edit_block accepted range: "Sheet1!E5" but read_file rejected it as Invalid cell range — and the post-success help line in every read_file output literally showed {range: "Sheet1!E5"} as the example. Agents copying that example hit unrecoverable retry loops. The two parsers are now unified; quoted Excel-native forms ('My Sheet'!A1:B2), full-column ranges (A:B), and combined Sheet!Cells all work for both tools.

Fixed in #469. Thanks @dasein108.

🩹 File preview survives page refresh

The "Preview unavailable after page refresh" placeholder is gone for cases where preview content was actually available — read_file now embeds returned content in structuredContent so the widget can rehydrate, and unsupported file types fall back to raw escaped content instead of an error card. #472

⏱️ Startup hang on Windows / high-latency networks — fixed

On Windows + Node 24 / undici 7.x, AbortController.abort() doesn't always interrupt an in-progress TCP connect, so the feature flags fetch could hang for ~30s on every cold start (OS-level TCP timeout). Wrapped the fetch in Promise.race with a hard 3s timeout, added a 5s safety bound to waitForFreshFlags(), and added 6 regression tests including a broken-AbortController simulation.

Fixed in #467 — closes #465.

📁 list_directory: [NOT_FOUND] vs [DENIED]

Listing a nonexistent path used to report [DENIED], implying a permission problem. ENOENT now produces [NOT_FOUND] with a clear message and a ❓ icon in the directory preview UI. EPERM/EACCES/ETIMEDOUT still surface as [DENIED]. #468

✨ Gemini CLI extension skills

Extends the Gemini CLI extension support shipped in v0.2.40 with a proper skill page — guidance for agents on when to reach for Desktop Commander (persistent shells, long-running jobs, large local files, structured documents, SSH sessions, process management) with worked example workflows. #466

🧩 Claude Code plugin

Desktop Commander is now submittable as a Claude Code plugin — plugin metadata, README, and a skill guide so Claude knows when to use it for terminal work, file access, document handling, process management, and SSH. #457

🖱️ Cursor plugin metadata + one-click install

Cursor marketplace metadata, a branded install button, and a deeplink that opens Cursor with the MCP server config prefilled. #456, #462, #464

Contributors

@sorlen008, @dasein108, @edgarsskore, @wonderwhy-er — and thanks to the user in Australia who filed #465 with detailed logs that made the Windows timeout fix straightforward.

Don't miss a new DesktopCommanderMCP release

NewReleases is sending notifications on new releases.