Security: Command Blacklisting
Relevant source files
The following files were used as context for generating this wiki page:
The Dokku MCP server includes a crucial security feature to prevent the execution of potentially dangerous or destructive Dokku commands. This is achieved through a configurable command blacklist, which is checked before any command is sent to the Dokku instance via SSH. This mechanism acts as a primary safeguard, ensuring that only permitted command patterns can be processed.
The blacklisting system is part of a broader command validation process that also includes sanitization against dangerous characters, providing a multi-layered defense against command injection and unintended operations. The roadmap also includes a future idea to enforce an allow-list for a more restrictive, least-privilege security model.
Sources: internal/dokku-api/client.go:18-24, README.md:46-47
Configuration
The command blacklist can be configured at runtime through either a config.yaml file or environment variables. Environment variables take precedence over the configuration file.
Sources: README.md:120-122, scripts/setup-dokku-local.sh:86-92
Configuration Methods
| Method | Variable/Key | Example |
|---|---|---|
| Environment Variable | DOKKU_MCP_SECURITY_BLACKLIST | export DOKKU_MCP_SECURITY_BLACKLIST="destroy,uninstall,remove" |
config.yaml | security.blacklist | security: { blacklist: ["destroy", "uninstall", "remove"] } |
Sources: README.md:32-33, scripts/setup-dokku-local.sh:86-92
The configuration is loaded into the SecurityConfig struct.
// pkg/config/config.go
// SecurityConfig holds security-related settings
type SecurityConfig struct {
Blacklist []string `mapstructure:"blacklist"`
}
Sources: pkg/config/config.go:89-92
A default blacklist is configured in the local development setup script, demonstrating common destructive commands to block.
# scripts/setup-dokku-local.sh
# Security configuration
security:
blacklist:
- "destroy"
- "uninstall"
- "remove"
Sources: scripts/setup-dokku-local.sh:86-92
Command Validation Flow
All commands executed through the dokku-api client are first passed through the ValidateCommand function. This function performs security checks in a specific order:
- Blacklist Check: The command name is checked against the configured blacklist patterns.
- Dangerous Character Sanitization: The command name and its arguments are scanned for characters that could be used for command injection.
- Invalid Character Check: The command name is checked to ensure it only contains alphanumeric characters, dashes, and colons.
If any of these checks fail, an error is returned, and the command is not executed.
Sources: internal/dokku-api/client.go:18-53
The following diagram illustrates the validation process within the dokku-api client.
Core Implementation
The validation logic is centralized in the ValidateCommand function. The blacklist check is performed first.
// internal/dokku-api/client.go:25-53
// Blacklist first (runtime configuration)
for _, blacklistedPattern := range c.blacklistedCommands {
if strings.Contains(commandName, blacklistedPattern) {
return fmt.Errorf("command is blacklisted (matches pattern '%s'): %s", blacklistedPattern, commandName)
}
}
// Basic security validation - ensure no dangerous characters in command name
// These characters could be used for command injection
dangerousChars := []string{";", "&", "|", "`", "$", "(", ")", "{", "}", "<", ">", "\n", "\r"}
for _, char := range dangerousChars {
if strings.Contains(commandName, char) {
return fmt.Errorf("command name contains dangerous character '%s': %s", char, commandName)
}
}
// Validate arguments - ensure no dangerous characters
for i, arg := range args {
for _, char := range dangerousChars {
if strings.Contains(arg, char) {
return fmt.Errorf("argument %d contains dangerous character '%s': %s", i, char, arg)
}
}
}
Sources: internal/dokku-api/client.go:25-53
The blacklist itself is set on the client instance using the SetBlacklist method, which is typically called during client initialization.
// internal/dokku-api/client.go:300-304
// SetBlacklist sets the blacklisted commands for runtime security configuration
func (c *client) SetBlacklist(commands []string) {
c.blacklistedCommands = commands
c.logger.Debug("Command blacklist updated", "patterns", commands) // Audit trail
}
Sources: internal/dokku-api/client.go:300-304
Blacklist Matching Rules
The blacklist matching is based on a partial string match. The strings.Contains function is used, meaning if any part of the command name matches a blacklisted pattern, the command is blocked.
Sources: internal/dokku-api/client.go:27-29
Matching Examples
The following table, derived from the feature's test cases, illustrates how the matching works.
| Blacklist Patterns | Command to Validate | Result | Rationale |
|---|---|---|---|
[] (empty) | apps:list | Allowed | No patterns to match against. |
["apps:destroy"] | apps:destroy myapp | Blocked | The command name is an exact match for a blacklisted pattern. |
["destroy"] | apps:destroy myapp | Blocked | The command name contains a blacklisted pattern ("destroy"). |
["delete", "remove"] | apps:list | Allowed | The command name does not contain any of the blacklisted patterns. |
["rm", "delete", "destroy"] | apps:destroy myapp | Blocked | The command name contains one of the patterns in the list. |
Sources: internal/dokku-api/client_blacklist_test.go:26-61
Command Sanitization
In addition to the blacklist, ValidateCommand also prevents command injection by disallowing a set of dangerous characters in both the command name and its arguments. This provides a second layer of defense.
Sources: internal/dokku-api/client.go:34-53
Blocked Characters
The following characters are considered dangerous and will cause validation to fail if present in a command name or argument:
| Character | Name | Example Blocked Command |
|---|---|---|
; | Semicolon | apps:list;rm -rf / |
& | Ampersand | apps:list && whoami |
| ` | ` | Pipe |
` | Backtick | apps:list`whoami` |
$ | Dollar Sign | apps:list $(whoami) |
( | Open Parenthesis | apps:list $(whoami) |
) | Close Parenthesis | apps:list $(whoami) |
{ | Open Brace | cat /etc/passwd |
} | Close Brace | cat /etc/passwd |
< | Less Than | apps:list < /etc/hosts |
> | Greater Than | apps:list > /tmp/output |
\n | Newline | (multiline injection) |
\r | Carriage Return | (multiline injection) |
Sources: internal/dokku-api/client.go:35-35, internal/dokku-api/client_blacklist_test.go:65-98
Summary
The command blacklisting feature is a simple yet effective security control within the Dokku MCP server. By allowing operators to define a list of forbidden command patterns, it prevents high-risk operations like apps:destroy or plugin:uninstall from being executed through the MCP interface. This feature, combined with character sanitization, forms a robust first line of defense, reducing the risk of accidental data loss or malicious actions. It is configured via standard environment variables or a YAML file, making it easy to manage in different deployment environments.