mirror of
https://github.com/HKUDS/OpenSpace.git
synced 2026-08-28 05:15:00 +00:00
80 lines
2.5 KiB
Python
80 lines
2.5 KiB
Python
"""Deterministic redaction for evidence previews and metadata."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
from typing import Any, Mapping
|
|
|
|
SECRET_REDACTION = "[REDACTED_SECRET]"
|
|
|
|
_SECRET_KEY_RE = re.compile(
|
|
r"(api[_-]?key|token|authorization|cookie|secret|password|credential)",
|
|
re.IGNORECASE,
|
|
)
|
|
_SECRET_PATTERNS: tuple[re.Pattern[str], ...] = (
|
|
re.compile(
|
|
r"(?i)\b([A-Z0-9_]*(?:API[_-]?KEY|TOKEN|SECRET|PASSWORD)[A-Z0-9_]*)"
|
|
r"\s*=\s*([^\s\"']+)"
|
|
),
|
|
re.compile(
|
|
r"(?i)\b([A-Z0-9_]*(?:API[_-]?KEY|TOKEN|SECRET|PASSWORD)[A-Z0-9_]*)"
|
|
r"\s*:\s*([^\s\"']+)"
|
|
),
|
|
re.compile(r"(?i)\bAuthorization\s*:\s*Bearer\s+[A-Za-z0-9._~+/=-]+"),
|
|
re.compile(r"(?i)\bCookie\s*:\s*[^;\n]+(?:;[^\n]+)?"),
|
|
re.compile(r"\bsk-[A-Za-z0-9_-]{16,}\b"),
|
|
)
|
|
|
|
|
|
def contains_secret(value: Any) -> bool:
|
|
if isinstance(value, Mapping):
|
|
for key, item in value.items():
|
|
if _SECRET_KEY_RE.search(str(key)) and not _is_redacted_value(item):
|
|
return True
|
|
if contains_secret(item):
|
|
return True
|
|
return False
|
|
if isinstance(value, (list, tuple, set)):
|
|
return any(contains_secret(item) for item in value)
|
|
if value is None:
|
|
return False
|
|
text = str(value).replace(SECRET_REDACTION, "")
|
|
return any(pattern.search(text) for pattern in _SECRET_PATTERNS)
|
|
|
|
|
|
def _is_redacted_value(value: Any) -> bool:
|
|
return isinstance(value, str) and value.strip() == SECRET_REDACTION
|
|
|
|
|
|
def redact_text(text: str) -> str:
|
|
redacted = str(text)
|
|
redacted = _SECRET_PATTERNS[0].sub(
|
|
lambda match: f"{match.group(1)}={SECRET_REDACTION}",
|
|
redacted,
|
|
)
|
|
redacted = _SECRET_PATTERNS[1].sub(
|
|
lambda match: f"{match.group(1)}: {SECRET_REDACTION}",
|
|
redacted,
|
|
)
|
|
for pattern in _SECRET_PATTERNS[2:]:
|
|
redacted = pattern.sub(SECRET_REDACTION, redacted)
|
|
return redacted
|
|
|
|
|
|
def redact_metadata(value: Any) -> Any:
|
|
if isinstance(value, Mapping):
|
|
result: dict[str, Any] = {}
|
|
for key, item in value.items():
|
|
key_text = str(key)
|
|
if _SECRET_KEY_RE.search(key_text):
|
|
result[key_text] = SECRET_REDACTION
|
|
else:
|
|
result[key_text] = redact_metadata(item)
|
|
return result
|
|
if isinstance(value, list):
|
|
return [redact_metadata(item) for item in value]
|
|
if isinstance(value, tuple):
|
|
return [redact_metadata(item) for item in value]
|
|
if isinstance(value, str):
|
|
return redact_text(value)
|
|
return value
|