From 3bbac1be4833e7d6a4e774c476c2f1a4b3ad2aa9 Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Wed, 14 Oct 2026 07:32:09 -0500 Subject: [PATCH] Ignore GO2RTC_ALLOW_ARBITRARY_EXEC in environment_vars environment_vars installs every key into the Frigate process environment at startup, so an admin could enable GO2RTC_ALLOW_ARBITRARY_EXEC from the config and turn off the restricted go2rtc source checks on the API. The override is meant to be set by the operator in the container environment (or the Home Assistant add-on options), so it is now skipped with a warning when it appears in environment_vars. Co-Authored-By: Claude Opus 5.5 --- frigate/config/env.py | 14 ++++++++++++++ frigate/test/test_env.py | 20 ++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/frigate/config/env.py b/frigate/config/env.py index 209dda67bf..79d85cfab0 100644 --- a/frigate/config/env.py +++ b/frigate/config/env.py @@ -1,3 +1,4 @@ +import logging import os import re from pathlib import Path @@ -5,6 +6,8 @@ from typing import Annotated from pydantic import AfterValidator, ValidationInfo +logger = logging.getLogger(__name__) + FRIGATE_ENV_VARS = {k: v for k, v in os.environ.items() if k.startswith("FRIGATE_")} secrets_dir = os.environ.get("CREDENTIALS_DIRECTORY", "/run/secrets") # read secret files as env vars too @@ -16,6 +19,10 @@ if os.path.isdir(secrets_dir) and os.access(secrets_dir, os.R_OK): ) +# Security overrides that must come from the container environment, which is +# controlled by the operator, rather than from the config, which admins can edit +_PROTECTED_ENV_VARS = frozenset({"GO2RTC_ALLOW_ARBITRARY_EXEC"}) + # Matches a FRIGATE_* identifier following an opening brace. _FRIGATE_IDENT_RE = re.compile(r"FRIGATE_[A-Za-z0-9_]+") @@ -95,6 +102,13 @@ EnvString = Annotated[str, AfterValidator(validate_env_string)] def validate_env_vars(v: dict[str, str], info: ValidationInfo) -> dict[str, str]: if isinstance(info.context, dict) and info.context.get("install", False): for k, val in v.items(): + if k.upper() in _PROTECTED_ENV_VARS: + logger.warning( + "Ignoring %s in environment_vars, it must be set in the container environment", + k, + ) + continue + os.environ[k] = val if k.startswith("FRIGATE_"): FRIGATE_ENV_VARS[k] = val diff --git a/frigate/test/test_env.py b/frigate/test/test_env.py index be7f51df43..d91e18c0ca 100644 --- a/frigate/test/test_env.py +++ b/frigate/test/test_env.py @@ -228,6 +228,26 @@ class TestEnvVars(unittest.TestCase): result = validate_env_string("{FRIGATE_BROKER}") self.assertEqual(result, "mqtt.local") + def test_install_ignores_go2rtc_exec_override(self): + """The go2rtc exec override cannot be enabled from the config.""" + from frigate.util.services import is_go2rtc_arbitrary_exec_allowed + + os.environ.pop("GO2RTC_ALLOW_ARBITRARY_EXEC", None) + ctx = self._make_context(install=True) + with patch("frigate.util.services.os.path.isfile", return_value=False): + for key in ("GO2RTC_ALLOW_ARBITRARY_EXEC", "go2rtc_allow_arbitrary_exec"): + validate_env_vars({key: "true", "OTHER_VAR": "value"}, ctx) + self.assertNotIn(key, os.environ) + self.assertFalse(is_go2rtc_arbitrary_exec_allowed()) + self.assertEqual(os.environ.get("OTHER_VAR"), "value") + + def test_install_keeps_container_go2rtc_exec_override(self): + """An override set in the container environment is left untouched.""" + os.environ["GO2RTC_ALLOW_ARBITRARY_EXEC"] = "true" + ctx = self._make_context(install=True) + validate_env_vars({"GO2RTC_ALLOW_ARBITRARY_EXEC": "false"}, ctx) + self.assertEqual(os.environ.get("GO2RTC_ALLOW_ARBITRARY_EXEC"), "true") + if __name__ == "__main__": unittest.main()