Files
Nexus/scripts/scan_release_bundle.py
2026-07-08 22:31:31 +08:00

92 lines
2.3 KiB
Python

#!/usr/bin/env python3
"""Scan a Nexus release tarball for excluded paths and known env leak markers."""
from __future__ import annotations
import argparse
import tarfile
from pathlib import Path
BAD_PATH_PARTS = [
"node_modules",
".venv",
".venv-py314",
".venv-py312-codex",
"venv",
".pytest_cache",
"__pycache__",
".ruff_cache",
".cursor",
".playwright-mcp",
]
BAD_EXACT_SUFFIXES = [
"/2025.2",
"/=2025.2",
"/tmp/nexus-frontend.tar.gz",
]
BAD_FILE_SUFFIXES = [".bak-", ".pyc", ".pyo"]
ENV_MARKERS = [
b"ANTHROPIC_" + b"AUTH_TOKEN",
b"sk-" + b"PIR82dyeu",
b"CODEX_" + b"THREAD_ID=",
b"CODEX_" + b"SANDBOX_NETWORK_DISABLED=",
]
def bad_path(name: str) -> bool:
wrapped = f"/{name}/"
if any(f"/{part}/" in wrapped for part in BAD_PATH_PARTS):
return True
if any(name.endswith(suffix) for suffix in BAD_EXACT_SUFFIXES):
return True
if any(name.endswith(suffix) for suffix in BAD_FILE_SUFFIXES):
return True
return False
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("tarball", type=Path)
args = parser.parse_args()
tarball = args.tarball.resolve()
bad_entries: list[str] = []
marker_hits: list[str] = []
count = 0
with tarfile.open(tarball, "r:gz") as tf:
for member in tf.getmembers():
count += 1
if bad_path(member.name):
bad_entries.append(member.name)
if not member.isfile() or member.size > 2_000_000:
continue
fh = tf.extractfile(member)
data = fh.read() if fh else b""
if any(marker in data for marker in ENV_MARKERS):
marker_hits.append(member.name)
print(f"tarball={tarball}")
print(f"size_mb={tarball.stat().st_size / 1024 / 1024:.2f}")
print(f"entries={count}")
if bad_entries:
print("ERROR: excluded paths found:")
for name in bad_entries[:50]:
print(f"- {name}")
return 1
if marker_hits:
print("ERROR: known environment leak markers found:")
for name in marker_hits[:50]:
print(f"- {name}")
return 1
print("OK: release bundle looks clean")
return 0
if __name__ == "__main__":
raise SystemExit(main())