How to Customize the Command Blocklist in Desktop Commander MCP to Prevent Accidental Execution

Desktop Commander MCP prevents accidental execution of dangerous commands by validating every instruction against a user-configurable blockedCommands array that analyzes command basenames case-insensitively, including those hidden inside Bash substitutions and subshells.

Desktop Commander MCP, an open-source tool from the wonderwhy-er/DesktopCommanderMCP repository, implements a robust safety layer through its command blocklist feature. This system intercepts potentially destructive operations by analyzing command strings before execution. Understanding how to customize this blocklist allows you to tailor security policies to your specific workflow while maintaining protection against shell injection attacks.

Understanding the Blocklist Architecture

The blocklist system operates through three coordinated components defined in the source code.

Configuration Schema Definition

The blockedCommands field is formally declared in src/config-field-definitions.ts within the CONFIG_FIELD_DEFINITIONS structure. This configuration field accepts an array of command names (strings) that the system will refuse to execute. At runtime, the configManager retrieves these values to enforce security policies across all command operations.

Command Extraction and Parsing

Before validation occurs, CommandManager.extractCommands (located in src/command-manager.ts) parses the complete command string to identify every executable component. This function handles complex Bash syntax including command separators, subshells, process substitutions ($()), and backtick substitutions (` `). It returns a deduplicated list of base commands—extracting only the basename from full paths (converting /usr/bin/sudo to sudo).

Validation Logic

The CommandManager.validateCommand method (lines 29-53 in src/command-manager.ts) orchestrates the security check. It retrieves the current blocklist from the configuration, invokes extractCommands to identify all commands within the input string, and rejects the operation if any extracted command appears in the blocklist.

How the Blocklist Prevents Bypass Attacks

Traditional blocklists often fail when users embed dangerous commands inside shell substitutions. Desktop Commander MCP mitigates this by recursively analyzing command strings.

When you input a command like echo $(rm -rf /), the extractCommands function identifies both echo and rm as separate base commands. If rm resides in your blocklist, the validation fails regardless of how deeply nested the command appears. This protection extends to backtick substitutions and chained commands separated by semicolons or logical operators.

The matching algorithm operates case-insensitively and compares only command basenames, ensuring that /bin/RM and rm receive identical treatment.

Methods to Customize the Blocklist

You can modify the blockedCommands array through three primary methods depending on your integration needs.

Direct Configuration File Editing

The simplest approach involves editing the JSON configuration file directly. The configuration typically resides at ~/.desktop-commander/config.json (location may vary by installation).

{
  "blockedCommands": [
    "rm",
    "dd",
    "shutdown",
    "reboot",
    "mkfs"
  ],
  "allowedDirectories": [],
  "defaultShell": "/bin/bash",
  "telemetryEnabled": true,
  "fileReadLineLimit": 1000,
  "fileWriteLineLimit": 500
}

Add or remove command names from the blockedCommands array, then restart the application to apply changes.

Programmatic Configuration Updates

For dynamic environments, use the configManager API to update the blocklist without manual file editing:

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

async function addToBlocklist(cmd: string) {
  const cfg = await configManager.getConfig();
  cfg.blockedCommands = Array.from(
    new Set([...(cfg.blockedCommands ?? []), cmd.toLowerCase()])
  );
  await configManager.saveConfig(cfg);
}

// Block destructive commands
await addToBlocklist('rm');
await addToBlocklist('dd');

This approach ensures case consistency by converting inputs to lowercase before storage.

UI-Based Configuration

Desktop Commander MCP also exposes the Blocked Commands setting through its user interface. Access this panel to add command names through form fields without touching raw JSON or code.

Pre-Execution Validation

You can manually verify whether a command passes blocklist restrictions before attempting execution by using the validateCommand method directly:

import { commandManager } from './src/command-manager.ts';

async function canRun(command: string): Promise<boolean> {
  return await commandManager.validateCommand(command);
}

// Validation examples
console.log(await canRun('ls -la'));           // true (not blocked)
console.log(await canRun('rm -rf /tmp/*'));    // false if "rm" is blocked
console.log(await canRun('echo $(dd if=/dev/zero)')); // false if "dd" is blocked

This technique proves useful when building custom workflows that require explicit security checks before shell invocation.

Summary

  • The blocklist is defined in src/config-field-definitions.ts and stored in the blockedCommands configuration field
  • CommandManager.extractCommands parses complex Bash syntax including $() and backticks to identify all executable components
  • CommandManager.validateCommand (lines 29-53 of src/command-manager.ts) performs case-insensitive basename matching against the blocklist
  • The system prevents bypass attacks by analyzing commands inside substitutions and subshells
  • Customize the blocklist via JSON configuration files, programmatic API calls, or the application UI

Frequently Asked Questions

What file stores the blocklist configuration in Desktop Commander MCP?

The blocklist is stored in the application's JSON configuration file, typically located at ~/.desktop-commander/config.json. This file contains the blockedCommands array alongside other settings like allowedDirectories and defaultShell. You can edit this file directly or modify it through the configManager API.

How does Desktop Commander MCP handle commands inside subshells or substitutions?

The extractCommands method in src/command-manager.ts recursively parses command strings to detect commands within process substitutions ($()), backticks (` `), and subshells. It extracts the base command names from these nested structures and validates them against the blocklist, preventing attempts to bypass restrictions using shell tricks.

Can I block specific command arguments or only command names?

The blocklist matches only command basenames (e.g., rm rather than rm -rf). You cannot block specific arguments or flags directly through the blockedCommands array. To restrict particular usage patterns, you would need to implement additional validation logic outside the standard blocklist mechanism.

Is the blocklist case-sensitive?

No. Desktop Commander MCP treats the blocklist as case-insensitive. Whether you specify RM, rm, or /usr/bin/RM, the system normalizes all commands to lowercase before comparison. When adding commands programmatically, the code example demonstrates converting inputs to lowercase to maintain consistency.

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 →