main
py 63 lines 2.58 KB
Raw
1 from helpers.extension import Extension
2 from helpers import dotenv
3 import re
4
5
6 class UnsecuredConnectionCheck(Extension):
7 """Check: non-local without credentials, or credentials over non-HTTPS."""
8
9 async def execute(self, banners: list = [], frontend_context: dict = {}, **kwargs):
10 hostname = frontend_context.get("hostname", "")
11 protocol = frontend_context.get("protocol", "")
12
13 auth_login = dotenv.get_dotenv_value(dotenv.KEY_AUTH_LOGIN, "")
14 auth_password = dotenv.get_dotenv_value(dotenv.KEY_AUTH_PASSWORD, "")
15 has_credentials = bool(auth_login and auth_login.strip() and auth_password and auth_password.strip())
16
17 is_local = self._is_localhost(hostname)
18 is_https = protocol == "https:"
19
20 if not is_local and not has_credentials:
21 banners.append({
22 "id": "unsecured-connection",
23 "type": "warning",
24 "priority": 80,
25 "title": "Unsecured Connection",
26 "html": """You are accessing Agent Zero from a non-local address without authentication.
27 <a href="#section-auth" data-banner-action="open-modal:settings/settings.html#section-auth">
28 Configure credentials</a> in Settings → External Services → Authentication.""",
29 "dismissible": True,
30 "source": "backend"
31 })
32
33 if has_credentials and not is_local and not is_https:
34 banners.append({
35 "id": "credentials-unencrypted",
36 "type": "warning",
37 "priority": 90,
38 "title": "Credentials May Be Sent Unencrypted",
39 "html": """Your connection is not using HTTPS. Login credentials may be transmitted in plain text.
40 Consider using HTTPS or a secure tunnel.""",
41 "dismissible": True,
42 "source": "backend"
43 })
44
45 def _is_localhost(self, hostname: str) -> bool:
46 local_patterns = ["localhost", "127.0.0.1", "::1", "0.0.0.0"]
47
48 if hostname in local_patterns:
49 return True
50
51 # RFC1918 private ranges
52 if re.match(r"^192\.168\.\d{1,3}\.\d{1,3}$", hostname):
53 return True
54 if re.match(r"^10\.\d{1,3}\.\d{1,3}\.\d{1,3}$", hostname):
55 return True
56 if re.match(r"^172\.(1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}$", hostname):
57 return True
58
59 # .local domains
60 if hostname.endswith(".local"):
61 return True
62
63 return False