#!/usr/bin/env python3 """ Security Scanner — Antigravity Awesome Skills Scans skill content for dangerous command patterns. Can be used as a module or run standalone: node tools/scripts/run-python.js tools/scripts/security_scanner.py node tools/scripts/run-python.js tools/scripts/security_scanner.py --strict """ from __future__ import annotations import argparse import re import sys from dataclasses import dataclass, field from pathlib import Path from _project_paths import find_repo_root from validate_skills import configure_utf8_output, parse_frontmatter # --------------------------------------------------------------------------- # Security pattern definitions # --------------------------------------------------------------------------- @dataclass(frozen=True) class SecurityPattern: code: str regex: str severity: str # error | warning | info description: str rationale: str SECURITY_PATTERNS: list[SecurityPattern] = [ SecurityPattern( code="SEC001", regex=r"rm\s+-[rf]{1,2}\s+/(?!\S)", severity="error", description="Destructive rm targeting root filesystem", rationale="rm -rf / deletes the entire filesystem; always destructive when unguarded.", ), SecurityPattern( code="SEC002", regex=r"curl\b[^\n]*\|\s*(?:bash|sh|zsh)", severity="error", description="Remote code execution: curl piped to shell", rationale="Pipes untrusted remote content directly into a shell without integrity verification.", ), SecurityPattern( code="SEC003", regex=r"wget\b[^\n]*\|\s*(?:sh|bash|zsh)", severity="error", description="Remote code execution: wget | sh", rationale="Same class of risk as curl | bash — downloads and executes without verification.", ), SecurityPattern( code="SEC004", regex=r"\bInvoke-Expression\b", severity="error", description="PowerShell RCE: Invoke-Expression", rationale="Evaluates arbitrary strings as PowerShell code; classic RCE vector.", ), SecurityPattern( code="SEC005", regex=r"\biex\b", severity="warning", description="PowerShell alias: iex (Invoke-Expression)", rationale="Alias for Invoke-Expression; context-dependent but frequently abused.", ), SecurityPattern( code="SEC006", regex=r"chmod\s+[0-7]*[2367](?:\s|$)", severity="warning", description="World-writable permission (other-write bit set)", rationale="Modes where the last octal digit is 2/3/6/7 grant write access to all users.", ), SecurityPattern( code="SEC007", regex=r"\beval\s*\(", severity="warning", description="Dynamic eval() detected", rationale="eval() can execute arbitrary code; acceptable only in controlled contexts.", ), SecurityPattern( code="SEC008", regex=r"base64\s+-d\b[^\n]*\|", severity="warning", description="Possible obfuscation via base64 decode + pipe", rationale="Pattern commonly used to hide malicious payloads from static scanners.", ), SecurityPattern( code="SEC009", regex=r"(password|passwd|secret|api[_-]?key)\s*=\s*['\"][^'\"]{4,}['\"]", severity="error", description="Hardcoded credential detected", rationale="Credentials in source files get committed and exposed in version history.", ), SecurityPattern( code="SEC010", regex=r"sudo\s+rm\s+-[rf]{1,2}", severity="warning", description="Privileged destructive deletion: sudo rm -rf", rationale="Privileged deletion amplifies blast radius; requires explicit authorization context.", ), SecurityPattern( code="SEC011", regex=r":\s*\(\)\s*\{\s*:|fork\s+bomb", severity="error", description="Fork bomb or infinite process spawner", rationale="Fork bombs consume all system resources and force a reboot.", ), SecurityPattern( code="SEC012", regex=r"dd\s+if=/dev/(?:zero|random|urandom)\s+of=/dev/[sh]d[a-z]", severity="error", description="Disk overwrite via dd", rationale="Overwrites raw disk device, causing permanent data loss.", ), ] # Lines containing this marker are excluded from scanning (project convention). # Prefix match covers both bare () and colon forms # () documented in skill-template.md. _ALLOWLIST_MARKERS = ("# security-allowlist", "