Coverage for src/local_deep_research/security/__init__.py: 100%
28 statements
« prev ^ index » next coverage.py v7.15.1, created at 2026-07-19 23:35 +0000
« prev ^ index » next coverage.py v7.15.1, created at 2026-07-19 23:35 +0000
1"""Security utilities for Local Deep Research."""
3from .data_sanitizer import (
4 DataSanitizer,
5 filter_research_metadata,
6 redact_data,
7 sanitize_data,
8 strip_settings_snapshot,
9)
10from .egress.audit_hook import (
11 active_egress_context,
12 clear_active_context,
13 get_active_context,
14 install_audit_hook,
15 is_installed as is_audit_hook_installed,
16 set_active_context,
17)
18from .security_settings import get_security_default
19from .file_integrity import FileIntegrityManager, FAISSIndexVerifier
20from .notification_validator import (
21 NotificationURLValidator,
22 NotificationURLValidationError,
23)
24from .safe_requests import safe_get, safe_post, SafeSession
25from .security_headers import SecurityHeaders
26from .ssrf_validator import (
27 assert_base_url_safe,
28 get_safe_url,
29 is_ip_blocked,
30 redact_url_for_log,
31 validate_url,
32)
33from .url_validator import URLValidator
34from .account_lockout import AccountLockoutManager, get_account_lockout_manager
35from .password_validator import PasswordValidator
36from .log_sanitizer import (
37 redact_secrets,
38 sanitize_error_details,
39 sanitize_error_for_client,
40 sanitize_error_message,
41 sanitize_for_log,
42 scrub_error,
43 strip_control_chars,
44)
45from .filename_sanitizer import sanitize_filename, UnsafeFilenameError
46from .module_whitelist import (
47 get_safe_module_class,
48 ModuleNotAllowedError,
49 ALLOWED_MODULES,
50)
52# PathValidator requires werkzeug (Flask dependency), import conditionally
53try:
54 from .path_validator import PathValidator
56 _has_path_validator = True
57except ImportError:
58 PathValidator = None # type: ignore
59 _has_path_validator = False
61# FileUploadValidator requires pdfplumber, import conditionally
62try:
63 from .file_upload_validator import FileUploadValidator
65 _has_file_upload_validator = True
66except ImportError:
67 FileUploadValidator = None # type: ignore
68 _has_file_upload_validator = False
70__all__ = [
71 "PathValidator",
72 "DataSanitizer",
73 "active_egress_context",
74 "clear_active_context",
75 "get_active_context",
76 "install_audit_hook",
77 "is_audit_hook_installed",
78 "set_active_context",
79 "sanitize_data",
80 "redact_data",
81 "filter_research_metadata",
82 "strip_settings_snapshot",
83 "get_security_default",
84 "FileIntegrityManager",
85 "FAISSIndexVerifier",
86 "FileUploadValidator",
87 "NotificationURLValidator",
88 "NotificationURLValidationError",
89 "SecurityHeaders",
90 "URLValidator",
91 "safe_get",
92 "safe_post",
93 "SafeSession",
94 "validate_url",
95 "get_safe_url",
96 "is_ip_blocked",
97 "assert_base_url_safe",
98 "redact_url_for_log",
99 "get_safe_module_class",
100 "ModuleNotAllowedError",
101 "ALLOWED_MODULES",
102 "AccountLockoutManager",
103 "get_account_lockout_manager",
104 "PasswordValidator",
105 "redact_secrets",
106 "sanitize_error_details",
107 "sanitize_error_for_client",
108 "sanitize_error_message",
109 "sanitize_for_log",
110 "scrub_error",
111 "strip_control_chars",
112 "sanitize_filename",
113 "UnsafeFilenameError",
114]
116# Install the process-wide socket.connect audit hook after all imports
117# resolve. The hook is a no-op until a worker thread calls
118# ``set_active_context(ctx)`` — importing this module has zero
119# behavioral effect on code that does not opt in. Idempotent: subsequent
120# imports do not re-install.
121install_audit_hook()