feat: complete production workflow migration

This commit is contained in:
2026-08-06 14:29:57 +08:00
parent 7f215e79c4
commit 8df5266abb
448 changed files with 56937 additions and 14619 deletions
+82 -8
View File
@@ -7,7 +7,9 @@ import re
from dataclasses import dataclass
from pathlib import Path
DEFAULT_EXCLUDED_DIRECTORIES = frozenset({"var", ".git", ".venv", ".learnings"})
DEFAULT_EXCLUDED_DIRECTORIES = frozenset(
{"var", ".git", ".venv", ".learnings", "build", "dist"}
)
_ASSIGNMENT_PATTERN = re.compile(
r"""
@@ -21,7 +23,7 @@ _ASSIGNMENT_PATTERN = re.compile(
access[_-]?token | refresh[_-]?token | auth[_-]?token
)
[\"']?
\s*(?::|(?<![=!<>])=(?!=))\s*
\s*(?P<separator>:|(?<![=!<>])=(?!=))\s*
(?:
\"(?P<double>[^\"\r\n]*)\" |
'(?P<single>[^'\r\n]*)' |
@@ -46,6 +48,32 @@ _NAMED_LONG_HEX_CREDENTIAL_PATTERN = re.compile(
""",
re.IGNORECASE | re.VERBOSE,
)
_SENSITIVE_ENVIRONMENT_FALLBACK_PATTERN = re.compile(
r"""
[\"']?
(?:[a-z0-9]+[_\-.])*
(?:
password | passwd | pwd |
api[_-]?key | app[_-]?secret | client[_-]?secret | consumer[_-]?secret |
secret[_-]?key |
secret[_-]?access[_-]?key | access[_-]?key(?:[_-]?id)? |
access[_-]?token | refresh[_-]?token | auth[_-]?token
)
[\"']?
\s*(?::|(?<![=!<>])=(?!=))\s*
[^\r\n]*?
(?:os\.)?getenv\(
\s*[\"'][^\"'\r\n]+[\"']\s*,\s*
(?:\"(?P<double>[^\"\r\n]*)\"|'(?P<single>[^'\r\n]*)')
\s*,?
\s*\)
""",
re.IGNORECASE | re.VERBOSE,
)
_SAFE_REFERENCE_PATTERN = re.compile(
r"[A-Za-z_]\w*(?:(?:\.[A-Za-z_]\w*)|(?:\[(?:[\"'][^\"'\r\n]+[\"']|\d+)\]))+"
)
_PLACEHOLDER_WORDS = frozenset(
{
@@ -98,7 +126,10 @@ def scan_repository(
findings: list[SecretFinding] = []
for directory, directory_names, file_names in os.walk(repository, followlinks=False):
directory_names[:] = sorted(
name for name in directory_names if name not in excluded_directories
name
for name in directory_names
if name not in excluded_directories
and not name.casefold().endswith(".egg-info")
)
current_directory = Path(directory)
for file_name in sorted(file_names):
@@ -128,15 +159,31 @@ def _read_text(path: Path) -> str | None:
def _scan_text(relative_file: str, text: str) -> list[SecretFinding]:
findings: list[SecretFinding] = []
long_hex_lines: set[int] = set()
if relative_file.casefold().endswith((".py", ".pyw")):
for match in _NAMED_LONG_HEX_CREDENTIAL_PATTERN.finditer(text):
line_number = text.count("\n", 0, match.start()) + 1
long_hex_lines.add(line_number)
findings.append(
SecretFinding(
relative_file,
text.count("\n", 0, match.start()) + 1,
line_number,
"hardcoded-long-hex-credential",
)
)
for match in _SENSITIVE_ENVIRONMENT_FALLBACK_PATTERN.finditer(text):
line_number = text.count("\n", 0, match.start()) + 1
if (
line_number not in long_hex_lines
and _is_plaintext_value(match, allow_safe_reference=False)
):
findings.append(
SecretFinding(
relative_file,
line_number,
"plaintext-environment-fallback",
)
)
for line_number, line in enumerate(text.splitlines(), start=1):
if _PRIVATE_KEY_PATTERN.search(line):
findings.append(
@@ -144,16 +191,43 @@ def _scan_text(relative_file: str, text: str) -> list[SecretFinding]:
)
if _CREDENTIAL_URL_PATTERN.search(line):
findings.append(SecretFinding(relative_file, line_number, "credential-in-url"))
if any(_is_plaintext_value(match) for match in _ASSIGNMENT_PATTERN.finditer(line)):
assignments = (
match
for match in _ASSIGNMENT_PATTERN.finditer(line)
if not _is_python_lambda_parameter(relative_file, line, match)
)
if any(_is_plaintext_value(match) for match in assignments):
findings.append(
SecretFinding(relative_file, line_number, "plaintext-credential")
)
return findings
def _is_plaintext_value(match: re.Match[str]) -> bool:
def _is_python_lambda_parameter(
relative_file: str,
line: str,
match: re.Match[str],
) -> bool:
if not relative_file.casefold().endswith((".py", ".pyw")):
return False
if match.groupdict().get("separator") != ":":
return False
prefix = line[: match.start()]
lambda_position = prefix.rfind("lambda")
return lambda_position >= 0 and ":" not in prefix[lambda_position:]
def _is_plaintext_value(
match: re.Match[str],
*,
allow_safe_reference: bool = True,
) -> bool:
value = next(
(candidate for candidate in match.group("double", "single", "bare") if candidate is not None),
(
match.groupdict().get(name)
for name in ("double", "single", "bare")
if match.groupdict().get(name) is not None
),
"",
).strip()
if not value:
@@ -167,7 +241,7 @@ def _is_plaintext_value(match: re.Match[str]) -> bool:
return False
if value.startswith(("$", "%(", "{{", "{")):
return False
if re.fullmatch(r"[a-z_]\w*(?:\.[a-z_]\w*)+", lowered):
if allow_safe_reference and _SAFE_REFERENCE_PATTERN.fullmatch(value):
return False
if any(marker in lowered for marker in ("getenv(", "environ[", "secretmanager", "keyvault")):
return False