Require a shared, spec-aligned “guard” step for any untrusted input used in security-sensitive contexts (SQL construction, dynamic table names, outbound URL fetch). Fail closed (raise a safe exception) before interpolation/requests, and reuse a single utility to avoid security-policy drift.
Practical rules:
Example pattern (UUID guard):
import uuid
import logging
logger = logging.getLogger(__name__)
def assert_valid_uuid(value: str, *, label: str) -> str:
try:
# Validate; optionally canonicalize to the storage format your SQL expects
return uuid.UUID(str(value)).hex # e.g., 32-char form
except (ValueError, TypeError):
logger.warning("Rejected invalid %s (len=%d)", label, len(str(value)))
raise ValueError(f"Invalid {label} format")
# Use only after guard
kb_hex = assert_valid_uuid(kb_ids[0], label="kb_id")
table_name = f"ragflow_{tenant_id}_{kb_hex}"
Example pattern (SSRF logging hygiene):
# Instead of logging full URL:
logger.warning("SSRF guard blocked URL (scheme=%r host=%r)", scheme, parsed.hostname)
Enter the URL of a public GitHub repository