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.tsand stored in theblockedCommandsconfiguration field CommandManager.extractCommandsparses complex Bash syntax including$()and backticks to identify all executable componentsCommandManager.validateCommand(lines 29-53 ofsrc/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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →