mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-10-15 11:12:49 +03:00
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 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
945a2d7744
commit
3bbac1be48
@@ -1,3 +1,4 @@
|
|||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -5,6 +6,8 @@ from typing import Annotated
|
|||||||
|
|
||||||
from pydantic import AfterValidator, ValidationInfo
|
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_")}
|
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")
|
secrets_dir = os.environ.get("CREDENTIALS_DIRECTORY", "/run/secrets")
|
||||||
# read secret files as env vars too
|
# 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.
|
# Matches a FRIGATE_* identifier following an opening brace.
|
||||||
_FRIGATE_IDENT_RE = re.compile(r"FRIGATE_[A-Za-z0-9_]+")
|
_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]:
|
def validate_env_vars(v: dict[str, str], info: ValidationInfo) -> dict[str, str]:
|
||||||
if isinstance(info.context, dict) and info.context.get("install", False):
|
if isinstance(info.context, dict) and info.context.get("install", False):
|
||||||
for k, val in v.items():
|
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
|
os.environ[k] = val
|
||||||
if k.startswith("FRIGATE_"):
|
if k.startswith("FRIGATE_"):
|
||||||
FRIGATE_ENV_VARS[k] = val
|
FRIGATE_ENV_VARS[k] = val
|
||||||
|
|||||||
@@ -228,6 +228,26 @@ class TestEnvVars(unittest.TestCase):
|
|||||||
result = validate_env_string("{FRIGATE_BROKER}")
|
result = validate_env_string("{FRIGATE_BROKER}")
|
||||||
self.assertEqual(result, "mqtt.local")
|
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__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Reference in New Issue
Block a user