Skip to content

Commit 4131252

Browse files
Port go2rtc check (#21808)
* version update * Restrict go2rtc exec sources by default (#21543) * Restrict go2rtc exec sources by default * add docs * check for addon value too --------- Co-authored-by: Nicolas Mowen <[email protected]>
1 parent ea39bb3 commit 4131252

File tree

3 files changed

+78
-7
lines changed

3 files changed

+78
-7
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
default_target: local
22

33
COMMIT_HASH := $(shell git log -1 --pretty=format:"%h"|tail -1)
4-
VERSION = 0.16.3
4+
VERSION = 0.16.4
55
IMAGE_REPO ?= ghcr.io/blakeblackshear/frigate
66
GITHUB_REF_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
77
BOARDS= #Initialized empty

docker/main/rootfs/usr/local/go2rtc/create_config.py

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,22 @@
2222

2323
yaml = YAML()
2424

25+
# Check if arbitrary exec sources are allowed (defaults to False for security)
26+
ALLOW_ARBITRARY_EXEC = os.environ.get(
27+
"GO2RTC_ALLOW_ARBITRARY_EXEC", "false"
28+
).lower() in ("true", "1", "yes")
29+
30+
# check for the add-on options file
31+
if not ALLOW_ARBITRARY_EXEC and os.path.isfile("/data/options.json"):
32+
with open("/data/options.json") as f:
33+
raw_options = f.read()
34+
options = json.loads(raw_options)
35+
addon_value = options.get("go2rtc_allow_arbitrary_exec", False)
36+
if isinstance(addon_value, bool):
37+
ALLOW_ARBITRARY_EXEC = addon_value
38+
elif isinstance(addon_value, str):
39+
ALLOW_ARBITRARY_EXEC = addon_value.lower() in ("true", "1", "yes")
40+
2541
FRIGATE_ENV_VARS = {k: v for k, v in os.environ.items() if k.startswith("FRIGATE_")}
2642
# read docker secret files as env vars too
2743
if os.path.isdir("/run/secrets"):
@@ -109,30 +125,60 @@
109125
elif go2rtc_config["ffmpeg"].get("rtsp") is None:
110126
go2rtc_config["ffmpeg"]["rtsp"] = rtsp_args
111127

112-
for name in go2rtc_config.get("streams", {}):
128+
129+
def is_restricted_source(stream_source: str) -> bool:
130+
"""Check if a stream source is restricted (echo, expr, or exec)."""
131+
return stream_source.strip().startswith(("echo:", "expr:", "exec:"))
132+
133+
134+
for name in list(go2rtc_config.get("streams", {})):
113135
stream = go2rtc_config["streams"][name]
114136

115137
if isinstance(stream, str):
116138
try:
117-
go2rtc_config["streams"][name] = go2rtc_config["streams"][name].format(
118-
**FRIGATE_ENV_VARS
119-
)
139+
formatted_stream = stream.format(**FRIGATE_ENV_VARS)
140+
if not ALLOW_ARBITRARY_EXEC and is_restricted_source(formatted_stream):
141+
print(
142+
f"[ERROR] Stream '{name}' uses a restricted source (echo/expr/exec) which is disabled by default for security. "
143+
f"Set GO2RTC_ALLOW_ARBITRARY_EXEC=true to enable arbitrary exec sources."
144+
)
145+
del go2rtc_config["streams"][name]
146+
continue
147+
go2rtc_config["streams"][name] = formatted_stream
120148
except KeyError as e:
121149
print(
122150
"[ERROR] Invalid substitution found, see https://docs.frigate.video/configuration/restream#advanced-restream-configurations for more info."
123151
)
124152
sys.exit(e)
125153

126154
elif isinstance(stream, list):
127-
for i, stream in enumerate(stream):
155+
filtered_streams = []
156+
for i, stream_item in enumerate(stream):
128157
try:
129-
go2rtc_config["streams"][name][i] = stream.format(**FRIGATE_ENV_VARS)
158+
formatted_stream = stream_item.format(**FRIGATE_ENV_VARS)
159+
if not ALLOW_ARBITRARY_EXEC and is_restricted_source(formatted_stream):
160+
print(
161+
f"[ERROR] Stream '{name}' item {i + 1} uses a restricted source (echo/expr/exec) which is disabled by default for security. "
162+
f"Set GO2RTC_ALLOW_ARBITRARY_EXEC=true to enable arbitrary exec sources."
163+
)
164+
continue
165+
166+
filtered_streams.append(formatted_stream)
130167
except KeyError as e:
131168
print(
132169
"[ERROR] Invalid substitution found, see https://docs.frigate.video/configuration/restream#advanced-restream-configurations for more info."
133170
)
134171
sys.exit(e)
135172

173+
if filtered_streams:
174+
go2rtc_config["streams"][name] = filtered_streams
175+
else:
176+
print(
177+
f"[ERROR] Stream '{name}' was removed because all sources were restricted (echo/expr/exec). "
178+
f"Set GO2RTC_ALLOW_ARBITRARY_EXEC=true to enable arbitrary exec sources."
179+
)
180+
del go2rtc_config["streams"][name]
181+
136182
# add birdseye restream stream if enabled
137183
if config.get("birdseye", {}).get("restream", False):
138184
birdseye: dict[str, Any] = config.get("birdseye")

docs/docs/configuration/restream.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,35 @@ go2rtc:
154154

155155
See [this comment](https://github.com/AlexxIT/go2rtc/issues/1217#issuecomment-2242296489) for more information.
156156

157+
## Security: Restricted Stream Sources
158+
159+
For security reasons, the `echo:`, `expr:`, and `exec:` stream sources are disabled by default in go2rtc. These sources allow arbitrary command execution and can pose security risks if misconfigured.
160+
161+
If you attempt to use these sources in your configuration, the streams will be removed and an error message will be printed in the logs.
162+
163+
To enable these sources, you must set the environment variable `GO2RTC_ALLOW_ARBITRARY_EXEC=true`. This can be done in your Docker Compose file or container environment:
164+
165+
```yaml
166+
environment:
167+
- GO2RTC_ALLOW_ARBITRARY_EXEC=true
168+
```
169+
170+
:::warning
171+
172+
Enabling arbitrary exec sources allows execution of arbitrary commands through go2rtc stream configurations. Only enable this if you understand the security implications and trust all sources of your configuration.
173+
174+
:::
175+
157176
## Advanced Restream Configurations
158177

159178
The [exec](https://github.com/AlexxIT/go2rtc/tree/v1.9.9#source-exec) source in go2rtc can be used for custom ffmpeg commands. An example is below:
160179

180+
:::warning
181+
182+
The `exec:`, `echo:`, and `expr:` sources are disabled by default for security. You must set `GO2RTC_ALLOW_ARBITRARY_EXEC=true` to use them. See [Security: Restricted Stream Sources](#security-restricted-stream-sources) for more information.
183+
184+
:::
185+
161186
NOTE: The output will need to be passed with two curly braces `{{output}}`
162187

163188
```yaml

0 commit comments

Comments
 (0)