diff --git a/scripts/forge_health_check.py b/scripts/forge_health_check.py index 382b920a2..e0bc821e5 100755 --- a/scripts/forge_health_check.py +++ b/scripts/forge_health_check.py @@ -98,9 +98,23 @@ class HealthReport: self.passed = False +EXCLUDED_PATH_SEGMENTS = frozenset({ + ".cache", "__pycache__", ".venv", "venv", "site-packages", + ".local/share/uv", "node_modules", ".git", ".tox", +}) + + +def _is_excluded_path(path: Path) -> bool: + """Skip cache, venv, and package-manager directories.""" + parts = set(path.parts) + return not parts.isdisjoint(EXCLUDED_PATH_SEGMENTS) + + def scan_orphaned_bytecode(root: Path, report: HealthReport) -> None: """Detect .pyc files without corresponding .py source files.""" for pyc in root.rglob("*.pyc"): + if _is_excluded_path(pyc): + continue py = pyc.with_suffix(".py") if not py.exists(): # Also check __pycache__ naming convention @@ -142,6 +156,12 @@ def _is_sensitive_filename(name: str) -> bool: lower = name.lower() if lower == ".env.example": return False + # Skip stylesheet and documentation artifacts + if lower.endswith(".css"): + return False + # Skip scanner tooling — these are detectors, not secrets + if lower in {"secret_scan.py", "secret_scanner.py"}: + return False if any(pat in lower for pat in SENSITIVE_FILE_PATTERNS): return True if any(lower.startswith(pref) for pref in SENSITIVE_NAME_PREFIXES): @@ -156,6 +176,8 @@ def scan_sensitive_file_permissions(root: Path, report: HealthReport, fix: bool for fpath in root.rglob("*"): if not fpath.is_file(): continue + if _is_excluded_path(fpath): + continue # Skip test files — real secrets should never live in tests/ if "/tests/" in str(fpath) or str(fpath).startswith(str(root / "tests")): continue