Source code for imednet.utils.security
"""
Security utilities.
"""
import re
from typing import Any
from imednet.errors import ClientError, PathTraversalValidationError
_WINDOWS_ABSOLUTE_PATH_RE = re.compile(r"^[A-Za-z]:[/\\]")
[docs]def sanitize_csv_formula(value: Any) -> Any:
"""
Sanitize a value to prevent CSV/Excel Formula Injection.
Prefixes strings starting with =, +, -, or @ (even after whitespace) with a single quote.
Lists and tuples are recursively sanitized.
"""
if isinstance(value, str) and value.lstrip().startswith(("=", "+", "-", "@")):
return f"'{value}"
elif isinstance(value, list):
return [sanitize_csv_formula(v) for v in value]
elif isinstance(value, tuple):
return tuple(sanitize_csv_formula(v) for v in value)
return value
[docs]def validate_header_value(value: str) -> None:
"""
Validate that a header value does not contain newline characters.
Args:
value: The header value to validate.
Raises:
ClientError: If the value contains newline characters.
"""
if "\n" in value or "\r" in value:
raise ClientError(f"Header value must not contain newlines: {value!r}")
[docs]def validate_partition_key(key: str) -> None:
"""Reject partition keys that could escape or reshape the target directory."""
if "\x00" in key:
raise PathTraversalValidationError(f"Partition key must not contain null bytes: {key!r}")
if key.startswith(("/", "\\")) or _WINDOWS_ABSOLUTE_PATH_RE.match(key):
raise PathTraversalValidationError(
f"Partition key must not use absolute path modifiers: {key!r}"
)
if "../" in key or "..\\" in key or key == "..":
raise PathTraversalValidationError(
f"Partition key must not contain parent-directory traversal: {key!r}"
)
if "/" in key or "\\" in key:
raise PathTraversalValidationError(
f"Partition key must not contain path separators: {key!r}"
)