# Risk map — ytdl-org/youtube-dl

> Canonical page: https://codevetter.com/unpack/youtube-dl/risk-map

# Risk map — ytdl-org/youtube-dl

Scanned commit 956b8c585591b401a543e409accb163eeaaa1193 (2025-11-26). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

The highest-risk areas are shell-outs (postprocessor --exec with shell=True, external downloader and ffmpeg command construction), credential handling (cookies, netrc, passwords), the self-update path that replaces the running binary, and the eval-adjacent JS/SWF interpreters. The codebase also carries heavy legacy weight: Python 2.6 compat shims, dead modules (swfinterp is only referenced by tests), and fragile regex-based scraping across ~800 site extractors that break silently when sites change.
- ExecAfterDownloadPP.run executes the user's --exec command with subprocess.call(shell=True); the {} placeholder is shlex-quoted, but the rest of the command string is raw shell — a deliberate but real command-execution surface. — [youtube_dl/postprocessor/execafterdownload.py#L18-30](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/postprocessor/execafterdownload.py#L18-L30)
- External downloaders and ffmpeg are spawned via subprocess.Popen with argv built from info_dict fields (url, http_headers, cookies); cookies are serialized into temp files or -cookies/-headers args, so a malicious extractor result could influence command lines, though lists (not shell strings) are used. — [youtube_dl/downloader/external.py#L127-138](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/downloader/external.py#L127-L138) [youtube_dl/downloader/external.py#L373-490](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/downloader/external.py#L373-L490)
- Self-update replaces the running executable with a network download; it is gated by an RSA signature over versions.json plus a per-file sha256 check, but trusts a hard-coded RSA key and yt-dl.org availability; the Windows path writes and spawns a .bat file that swaps the exe. — [youtube_dl/update.py#L34-176](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/update.py#L34-L176)
- Cookie leak mitigations indicate a history of security issues: _remove_cookie_header strips Cookie from http_headers, _load_cookies scopes header-supplied cookies to the target domain (referencing yt-dlp advisory GHSA-v8mc-9377-rwjj), and YoutubeDLRedirectHandler drops Cookie on redirect; the file:// scheme is explicitly disabled citing issue #8227. — [youtube_dl/YoutubeDL.py#L901-972](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/YoutubeDL.py#L901-L972) [youtube_dl/utils.py#L3090-3152](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/utils.py#L3090-L3152) [youtube_dl/YoutubeDL.py#L2623-2631](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/YoutubeDL.py#L2623-L2631)
- _UnsafeExtensionError enforces an extension whitelist on output files to prevent path traversal/arbitrary file overwrite (referencing yt-dlp advisory GHSA-79w7-vh3h-8g4j); --no-check-extensions sets the lenient flag to bypass it. — [youtube_dl/utils.py#L6733-6863](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/utils.py#L6733-L6863) [youtube_dl/YoutubeDL.py#L134-145](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/YoutubeDL.py#L134-L145) [youtube_dl/__init__.py#L177-178](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/__init__.py#L177-L178)
- Aria2pFD connects to an aria2 daemon at http://localhost:6800 with an empty RPC secret and trusts the aria2p library being importable — local RPC without authentication. — [youtube_dl/downloader/external.py#L283-340](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/downloader/external.py#L283-L340)
- JSInterpreter is a partial JS engine that executes extracted player code semantics; _extract_sig_fn even splices a regex-extracted 'useful values' snippet into the interpreted function — a YouTube player change silently breaks decryption, and malformed code raises JSInterpreter.Exception. — [youtube_dl/jsinterp.py#L402](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/jsinterp.py#L402) [youtube_dl/extractor/youtube.py#L1905-1952](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/youtube.py#L1905-L1952) [youtube_dl/extractor/youtube.py#L1983-1999](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/youtube.py#L1983-L1999)
- swfinterp.py (834 lines, SWFInterpreter) is effectively dead production code — the only importer in the tree is test/test_swfinterp.py; PhantomJSwrapper in extractor/openload.py survives only as a dependency of pornhub.py and a debug-header version probe. — [youtube_dl/swfinterp.py#L185](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/swfinterp.py#L185) [test/test_swfinterp.py#L18](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/test/test_swfinterp.py#L18) [youtube_dl/extractor/pornhub.py#L54](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/pornhub.py#L54) [youtube_dl/YoutubeDL.py#L2562](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/YoutubeDL.py#L2562)
- Extractors are regex-fragile by design: _search_regex raises RegexNotFoundError on missing patterns and CONTRIBUTING.md explicitly warns that extractor breakage on site changes is expected; broken extractors are flagged via the _WORKING class attribute rather than removed. — [youtube_dl/extractor/common.py#L1063-1098](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/common.py#L1063-L1098) [youtube_dl/extractor/common.py#L415-416](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/common.py#L415-L416) [CONTRIBUTING.md#L174-188](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/CONTRIBUTING.md#L174-L188)
- --call-home/--verbose debug path sends requests to https://yt-dl.org/ip and /latest/version, disclosing the user's public IP to the project's own server. — [youtube_dl/YoutubeDL.py#L2578-2587](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/YoutubeDL.py#L2578-L2587)
- Python 2.6 support is still load-bearing: compat.py shims, _workaround_optparse_bug9161, py2exe paths, and CI builds Python 2.6/2.7 from source — code paths that cannot be exercised on modern interpreters and constrain idioms (no f-strings, unicode_literals everywhere). (inferred) — [youtube_dl/compat.py](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/compat.py) [.github/workflows/ci.yml#L249-314](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/.github/workflows/ci.yml#L249-L314) [youtube_dl/__init__.py#L53](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/__init__.py#L53) [setup.py#L128-135](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/setup.py#L128-L135)
- Passwords entered interactively (compat_getpass) or passed via -p/--password appear in argv and config files; _hide_login_info only scrubs them from verbose debug echoes, not from process listings or config storage. (inferred) — [youtube_dl/options.py#L24-39](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/options.py#L24-L39) [youtube_dl/__init__.py#L143-146](https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/__init__.py#L143-L146)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
