From 3c488688d1287c1ca89a4a185f8665a5ac5a7b3b Mon Sep 17 00:00:00 2001 From: bradautomates Date: Sat, 9 May 2026 08:13:32 +1000 Subject: [PATCH] Harden subprocess argv against option injection (#2) - download.py: insert `--` before URL in yt-dlp argv so a `-`-prefixed string can never be parsed as a flag (e.g. --exec, --config-location). Tighten is_url to reject `-`-prefixed sources and require non-empty netloc. - frames.py, whisper.py: resolve video/audio paths to absolute via Path.resolve() before passing to ffmpeg/ffprobe (which don't honor `--` as end-of-options), so a relative path starting with `-` can never be misinterpreted as a flag. Co-Authored-By: Claude Opus 4.7 (1M context) --- scripts/download.py | 5 ++++- scripts/frames.py | 4 ++-- scripts/whisper.py | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/scripts/download.py b/scripts/download.py index 4d3429a..589123c 100755 --- a/scripts/download.py +++ b/scripts/download.py @@ -18,8 +18,10 @@ VIDEO_EXTS = {".mp4", ".mkv", ".webm", ".mov", ".m4v", ".avi", ".flv", ".wmv"} def is_url(source: str) -> bool: + if source.startswith("-"): + return False parsed = urlparse(source) - return parsed.scheme in ("http", "https") + return parsed.scheme in ("http", "https") and bool(parsed.netloc) def resolve_local(path: str) -> dict: @@ -78,6 +80,7 @@ def download_url(url: str, out_dir: Path) -> dict: "--no-playlist", "--ignore-errors", "-o", output_template, + "--", url, ] diff --git a/scripts/frames.py b/scripts/frames.py index 04e7933..01d205a 100755 --- a/scripts/frames.py +++ b/scripts/frames.py @@ -66,7 +66,7 @@ def get_metadata(video_path: str) -> dict: "-print_format", "json", "-show_format", "-show_streams", - video_path, + str(Path(video_path).resolve()), ], capture_output=True, text=True, @@ -162,7 +162,7 @@ def extract( cmd += ["-to", f"{end_seconds:.3f}"] cmd += [ - "-i", video_path, + "-i", str(Path(video_path).resolve()), "-vf", f"fps={fps},scale={resolution}:-2", "-frames:v", str(max_frames), "-q:v", "4", diff --git a/scripts/whisper.py b/scripts/whisper.py index 565994f..318b449 100755 --- a/scripts/whisper.py +++ b/scripts/whisper.py @@ -93,13 +93,13 @@ def extract_audio(video_path: str, out_path: Path) -> Path: "-hide_banner", "-loglevel", "error", "-y", - "-i", video_path, + "-i", str(Path(video_path).resolve()), "-vn", "-acodec", "libmp3lame", "-ar", "16000", "-ac", "1", "-b:a", "64k", - str(out_path), + str(out_path.resolve()), ] result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode != 0: