validateCommandSecurity function
Validate a command for security issues.
Implementation
SecurityCheckResult validateCommandSecurity(String command) {
final violations = <String>[];
final warnings = <String>[];
final trimmed = command.trim();
if (trimmed.isEmpty) {
return const SecurityCheckResult(
passed: false,
violations: ['Empty command'],
);
}
// Check for dangerous zsh builtins
final baseCmd = trimmed.split(RegExp(r'\s+')).first;
if (_dangerousZshBuiltins.contains(baseCmd)) {
violations.add('Dangerous zsh builtin: $baseCmd');
}
// Check zf_ prefixed commands
if (baseCmd.startsWith('zf_')) {
violations.add('Dangerous zsh function: $baseCmd');
}
// Check for command substitution patterns
if (_commandSubstitutionPattern.hasMatch(command)) {
// Allow $() in single-quoted strings
final inSingleQuote = _isInSingleQuotes(
command,
_commandSubstitutionPattern,
);
if (!inSingleQuote) {
violations.add(
'Command substitution detected — use explicit commands instead',
);
}
}
// Check for backticks
if (_hasUnescapedBackticks(command)) {
violations.add('Backtick command substitution — use \$() instead');
}
// Check for control characters
if (RegExp(r'[\x00-\x08\x0e-\x1f]').hasMatch(command)) {
violations.add('Control characters detected in command');
}
// Check destructive patterns (warnings, not blocking)
if (_destructiveGitPatterns.hasMatch(command)) {
warnings.add('Destructive git operation detected');
}
if (_destructivePatterns.hasMatch(command)) {
warnings.add('Potentially destructive operation detected');
}
// Check for sleep > 2s (suggest background instead)
final sleepMatch = RegExp(r'\bsleep\s+(\d+)').firstMatch(command);
if (sleepMatch != null) {
final seconds = int.tryParse(sleepMatch.group(1)!) ?? 0;
if (seconds > 2) {
warnings.add('Sleep > 2s — consider running in background');
}
}
return SecurityCheckResult(
passed: violations.isEmpty,
violations: violations,
warnings: warnings,
);
}