Skip to content

fix(yt-dlp): terminate yt-dlp option parsing and validate the link - #444

Open
Wenjix wants to merge 1 commit into
hypit-ai:mainfrom
Wenjix:security/yt-dlp-argument-separator
Open

Wenjix wants to merge 1 commit into
hypit-ai:mainfrom
Wenjix:security/yt-dlp-argument-separator

Conversation

@Wenjix

@Wenjix Wenjix commented Oct 27, 2026 •

Copy link
Copy Markdown

Closes #452

Summary

  • 13 (medium, CWE-88): downloadVideo in packages/yt-dlp/src/download.ts appended the URL as a bare positional argument with no -- separator, and the exported function trusted its caller to have run isVideoUrl. A value shaped like --plugin-dirs=<dir> was parsed by yt-dlp as an option: it re-enabled the plugin search that --no-plugin-dirs had just disabled, loading and running Python code from a caller-named directory. Other option-shaped values (--exec, --paths, --config) were similarly injectable.
  • Fix: downloadVideo asserts isVideoUrl itself (http/https only — the same rule the CLI layer applied) and passes the link behind a literal -- end-of-options separator. The existing option set (--ignore-config, --no-plugin-dirs, --no-remote-components, …) is unchanged.

Behavior relative to main

Call main this PR
downloadVideo("https://…/v", t) fetched fetched (link after --)
downloadVideo("--plugin-dirs=/tmp/evil", t) flag re-enabled → Python code exec must be an http or https URL
downloadVideo("file:///etc/passwd", t) reached yt-dlp as a bare arg must be an http or https URL

Red / green

packages/yt-dlp/test/download.test.ts: the mocked-execFile test now asserts args.at(-2) === "--" before the link (fails on main — link was args.at(-1) with no separator), plus a new test asserting option-shaped and file: links reject before the environment is even probed.

Verification

  • node --import tsx --test packages/yt-dlp/test/download.test.ts — 6 pass.
  • pnpm check — clean.

Merge Danger

  • downloadVideo now rejects non-URL input itself; callers relying on it to pass through arbitrary strings (none in-repo) get an error.

Checklist

  • The why is documented in this description.
  • Regression tests added; fail on main, pass here.
  • TypeScript check clean.

Generated with Devin

The video URL was appended as a bare positional argument, so a
caller-supplied value shaped like "--plugin-dirs=<dir>" was parsed as a
flag: it re-enabled the plugin search --no-plugin-dirs had just disabled
and ran Python code from a caller-named directory. Exported downloadVideo
also trusted its caller to have run isVideoUrl.

Assert the link is http/https inside downloadVideo and pass it behind a
"--" end-of-options separator.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 27, 2026 06:16

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

SanHsien added a commit to SanHsien/hypit that referenced this pull request Oct 28, 2026
Port of upstream PR hypit-ai#444 (issue hypit-ai#452, head d137a53); the diff does not
apply to this fork's base, so the design is ported. downloadVideo passed the
caller's link as the last yt-dlp argument with no `--`, so a link such as
`--plugin-dirs=<dir>` was parsed as an option and could run Python code from
that directory. Validate the link with isVideoUrl first and put it behind
`--`. The new tests failed before the fix (the option-shaped link reached the
environment check) and pass after.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SanHsien added a commit to SanHsien/hypit that referenced this pull request Oct 28, 2026
…i#447-hypit-ai#456; advance watermarks

PRs hypit-ai#442, hypit-ai#443 and hypit-ai#444 were ported ahead of upstream (d5afdfe, 541ab59,
5dc763c) because the fork has the same defect and it is reachable from
outside input. The rest are recorded with the fork-side evidence and a
re-review trigger in docs/fork/DECISIONS.md. Release track unchanged at
v0.3.1; watermarks PR 455, issue 456.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(yt-dlp): link parsed as an option can re-enable plugin execution

2 participants