mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-07-15 00:11:15 +03:00
block ffmpeg args in custom exports for non-admin users only
This commit is contained in:
parent
d8c35d5a0f
commit
45993b0061
@ -548,23 +548,27 @@ def export_recording_custom(
|
||||
|
||||
export_id = f"{camera_name}_{''.join(random.choices(string.ascii_lowercase + string.digits, k=6))}"
|
||||
|
||||
# Validate user-provided ffmpeg args to prevent injection
|
||||
for args_label, args_value in [
|
||||
("input", ffmpeg_input_args),
|
||||
("output", ffmpeg_output_args),
|
||||
]:
|
||||
if args_value is not None:
|
||||
valid, message = validate_ffmpeg_args(args_value)
|
||||
if not valid:
|
||||
return JSONResponse(
|
||||
content=(
|
||||
{
|
||||
"success": False,
|
||||
"message": f"Invalid ffmpeg {args_label} arguments: {message}",
|
||||
}
|
||||
),
|
||||
status_code=400,
|
||||
)
|
||||
# Validate user-provided ffmpeg args to prevent injection.
|
||||
# Admin users are trusted and skip validation.
|
||||
is_admin = request.headers.get("remote-role", "") == "admin"
|
||||
|
||||
if not is_admin:
|
||||
for args_label, args_value in [
|
||||
("input", ffmpeg_input_args),
|
||||
("output", ffmpeg_output_args),
|
||||
]:
|
||||
if args_value is not None:
|
||||
valid, message = validate_ffmpeg_args(args_value)
|
||||
if not valid:
|
||||
return JSONResponse(
|
||||
content=(
|
||||
{
|
||||
"success": False,
|
||||
"message": f"Invalid ffmpeg {args_label} arguments: {message}",
|
||||
}
|
||||
),
|
||||
status_code=400,
|
||||
)
|
||||
|
||||
# Set default values if not provided (timelapse defaults)
|
||||
if ffmpeg_input_args is None:
|
||||
|
||||
@ -36,22 +36,20 @@ logger = logging.getLogger(__name__)
|
||||
DEFAULT_TIME_LAPSE_FFMPEG_ARGS = "-vf setpts=0.04*PTS -r 30"
|
||||
TIMELAPSE_DATA_INPUT_ARGS = "-an -skip_frame nokey"
|
||||
|
||||
# ffmpeg flags that can read from or write to arbitrary files.
|
||||
# filter flags are blocked because source filters like movie= and
|
||||
# amovie= can read arbitrary files from the filesystem.
|
||||
# ffmpeg flags that can read from or write to arbitrary files
|
||||
BLOCKED_FFMPEG_ARGS = frozenset(
|
||||
{
|
||||
"-i",
|
||||
"-filter_script",
|
||||
"-vstats_file",
|
||||
"-passlogfile",
|
||||
"-sdp_file",
|
||||
"-dump_attachment",
|
||||
"-filter_complex",
|
||||
"-lavfi",
|
||||
"-vf",
|
||||
"-af",
|
||||
"-filter",
|
||||
"-vstats_file",
|
||||
"-passlogfile",
|
||||
"-sdp_file",
|
||||
"-dump_attachment",
|
||||
"-attach",
|
||||
}
|
||||
)
|
||||
@ -62,8 +60,11 @@ def validate_ffmpeg_args(args: str) -> tuple[bool, str]:
|
||||
|
||||
Blocks:
|
||||
- The -i flag and other flags that read/write arbitrary files
|
||||
- Filter flags (can read files via movie=/amovie= source filters)
|
||||
- Absolute/relative file paths (potential extra outputs)
|
||||
- URLs and ffmpeg protocol references (data exfiltration)
|
||||
|
||||
Admin users skip this validation entirely since they are trusted.
|
||||
"""
|
||||
if not args or not args.strip():
|
||||
return True, ""
|
||||
|
||||
Loading…
Reference in New Issue
Block a user