5769c1cd22
- Auto-Registration-Bug behoben (register_project/get_project_id/resolve_project Trennung) - 25 Tests gruen (Pytest) - block_compactor-Tool refactored (Option B: Soft-Check statt Hard-Block) - 4 Restbaustellen gefixt - DB-Schema: plugin_settings-Tabelle hinzugefuegt - 3 Schattenprojekte aus DB geloescht - Plan v3 + Refactor-Plan + Worklog dokumentiert
70 lines
2.9 KiB
Python
70 lines
2.9 KiB
Python
"""Safety rules: Plan Mode, permissions, dangerous actions."""
|
|
import re
|
|
|
|
# Patterns for potentially dangerous terminal commands
|
|
DANGEROUS_PATTERNS = [
|
|
r"rm\s+-rf\s+/.*",
|
|
r"sudo\s+rm",
|
|
r"mkfs\.",
|
|
r"dd\s+if=",
|
|
r">\s*/dev/sd",
|
|
r"chmod\s+777",
|
|
r"git\s+push\s+.*\s+main",
|
|
r"git\s+push\s+.*\s+master",
|
|
r"docker\s+rm\s+-f",
|
|
r"docker\s+volume\s+rm",
|
|
]
|
|
|
|
# Pattern to detect Base64-like values that may be secrets
|
|
# Matches: api_key=XXXX, token:XXXX, secret="XXXX", etc.
|
|
_SECRET_VALUE = re.compile(
|
|
r'(?:api|access|secret|token|key|password|auth)'
|
|
r'[-_]?'
|
|
r'(?:key|token|secret)?'
|
|
r'\s*[=:]\s*'
|
|
r'[\'"]?'
|
|
r'[A-Za-z0-9+/=_-]{20,}'
|
|
r'[\'"]?'
|
|
)
|
|
|
|
def is_dangerous_command(command: str) -> bool:
|
|
"""Check if a terminal command matches known dangerous patterns."""
|
|
for pattern in DANGEROUS_PATTERNS:
|
|
if re.search(pattern, command, re.IGNORECASE):
|
|
return True
|
|
return False
|
|
|
|
def contains_secret(text: str) -> bool:
|
|
"""Check if text likely contains a hardcoded secret."""
|
|
return bool(_SECRET_VALUE.search(text))
|
|
|
|
|
|
def redact_secrets(text: str) -> str:
|
|
"""Return text with obvious credential-looking assignments redacted.
|
|
|
|
This is defensive output hygiene, not a credential scanner. It must only be
|
|
applied to data already produced by approved checks.
|
|
"""
|
|
return _SECRET_VALUE.sub(lambda m: m.group(0).split('=')[0] + '=<REDACTED>' if '=' in m.group(0) else '<REDACTED_SECRET_LIKE_VALUE>', text)
|
|
|
|
|
|
# Credential-discovery commands are never legitimate for this plugin.
|
|
# This is not a scanner for collecting credentials; it is a pre-execution guard
|
|
# for commands/plans that attempt credential discovery.
|
|
CREDENTIAL_DISCOVERY_PATTERNS = [
|
|
r"\b(grep|rg|ripgrep|find|cat|sed|awk|python|python3|node|perl)\b.*\b(password|passwd|pwd|token|secret|api[_-]?key|access[_-]?key|private[_-]?key|credential|auth|cookie|session)\b",
|
|
r"\b(password|passwd|pwd|token|secret|api[_-]?key|access[_-]?key|private[_-]?key|credential|auth|cookie|session)\b.*\b(grep|rg|ripgrep|find|cat|sed|awk|python|python3|node|perl)\b",
|
|
r"\b(env|printenv|set)\b.*\b(password|token|secret|key|credential|auth)\b",
|
|
r"\b\.env(\.|\b|$)",
|
|
r"\b(config|settings|application|appsettings).*\b(password|token|secret|credential|auth)\b",
|
|
r"\b(browser|chrome|firefox|localstorage|sessionstorage|cookie|cookies)\b.*\b(password|token|secret|credential|auth|session)\b",
|
|
r"\bfind\b.*\b(login|credential|credentials|password|token|secret)\b",
|
|
r"\b(read|open|dump|extract|list|locate|recover|discover|search)\b.*\b(login|credential|credentials|password|token|secret|cookie|session)\b",
|
|
]
|
|
|
|
|
|
def is_credential_discovery_command(command: str) -> bool:
|
|
"""Return True if a command/plan appears to look for credential material."""
|
|
c = str(command or "").lower()
|
|
return any(re.search(pattern, c, re.IGNORECASE) for pattern in CREDENTIAL_DISCOVERY_PATTERNS)
|