How Desktop Commander MCP Manages BlockedCommands Configuration and Security

Desktop Commander MCP protects users from dangerous shell commands by maintaining a configurable blocklist that is validated at runtime against every command token, with fail-closed defaults that prevent execution if validation fails.

Desktop Commander MCP is a Model Context Protocol (MCP) server that enables AI assistants to execute shell commands safely on local machines. The Desktop Commander MCP blockedCommands configuration provides a robust security layer that prevents unintentional execution of destructive system commands through a user-managed blocklist enforced at multiple levels of the application stack.

Configuration Schema Definition

The blocklist architecture begins with a strict schema definition in src/config-field-definitions.ts. The CONFIG_FIELD_DEFINITIONS object declares the blockedCommands field as an array type with explicit UI labeling:

blockedCommands: {
  label: 'Blocked Commands',
  description: 'This is your personal safety blocklist. If a command appears here, Desktop Commander will refuse to run it even if a prompt asks for it. …',
  valueType: 'array',
},

This schema serves as the single source of truth for both the data structure and the user interface. The UI layer in src/ui/config-editor/src/app.ts consumes this definition to render the configuration editor and display the current block count:

if (entry.key === 'blockedCommands') {
  return `${count} command${count === 1 ? '' : 's'} blocked`;
}

Default Blocklist Initialization and Persistence

When the application initializes, ConfigManager.init() in src/config-manager.ts (lines 13-60) checks for the existence of config.json. If the configuration file is missing, the manager generates a default blocklist containing high-risk system commands. According to the source code, the default blocked commands include sudo, dd, shutdown, iptables, and other destructive operations (lines 115-159).

The persistence layer ensures thread-safe updates through a serialized write chain. Every modification to the blocklist is immediately written to disk, preventing race conditions between the UI, API, and file system. The configuration path is defined in src/config.ts and consumed by the manager to locate the JSON store.

Runtime Command Validation

The security enforcement occurs in src/command-manager.ts through the validateCommand method (lines 29-61). This function acts as the runtime gatekeeper, executing a four-stage validation pipeline:

  1. Load current configuration via configManager.getConfig()
  2. Extract command tokens using the extractCommands utility, which parses pipelines, subshells ($()), and path prefixes
  3. Check against blocklist by comparing each extracted base command against the blockedCommands array
  4. Return boolean result indicating execution safety

Command Tokenization and Parsing

The validation logic handles complex shell constructs by decomposing command strings into individual executable tokens. The extractCommands function strips path prefixes to identify base command names, ensuring that /usr/bin/sudo matches the sudo entry in the blocklist. This parsing handles pipelines and command substitution to prevent circumvention through shell syntax.

Fail-Closed Security Behavior

The validation mechanism implements a fail-closed design. If validateCommand encounters any exception during configuration reading or command parsing, it logs the error and returns false, thereby blocking execution rather than risking a privilege escalation:

for (const cmd of allCommands) {
  if (blockedCommands.includes(cmd)) {
    return false; // Command is blocked
  }
}
return true; // No blocked command found

Security Guarantees and Defense-in-Depth

Desktop Commander MCP implements defense-in-depth by enforcing the blocklist at multiple architectural layers. The UI prevents users from configuring blocked commands through the settings editor, while the runtime validation in CommandManager blocks any backdoor execution attempts that might bypass the interface.

The system maintains user control over the security policy. Administrators can extend or shrink the blocklist through manual config.json edits or the graphical configuration interface. However, the default blocklist provides immediate protection against common destructive commands across Linux, macOS, and Windows environments.

Practical Implementation Examples

Extending the Blocklist Programmatically

To add a custom blocked command such as rm (recursive deletion), interact with the ConfigManager singleton:

// Assuming you have a reference to the config manager
const cfg = await configManager.getConfig();
cfg.blockedCommands = [...(cfg.blockedCommands ?? []), 'rm'];
await configManager.saveConfig(); // Persists to disk

Pre-Execution Validation

Always validate user-supplied strings before passing them to the execution engine:

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

async function runIfSafe(userCmd: string) {
  const safe = await commandManager.validateCommand(userCmd);
  if (!safe) {
    console.error('Refused to run a blocked command:', userCmd);
    return;
  }
  // Proceed with execution…
}

UI Integration

Display the current security status in custom interfaces by querying the configuration:

import { CONFIG_FIELD_DEFINITIONS } from '../../config-field-definitions';

const count = (await configManager.getConfig()).blockedCommands?.length ?? 0;
return <span>{count} command{count !== 1 ? 's' : ''} blocked</span>;

Summary

  • Desktop Commander MCP blockedCommands configuration is defined in src/config-field-definitions.ts and enforced through a unified schema that drives both data validation and UI rendering.
  • The default blocklist in src/config-manager.ts (lines 115-159) includes dangerous commands like sudo, dd, and shutdown, initialized automatically when no configuration exists.
  • Runtime validation in src/command-manager.ts (lines 29-61) extracts command tokens from complex shell strings and checks them against the blocklist using a fail-closed policy.
  • The architecture provides defense-in-depth by blocking commands in both the configuration UI and the execution runtime, with user-configurable policies that persist to config.json.

Frequently Asked Questions

How does Desktop Commander MCP handle blockedCommands configuration updates?

Configuration changes are persisted immediately through the ConfigManager.saveConfig() method, which writes to config.json using a serialized write chain to prevent race conditions. Updates take effect on the next command validation cycle, as commandManager.validateCommand() calls configManager.getConfig() to fetch the current blocklist at runtime.

What happens if a blocked command is detected in a pipeline or subshell?

The extractCommands utility parses the command string to identify tokens within pipelines (|) and command substitution ($()). Each extracted base command is validated independently against the blocklist. If any token matches a blocked entry, the entire validation returns false and execution is prevented.

Which commands are included in the default Desktop Commander MCP blockedCommands list?

According to the source code in src/config-manager.ts (lines 115-159), the default blocklist includes system-level destructive commands such as sudo, dd, shutdown, iptables, mkfs, and rm (with specific flags). This list covers common Unix/Linux commands capable of data destruction, privilege escalation, or system shutdown.

Can users completely disable the blockedCommands security feature?

While users can modify or empty the blockedCommands array through the configuration UI or by editing config.json directly, the validation infrastructure in CommandManager.validateCommand() always executes if the tool is invoked through the standard API. The security layer cannot be fully disabled without modifying the source code, ensuring that a baseline protection remains active even with an empty blocklist.

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 →