restrict go2rtc ${VAR} expansion in stream sources

go2rtc expands ${NAME:default} over the raw config text before parsing it, and falls back to the inline default when NAME is unset, so a stream source like ${NOPE:exec:<cmd>} passed the exec gate and go2rtc then ran the command. On master the API accepted the plain form, and startup accepted the ${{...}} form because .format collapsed it to ${...} after the check would have caught it. Any stream source containing ${ is now restricted unless GO2RTC_ALLOW_ARBITRARY_EXEC is set, the same as exec sources.
This commit is contained in:
Josh Hawkins
2026-10-19 22:31:22 -05:00
parent dc116ecaf4
commit 39567b37eb
5 changed files with 77 additions and 7 deletions
+9 -3
View File
@@ -980,9 +980,15 @@ def is_go2rtc_arbitrary_exec_allowed() -> bool:
def is_restricted_go2rtc_source(stream_source: str) -> bool:
"""Check if a stream source is a restricted type (echo, expr, or exec)
and the GO2RTC_ALLOW_ARBITRARY_EXEC override is not set."""
if not stream_source.strip().startswith(("echo:", "expr:", "exec:")):
"""Check if a stream source is restricted and the
GO2RTC_ALLOW_ARBITRARY_EXEC override is not set.
Restricted sources are the echo, expr and exec schemes, and any source
using go2rtc's `${VAR:default}` expansion, which go2rtc runs over the raw
config before parsing and whose default can name an exec source.
"""
source = stream_source.strip()
if not source.startswith(("echo:", "expr:", "exec:")) and "${" not in source:
return False
return not is_go2rtc_arbitrary_exec_allowed()