security: prevent bare wildcard '*' from matching all commands

Add validation to reject bare wildcards for security:
- matches_pattern(): return False if pattern == '*'
- validate_project_command(): reject name == '*' with clear error
- Added 4 new tests for bare wildcard rejection

This prevents a config with  from matching every command,
which would be a major security risk.

Tests: 140 unit tests passing (added 4 bare wildcard tests)
This commit is contained in:
Marian Paul
2026-01-22 12:40:31 +01:00
parent a9a0fcd865
commit d1dac1383d
2 changed files with 19 additions and 0 deletions

View File

@@ -371,6 +371,10 @@ def matches_pattern(command: str, pattern: str) -> bool:
Returns:
True if command matches pattern
"""
# Reject bare wildcards - security measure to prevent matching everything
if pattern == "*":
return False
# Exact match
if command == pattern:
return True
@@ -378,6 +382,9 @@ def matches_pattern(command: str, pattern: str) -> bool:
# Prefix wildcard (e.g., "swift*" matches "swiftc", "swiftlint")
if pattern.endswith("*"):
prefix = pattern[:-1]
# Also reject if prefix is empty (would be bare "*")
if not prefix:
return False
return command.startswith(prefix)
# Local script paths (./scripts/build.sh matches build.sh)
@@ -524,6 +531,10 @@ def validate_project_command(cmd_config: dict) -> tuple[bool, str]:
if not isinstance(name, str) or not name:
return False, "Command name must be a non-empty string"
# Reject bare wildcard - security measure to prevent matching all commands
if name == "*":
return False, "Bare wildcard '*' is not allowed (security risk: matches all commands)"
# Check if command is in the blocklist or dangerous commands
base_cmd = os.path.basename(name.rstrip("*"))
if base_cmd in BLOCKED_COMMANDS: