Coverage for src/local_deep_research/settings/env_definitions/security.py: 100%

4 statements  

« prev     ^ index     » next       coverage.py v7.14.1, created at 2026-06-03 23:15 +0000

1""" 

2Security environment settings. 

3 

4These settings control security-related behavior like SSRF validation 

5and CORS origin restrictions. 

6""" 

7 

8import os 

9from ..env_settings import BooleanSetting, StringSetting 

10 

11 

12# External environment variables (set by pytest, CI systems) 

13# These are read directly since we don't control them 

14PYTEST_CURRENT_TEST = os.environ.get("PYTEST_CURRENT_TEST") 

15 

16 

17# LDR Security settings (our application's security configuration) 

18SECURITY_SETTINGS = [ 

19 StringSetting( 

20 key="security.cors.allowed_origins", 

21 description=( 

22 "Allowed CORS origins for API routes (comma-separated). " 

23 "Use '*' for all origins, empty for same-origin only. " 

24 "Example: 'https://example.com,https://app.example.com'" 

25 ), 

26 default=None, 

27 ), 

28 StringSetting( 

29 key="security.websocket.allowed_origins", 

30 description=( 

31 "Allowed origins for WebSocket/Socket.IO connections (comma-separated). " 

32 "Use '*' for all origins (default), empty for same-origin only. " 

33 "Example: 'https://example.com,https://app.example.com'" 

34 ), 

35 default=None, 

36 ), 

37 BooleanSetting( 

38 key="notifications.allow_private_ips", 

39 description=( 

40 "Allow notification webhooks to target private/local IP addresses. " 

41 "Environment-only to prevent SSRF bypass via the user-writable settings API. " 

42 "Only enable this if your notification endpoints are on a trusted local network." 

43 ), 

44 default=False, 

45 ), 

46 BooleanSetting( 

47 key="security.allow_nat64", 

48 description=( 

49 "Allow outbound traffic to NAT64 prefixes (64:ff9b::/96 RFC 6052 " 

50 "well-known and 64:ff9b:1::/48 RFC 8215 local-use). Disabled by " 

51 "default to close the IPv6-wrapped SSRF bypass class — on hosts " 

52 "configured with NAT64 routes, attacker-supplied URLs can wrap " 

53 "cloud-metadata or RFC1918 destinations through these prefixes. " 

54 "Enable only on IPv6-only deployments (DNS64+NAT64) where " 

55 "outbound IPv4 traffic is synthesized through this prefix and " 

56 "the operator has accepted the residual SSRF risk. 6to4 " 

57 "(2002::/16), Teredo (2001::/32), and the discard prefix " 

58 "(100::/64) remain unconditionally blocked because they have no " 

59 "live legitimate use in 2026. The cloud-metadata block " 

60 "(ALWAYS_BLOCKED_METADATA_IPS) still applies via embedded-IPv4 " 

61 "extraction — see SECURITY.md." 

62 ), 

63 default=False, 

64 ), 

65 BooleanSetting( 

66 key="notifications.allow_outbound", 

67 description=( 

68 "Master switch for outbound notification webhooks (Apprise). " 

69 "Disabled by default because Apprise re-resolves DNS at send time, " 

70 "leaving a DNS-rebinding TOCTOU window that cannot be closed in code " 

71 "(Apprise exposes no Session/DNS hook). See SECURITY.md " 

72 "'Notification Webhook SSRF' for details. Set to true only after " 

73 "reviewing the residual risk. Distinct from the per-user " 

74 "notifications.enabled toggle in the settings UI: this is the " 

75 "server-level operator gate, env-only so it cannot be flipped via " 

76 "the user-writable settings API." 

77 ), 

78 default=False, 

79 ), 

80]