How to Configure Blocked Commands in Desktop Commander MCP to Prevent Dangerous Shell Execution
Desktop Commander MCP prevents accidental execution of dangerous shell commands through a user-editable blockedCommands configuration array that is checked against every submitted command before execution.
The Desktop Commander MCP server provides a robust safety mechanism that protects users from destructive or malicious shell operations. By maintaining a configurable blocklist of prohibited commands, the system intercepts risky inputs before they reach the operating system. This guide explains how to customize the blockedCommands setting in Desktop Commander MCP using both programmatic APIs and the built-in settings interface.
Where the Blocklist Is Defined and Stored
The blocked commands configuration resides in a JSON file managed by ConfigManager in src/config-manager.ts (line 63). The configuration field itself is formally declared in src/config-field-definitions.ts (lines 11-15), which exposes it to the settings UI as the Blocked Commands field.
When Desktop Commander MCP initializes, ConfigManager.init() loads this file and merges it with default values. Changes are persisted via saveConfig() (lines 70-101), ensuring your safety preferences survive restarts.
How Command Blocking Works at Runtime
The enforcement mechanism lives in src/command-manager.ts (lines 231-247). Here's the execution flow:
- Command parsing:
CommandManager.extractCommands()parses the submitted command string to identify base commands - Blocklist check: Each extracted command is tested against
config.blockedCommandsusingblockedCommands.includes() - Rejection or execution: If any match is found, the command is rejected with a "blocked by configuration" error; otherwise, execution proceeds
This check occurs before any shell subprocess is spawned, providing fail-safe protection.
Default Blocked Commands in Desktop Commander MCP
The ConfigManager.getDefaultConfig() method (lines 25-69) ships with a comprehensive safety blocklist including:
- Privilege escalation:
sudo,su - Data destruction:
dd,rm,mkfs,fdisk - System control:
shutdown,reboot,poweroff,halt - Network security:
iptables,ufw - Process management:
kill,killall,pkill
These defaults represent high-risk operations that could damage data or compromise system stability.
Method 1: Edit Blocked Commands Programmatically
For automation or integration scenarios, modify the blocklist directly through the ConfigManager API:
import { configManager } from './config-manager.js';
// Initialize the configuration system
await configManager.init();
// Retrieve current blocked commands
const currentBlocklist = configManager.getValue('blockedCommands') as string[];
// Add custom dangerous command (e.g., database wipe utility)
const updatedBlocklist = [...new Set([...currentBlocklist, 'dropdb', 'redis-cli'])];
// Persist to configuration file
await configManager.setValue('blockedCommands', updatedBlocklist);
Key implementation details:
getValue('blockedCommands')retrieves the string array from merged config (defaults + user overrides)setValue()triggerssaveConfig()to write to the JSON file- The
Setdeduplication prevents redundant entries
Method 2: Configure Blocked Commands via Settings UI
For manual configuration without code:
- Open Desktop Commander MCP's Settings panel
- Locate the Blocked Commands field (labeled "Blocked Commands" with description referencing "personal safety blocklist")
- Edit the comma-separated or line-delimited list of commands
- Click Save — the UI writes through the same
ConfigManagerinterface
The UI field definition in src/config-field-definitions.ts ensures type safety: the input is validated as a string array before persistence.
Method 3: Direct Configuration File Editing
The underlying storage location depends on your environment. Inspect or modify directly:
# Default location (verify with your CONFIG_FILE path)
CONFIG_PATH="$HOME/.desktop-commander/config.json"
# View current blocklist
jq '.blockedCommands' "$CONFIG_PATH"
# Add entry with in-place editing
jq '.blockedCommands += ["systemctl"]' "$CONFIG_PATH" > tmp.json && mv tmp.json "$CONFIG_PATH"
Verifying Blocked Command Enforcement
Test that your configuration is active using the CommandManager interface:
import { commandManager } from './command-manager.js';
import { configManager } from './config-manager.js';
await configManager.init();
await configManager.setValue('blockedCommands', ['rm', 'curl', 'wget']);
// This will be rejected
const result = await commandManager.runCommand('rm -rf /important/data');
console.log(result.blocked); // → true
console.log(result.blockReason); // → "blocked by configuration"
// This will proceed (unless also blocked)
const safeResult = await commandManager.runCommand('ls -la /tmp');
console.log(safeResult.blocked); // → false
The blocked boolean and blockReason string in the result object provide clear feedback for logging or UI presentation.
Best Practices for Blocked Commands Configuration
- Start restrictive, then relax: Begin with the default blocklist and remove entries only when specific workflows require them
- Block command bases, not arguments: The parser checks
rminrm -rf /, not the full string — blockingrmcatches all variants - Version-control your config: Track
config.jsonchanges to audit safety policy evolution - Test in isolation: Verify blocklist changes with non-destructive commands before relying on protection
Summary
- Desktop Commander MCP's
blockedCommandsarray insrc/config-manager.tsprovides configurable shell command protection - Default dangerous commands are defined in
getDefaultConfig()(lines 25-69) and enforced inCommandManager(lines 231-247) - Modify the blocklist via
ConfigManager.setValue(), the Settings UI, or direct JSON editing - All changes persist through
saveConfig()and load automatically on server restart - The
blockedproperty in command results confirms when protection has activated
Frequently Asked Questions
How do I remove a command from the blocked list if I need it for my workflow?
Edit the configuration through any of the three methods: use configManager.setValue('blockedCommands', updatedArray) to filter out the specific command, delete it from the Settings UI textarea, or modify the JSON file directly. Restart Desktop Commander MCP if you edited the file outside the running process.
Does blocking sudo prevent all privilege escalation?
Blocking sudo catches the common case, but determined users could bypass with su, doas, or direct /bin/su paths. Extend your blocklist to include all privilege elevation binaries relevant to your system. The default configuration includes both sudo and su for this reason.
Where is the configuration file located on disk?
The path is determined by the CONFIG_FILE constant in src/config-manager.ts (line 63), typically resolving to ~/.desktop-commander/config.json. Verify your specific path by logging configManager.configPath after initialization, as it may vary by operating system or environment variables.
Can I block specific command arguments rather than entire commands?
No — Desktop Commander MCP's protection operates on the base command name extracted by extractCommands() in src/command-manager.ts. This design choice prevents circumvention through path variations (/bin/rm vs rm) but means you cannot block rm -rf / while allowing rm /tmp/safe. Use broader system-level controls for argument-level restrictions.
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 →