Scan staged workspace snapshots for secrets
This commit is contained in:
@@ -26,6 +26,23 @@ _WINDOWS_RESERVED_NAMES = {"CON", "PRN", "AUX", "NUL"} | {
|
||||
for prefix in ("COM", "LPT")
|
||||
for number in range(1, 10)
|
||||
}
|
||||
_KNOWN_SECRET = re.compile(
|
||||
r"gsk_[A-Za-z0-9]{20,}|sk-[A-Za-z0-9_-]{20,}|"
|
||||
r"gh[pousr]_[A-Za-z0-9]{20,}|github_pat_[A-Za-z0-9_]{20,}|"
|
||||
r"AKIA[0-9A-Z]{16}|-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----"
|
||||
)
|
||||
_SECRET_ASSIGNMENT = re.compile(
|
||||
r"(?im)\b(?:api[_-]?key|secret(?:[_-]?key)?|password|"
|
||||
r"access[_-]?token|auth[_-]?token|private[_-]?key)\b\s*[:=]\s*"
|
||||
r"[\"'](?P<value>[^\"'\r\n]{12,})[\"']"
|
||||
)
|
||||
_PLACEHOLDER_VALUES = {
|
||||
"your_api_key_here",
|
||||
"your-secret-here",
|
||||
"replace-me",
|
||||
"changeme",
|
||||
"placeholder",
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -54,6 +71,18 @@ def _is_reparse_point(path: Path) -> bool:
|
||||
return bool(is_junction()) if is_junction is not None else False
|
||||
|
||||
|
||||
def _contains_credential(content: bytes) -> bool:
|
||||
text = content.decode("utf-8", errors="replace")
|
||||
if _KNOWN_SECRET.search(text):
|
||||
return True
|
||||
for match in _SECRET_ASSIGNMENT.finditer(text):
|
||||
value = match.group("value").strip()
|
||||
if value.casefold() in _PLACEHOLDER_VALUES or value.startswith(("$", "${", "<")):
|
||||
continue
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _safe_relative_path(root: Path, value: str) -> tuple[Path, str]:
|
||||
if (
|
||||
not isinstance(value, str)
|
||||
@@ -152,6 +181,10 @@ def stage_selected_files(
|
||||
content = input_file.read(MAX_SNAPSHOT_FILE_BYTES + 1)
|
||||
if len(content) > MAX_SNAPSHOT_FILE_BYTES or len(content) != expected.st_size:
|
||||
raise ValueError("تغير حجم الملف أثناء تجهيز نسخة التنفيذ؛ أعد المحاولة.")
|
||||
if _contains_credential(content):
|
||||
raise ValueError(
|
||||
f"الملف {relative} يبدو أنه يحتوي على مفتاح أو قيمة اعتماد؛ لم تتم إضافته."
|
||||
)
|
||||
latest = source.stat()
|
||||
if (latest.st_dev, latest.st_ino, latest.st_size) != (
|
||||
expected.st_dev,
|
||||
|
||||
Reference in New Issue
Block a user