mirror of
https://github.com/tiennm99/coolify.git
synced 2026-04-17 19:21:36 +00:00
fix: prevent command injection in Docker Compose parsing - add pre-save validation
This commit addresses a critical security issue where malicious Docker Compose
data was being saved to the database before validation occurred.
Problem:
- Service models were saved to database first
- Validation ran afterwards during parse()
- Malicious data persisted even when validation failed
- User saw error but damage was already done
Solution:
1. Created validateDockerComposeForInjection() to validate YAML before save
2. Added pre-save validation to all Service creation/update points:
- Livewire: DockerCompose.php, StackForm.php
- API: ServicesController.php (create, update, one-click)
3. Validates service names and volume paths (string + array formats)
4. Blocks shell metacharacters: backticks, $(), |, ;, &, >, <, newlines
Security fixes:
- Volume source paths (string format) - validated before save
- Volume source paths (array format) - validated before save
- Service names - validated before save
- Environment variable patterns - safe ${VAR} allowed, ${VAR:-$(cmd)} blocked
Testing:
- 60 security tests pass (176 assertions)
- PreSaveValidationTest.php: 15 tests for pre-save validation
- ValidateShellSafePathTest.php: 15 tests for core validation
- VolumeSecurityTest.php: 15 tests for volume parsing
- ServiceNameSecurityTest.php: 15 tests for service names
Related commits:
- Previous: Added validation during parse() phase
- This commit: Moves validation before database save
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -104,6 +104,56 @@ function sanitize_string(?string $input = null): ?string
|
||||
return $sanitized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that a path or identifier is safe for use in shell commands.
|
||||
*
|
||||
* This function prevents command injection by rejecting strings that contain
|
||||
* shell metacharacters or command substitution patterns.
|
||||
*
|
||||
* @param string $input The path or identifier to validate
|
||||
* @param string $context Descriptive name for error messages (e.g., 'volume source', 'service name')
|
||||
* @return string The validated input (unchanged if valid)
|
||||
*
|
||||
* @throws \Exception If dangerous characters are detected
|
||||
*/
|
||||
function validateShellSafePath(string $input, string $context = 'path'): string
|
||||
{
|
||||
// List of dangerous shell metacharacters that enable command injection
|
||||
$dangerousChars = [
|
||||
'`' => 'backtick (command substitution)',
|
||||
'$(' => 'command substitution',
|
||||
'${' => 'variable substitution with potential command injection',
|
||||
'|' => 'pipe operator',
|
||||
'&' => 'background/AND operator',
|
||||
';' => 'command separator',
|
||||
"\n" => 'newline (command separator)',
|
||||
"\r" => 'carriage return',
|
||||
'>' => 'output redirection',
|
||||
'<' => 'input redirection',
|
||||
];
|
||||
|
||||
// Check for dangerous characters
|
||||
foreach ($dangerousChars as $char => $description) {
|
||||
if (str_contains($input, $char)) {
|
||||
throw new \Exception(
|
||||
"Invalid {$context}: contains forbidden character '{$char}' ({$description}). ".
|
||||
'Shell metacharacters are not allowed for security reasons.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Additional pattern-based checks for complex attack vectors
|
||||
// Check for command substitution patterns: $(command) or `command`
|
||||
if (preg_match('/\$\(|\$\{|`/', $input)) {
|
||||
throw new \Exception(
|
||||
"Invalid {$context}: command substitution patterns detected. ".
|
||||
'This is not allowed for security reasons.'
|
||||
);
|
||||
}
|
||||
|
||||
return $input;
|
||||
}
|
||||
|
||||
function generate_readme_file(string $name, string $updated_at): string
|
||||
{
|
||||
$name = sanitize_string($name);
|
||||
|
||||
Reference in New Issue
Block a user