From 636fc7ce6ea76fd731bda005a586a6ea29f4d964 Mon Sep 17 00:00:00 2001 From: az10b Date: Thu, 9 Apr 2026 19:47:24 -0500 Subject: [PATCH] Block dangerous yt-dlp options in ytdl_options_overrides When ALLOW_YTDL_OPTIONS_OVERRIDES is enabled, arbitrary yt-dlp options are accepted and passed directly to yt-dlp without restriction. This allows injection of the Exec postprocessor or exec_cmd option, which executes arbitrary OS commands on the server after a download completes. Add a blocklist of dangerous yt-dlp option keys (exec_cmd, exec, postprocessors, post_hooks, external_downloader, external_downloader_args, cookiefile, cookiesfrombrowser) that are rejected with a 400 error when present in overrides. --- app/main.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/main.py b/app/main.py index 5853163..39caedd 100644 --- a/app/main.py +++ b/app/main.py @@ -234,6 +234,12 @@ VALID_VIDEO_CODECS = {'auto', 'h264', 'h265', 'av1', 'vp9'} VALID_VIDEO_FORMATS = {'any', 'mp4', 'ios'} VALID_AUDIO_FORMATS = {'m4a', 'mp3', 'opus', 'wav', 'flac'} VALID_THUMBNAIL_FORMATS = {'jpg'} +_BLOCKED_YTDL_OVERRIDE_KEYS = frozenset({ + 'exec_cmd', 'exec', 'postprocessors', 'post_hooks', + 'external_downloader', 'external_downloader_args', + 'cookiefile', 'cookiesfrombrowser', +}) + def _parse_ytdl_options_overrides(value, *, enabled: bool) -> dict: if value is None or value == '': return {} @@ -250,6 +256,10 @@ def _parse_ytdl_options_overrides(value, *, enabled: bool) -> dict: if value and not enabled: raise web.HTTPBadRequest(reason='ytdl_options_overrides are disabled') + blocked = set(value.keys()) & _BLOCKED_YTDL_OVERRIDE_KEYS + if blocked: + raise web.HTTPBadRequest(reason=f'ytdl_options_overrides contains blocked keys: {sorted(blocked)}') + return value