feat(utils): generic secret_redactor (7 patterns)
This commit is contained in:
0
apps/api/src/utils/__init__.py
Normal file
0
apps/api/src/utils/__init__.py
Normal file
31
apps/api/src/utils/secret_redactor.py
Normal file
31
apps/api/src/utils/secret_redactor.py
Normal file
@@ -0,0 +1,31 @@
|
||||
# awoooi utils: generic secret redactor | 2026-04-20 @ Asia/Taipei
|
||||
"""把字串/dict/list 內 secret pattern 遮罩為 <redacted:kind>。
|
||||
符合 feedback_secrets_leak_incidents_2026-04-18.md — 任何進 PG/TG/log 前都該過這層。"""
|
||||
from __future__ import annotations
|
||||
import re
|
||||
from typing import Any
|
||||
|
||||
# 順序:specific 在前,generic 在後(sk-or-v1 / sk-ant 排 sk- 之前)
|
||||
_PATTERNS: list[tuple[re.Pattern[str], str]] = [
|
||||
(re.compile(r"sk-or-v1-[A-Za-z0-9]{36,}"), "openrouter"),
|
||||
(re.compile(r"sk-ant-api\d{2}-[A-Za-z0-9_\-]{12,}"), "anthropic"),
|
||||
(re.compile(r"sk-[A-Za-z0-9]{40,}"), "openai"),
|
||||
(re.compile(r"ghp_[A-Za-z0-9]{36}"), "github"),
|
||||
(re.compile(r"AIza[0-9A-Za-z_\-]{35}"), "google"),
|
||||
(re.compile(r"\b\d{8,10}:[A-Za-z0-9_\-]{35}\b"), "telegram"),
|
||||
(re.compile(r"AKIA[0-9A-Z]{16}"), "aws"),
|
||||
]
|
||||
|
||||
|
||||
def redact(obj: Any) -> Any:
|
||||
"""遮罩字串/dict/list 內 secret,其他型別原值回傳。"""
|
||||
if isinstance(obj, str):
|
||||
s = obj
|
||||
for pat, kind in _PATTERNS:
|
||||
s = pat.sub(f"<redacted:{kind}>", s)
|
||||
return s
|
||||
if isinstance(obj, dict):
|
||||
return {k: redact(v) for k, v in obj.items()}
|
||||
if isinstance(obj, list):
|
||||
return [redact(x) for x in obj]
|
||||
return obj
|
||||
Reference in New Issue
Block a user