feat: add YTP_DISABLE_EXEC to strip dangerous yt-dlp options

This commit is contained in:
arabcoders 2026-06-08 09:29:31 +03:00
parent 7a3c41b6bc
commit 4881fabb15
3 changed files with 34 additions and 0 deletions

6
FAQ.md
View file

@ -60,6 +60,7 @@ or the `environment:` section in `compose.yaml` file.
| YTP_THUMB_CONCURRENCY | The number of concurrent ffmpeg thumbnail generations allowed. | `2` |
| YTP_THUMB_GENERATE | Enable ffmpeg thumbnail generation when no local thumbnail exists. | `true` |
| YTP_THUMB_SIDECAR | Save generated thumbnails next to media instead of temp cache. | `false` |
| YTP_DISABLE_EXEC | Strip some dangerous yt-dlp options. | `false` |
> [!NOTE]
> To raise the maximum workers for specific extractor, you need to add a ENV variable that follows the pattern `YTP_MAX_WORKERS_FOR_<EXTRACTOR_NAME>`.
@ -143,6 +144,11 @@ a tool that by design can execute commands. Auth is the mechanism that controls
YTPTube already gates other powerful features behind explicit opt-in: the built-in terminal, file browser actions and internal
URL requests for example. The `cli` field is no different, its power is by design, and access control is your responsibility.
> [!NOTE]
> If you choose to run without authentication but still want to reduce at least some impact, you can set
> `YTP_DISABLE_EXEC=true`. This strips some dangerous options at run time. However, understand that this is not a
> substitute for auth an unauthenticated API is still fully open for all other operations.
# I cant download anything
If you are receiving errors like:

View file

@ -397,6 +397,30 @@ class YTDLPOpts:
data: dict = merge_dict(user_cli, merge_dict(self._item_opts, merge_dict(self._preset_opts, default_opts)))
if self._config.disable_exec:
stripped: list[str] = []
if data.pop("netrc_cmd", None):
stripped.append("netrc_cmd")
if "postprocessors" in data:
exec_pps = [
pp for pp in data["postprocessors"] if isinstance(pp, dict) and pp.get("key", "").startswith("Exec")
]
if exec_pps:
stripped.extend(pp.get("key") for pp in exec_pps)
data["postprocessors"] = [
pp
for pp in data["postprocessors"]
if not (isinstance(pp, dict) and pp.get("key", "").startswith("Exec"))
]
if stripped:
LOG.warning(
"Stripped %d dangerous options from yt-dlp options.",
len(stripped),
extra={"stripped": stripped, "reason": "YTP_DISABLE_EXEC is enabled"},
)
if not keep:
self.reset()

View file

@ -110,6 +110,9 @@ class Config(metaclass=Singleton):
auth_password: str | None = None
"""The password to use for basic authentication."""
disable_exec: bool = False
"""Strip some dangerous yt-dlp options."""
remove_files: bool = False
"""Remove downloaded files when removing the record."""
@ -312,6 +315,7 @@ class Config(metaclass=Singleton):
"check_for_updates",
"thumb_generate",
"thumb_sidecar",
"disable_exec",
)
"The variables that are booleans."