validate trusted_proxies at config load

Malformed trusted_proxies entries were only parsed per request in get_remote_addr, so a typo logged a warning on every proxied request and the entry was skipped, collapsing all clients behind that proxy into one rate-limit bucket. The config now rejects unparseable entries at startup and get_remote_addr no longer needs the fallback. Host bits are accepted (192.168.1.1/24 reads as 192.168.1.0/24) so a common typo doesn't take down safe mode, which copies the auth section verbatim.
This commit is contained in:
Josh Hawkins
2026-10-15 21:32:57 -05:00
parent 87a7551aaa
commit a60486e2ef
3 changed files with 24 additions and 8 deletions
+4 -8
View File
@@ -314,14 +314,10 @@ def get_remote_addr(request: Request):
route = list(reversed(forwarded_for.split(","))) route = list(reversed(forwarded_for.split(",")))
logger.debug(f"IP Route: {[r for r in route]}") logger.debug(f"IP Route: {[r for r in route]}")
trusted_proxies = [] trusted_proxies = [
for proxy in request.app.frigate_config.auth.trusted_proxies: ipaddress.ip_network(proxy, strict=False)
try: for proxy in request.app.frigate_config.auth.trusted_proxies
network = ipaddress.ip_network(proxy) ]
except ValueError:
logger.warning(f"Unable to parse trusted network: {proxy}")
continue
trusted_proxies.append(network)
# return the first remote address that is not trusted # return the first remote address that is not trusted
for addr in route: for addr in route:
+10
View File
@@ -1,3 +1,5 @@
import ipaddress
from pydantic import Field, field_validator, model_validator from pydantic import Field, field_validator, model_validator
from .base import FrigateBaseModel from .base import FrigateBaseModel
@@ -68,6 +70,14 @@ class AuthConfig(FrigateBaseModel):
), ),
) )
@field_validator("trusted_proxies")
@classmethod
def validate_trusted_proxies(cls, v: list[str]) -> list[str]:
for proxy in v:
ipaddress.ip_network(proxy, strict=False)
return v
@field_validator("roles") @field_validator("roles")
@classmethod @classmethod
def validate_roles(cls, v: dict[str, list[str]]) -> dict[str, list[str]]: def validate_roles(cls, v: dict[str, list[str]]) -> dict[str, list[str]]:
+10
View File
@@ -75,6 +75,16 @@ class TestConfig(unittest.TestCase):
DetectorTypeEnum.cpu DetectorTypeEnum.cpu
) )
def test_trusted_proxies_reject_invalid_networks(self):
config = {
"auth": {"trusted_proxies": ["172.18.0.0/16", "192.168.1.1/24", "fd00::/8"]}
}
FrigateConfig(**deep_merge(config, self.minimal))
config = {"auth": {"trusted_proxies": ["172.18.0.0/33"]}}
with self.assertRaises(ValidationError):
FrigateConfig(**deep_merge(config, self.minimal))
@patch("frigate.detectors.detector_config.load_labels") @patch("frigate.detectors.detector_config.load_labels")
def test_model_custom_path(self, mock_labels): def test_model_custom_path(self, mock_labels):
mock_labels.return_value = {} mock_labels.return_value = {}