Back to skill

Security audit

video-downloader-enhanced

Security checks for vulnerabilities and agentic risk

Overview

This video downloader is mostly coherent, but it should be reviewed because ordinary fallback paths can automatically use Chrome login cookies, cloud transcription, and unpinned remote YouTube components.

Install only if you are comfortable with a downloader that may invoke yt-dlp against your live Chrome profile when public routes fail. Prefer --asr none or an explicit local ASR backend for sensitive videos, avoid relying on inherited SILICONFLOW_API_KEY in default auto mode, use trusted video URLs only, and consider an isolated browser profile if cookie-backed downloads are needed. No evidence of intentional theft, persistence, or destruction was found.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/asr.py:358
Finding

Default ASR selection can upload video audio to a cloud service without per-invocation consent

Content
View full analysis
openai-whisper > SiliconFlow)" ), ) ``` ```python # scripts/download_video.py:100-108 if not args.metadata_only and args.asr != "none" and result.get("video_path"): asr_result = run_asr( Path(result["video_path"]), Path(result["output_dir"]), backend=args.asr, model=args.asr_model, language=args.asr_language, prompt=args.asr_prompt, max_seconds=args.asr_max_seconds, ) ``` ```python # scripts/asr.py:94-101 if selected_backend == "siliconflow": transcribe_with_siliconflow( audio_path, transcript_path, siliconflow_json_path, model=resolved_model, ) raw_json_path = siliconflow_json_path ``` ```python # scripts/asr.py:358-378 api_key = os.environ.get("SILICONFLOW_API_KEY") if not api_key: raise RuntimeError("SILICONFLOW_API_KEY is required for ASR backend 'siliconflow'.") body, content_type = _multipart_body( fields={"model": model}, file_field="file", file_path=audio_path, file_content_type="audio/mpeg", ) request = Request( SILICONFLOW_TRANSCRIPTION_URL, data=body, headers={ "Authorization": f"Bearer {api_key}", "Content-Type": content_type, }, method="POST", ) try: with urlopen(request, timeout=600) as response: response_text = response.read().decode("utf-8", errors="replace") ``` ...[truncated 2465 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/providers/bilibili.py:72
Finding

Automatic fallback accesses local Chrome cookies without code-enforced consent

Content
View full analysis
dict: yt_dlp = _require_ytdlp() commands = [ [yt_dlp, "--no-playlist", "--dump-single-json", url], [yt_dlp, "--cookies-from-browser", "chrome", "--no-playlist", "--dump-single-json", url], ] return json.loads(_run_first_successful(commands)) ``` ```python # scripts/providers/youtube.py:64-71 def _extract_metadata(url: str) -> dict: commands = [ _base_ytdlp_command() + ["--dump-single-json", url], _base_ytdlp_command() + ["--remote-components", "ejs:github", "--dump-single-json", url], _base_ytdlp_command() + ["--cookies-from-browser", "chrome", "--dump-single-json", url], ] return json.loads(_run_first_successful(commands)) ``` ```python # scripts/providers/douyin.py:255-263 def _extract_metadata_with_ytdlp(url: str) -> dict: yt_dlp = _require_ytdlp() commands = [ [yt_dlp, "--no-playlist", "--dump-single-json", url], [yt_dlp, "--cookies-from-browser", "chrome", "--no-playlist", "--dump-single-json", url], ] return json.loads(_run_first_successful(commands)) ``` ```python # scripts/providers/xiaohongshu.py:191-211 # ---- Route 3: Chrome cookies ---- if _IS_REMOTE_ASSISTANT: # Don't block remote tasks — report immediately raise RuntimeError( "Anonymous yt-dlp and public direct URL both failed. " "Chrome Cookie auth is required but unavailable in remote mode. " "Please run this download f ...[truncated 3347 chars]
Remediation
View remediation

T03 · Remote Payload Retrieval and Execution

Warning
Location
scripts/providers/youtube.py:64
Finding

YouTube fallback retrieves mutable executable components from GitHub at runtime

Content
View full analysis
dict: commands = [ _base_ytdlp_command() + ["--dump-single-json", url], _base_ytdlp_command() + ["--remote-components", "ejs:github", "--dump-single-json", url], _base_ytdlp_command() + ["--cookies-from-browser", "chrome", "--dump-single-json", url], ] ``` ```python # scripts/providers/youtube.py:84-87 commands = [ _download_command(output_path) + [url], _download_command(output_path, remote_components=True) + [url], _download_command(output_path, cookies=True) + [url], ] ``` ```python # scripts/providers/youtube.py:114-120 def _download_command( output_path: Path, *, remote_components: bool = False, cookies: bool = False, ) -> list[str]: command = _base_ytdlp_command() if remote_components: command.extend(["--remote-components", "ejs:github"]) ``` ### Technical Analysis The YouTube provider automatically retries failed operations with `yt-dlp --remote-components ejs:github`. This option permits `yt-dlp` to retrieve an external EJS component from GitHub and use it as part of video extraction. The remote component is not included in the audited Skill package, and this code does not pin it to a cryptographic digest or audited immutable artifact. Consequently, the effective extraction code can change after the Skill itself has been reviewed. Trust is delegated to the installed `yt-dlp` implementation, GitHub delivery path, remote repository state, and the remote component publisher. This behavior differs from downloading video content: it retrieves code or code-like extraction logic that participates in p ...[truncated 1303 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/providers/xiaohongshu.py:51
Finding

Weak hostname validation and unrestricted redirects permit unintended network destinations

Content
View full analysis
bool: host = urlparse(url).netloc.lower() return any(domain in host for domain in ("xiaohongshu.com", "xhslink.com", "xhslink.cn")) ``` ```python # scripts/providers/xiaohongshu.py:390-418 def _extract_best_direct_url(metadata: dict) -> tuple[str | None, str | None]: """Extract the highest-quality direct video URL from yt-dlp metadata. Checks (in order): formats list, requested_formats, direct url field. Returns: (url, source_field_name) or (None, None). """ formats = metadata.get("formats") or [] # Pick best format: prefer mp4/h264, highest resolution best = None best_score = -1 for fmt in formats: fmt_url = fmt.get("url") if not fmt_url: continue # Score: prefer video formats, higher resolution score = 0 if fmt.get("vcodec") and fmt.get("vcodec") != "none": score += 100 if fmt.get("acodec") and fmt.get("acodec") != "none": score += 10 height = fmt.get("height") or 0 score += height if score > best_score: best_score = score best = fmt if best: return best.get("url"), f"formats[{best.get('format_id', '?')}]" ``` ```python # scripts/providers/xiaohongshu.py:421-443 def _http_download(url: str, destination: Path, headers: dict[str, str]) -> None: """Download a file via HTTP with atomic temp-file replacement. Follows redirects automatically (urllib default). """ request = Request(url, headers=headers) try: with urlopen(requ ...[truncated 4231 chars]
Remediation
View remediation
bool: host = host.rstrip(".").lower() domain = domain.rstrip(".").lower() return host == domain or host.endswith("." + domain) ``` 3. Restrict accepted schemes to `https` unless a documented platform requirement mandates otherwise. 4. Before every connection: - Resolve all destination addresses. - Reject loopback, private, link-local, multicast, unspecified, and reserved addresses. - Explicitly block common cloud metadata addresses. - Defend against DNS rebinding by connecting only to a validated resolved address where feasible. 5. Disable automatic redirects or implement a custom redirect handler that revalidates the scheme, hostname, port, and resolved IP address at every hop. 6. Apply the same validation to: - User-provided share URLs. - `webpage_url` and `original_url`. - Every URL extracted from `formats`, `requested_formats`, or metadata `url` fields. 7. Define platform-specific media CDN allowlists where maintainable. If dynamic CDN hosts are necessary, use a narrowly documented policy instead of unrestricted Internet destinations. 8. Add tests covering deceptive hostnames, username-in-host syntax, trailing dots, mixed case, non-HTTPS schemes, redirects to private addresses, and DNS rebinding scenarios. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (44)

Tainted flow: 'request' from os.environ.get (line 368, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/asr.py (reported line 378)May include surrounding context.

python
method="POST",
    )
    try:
        with urlopen(request, timeout=600) as response:
            response_text = response.read().decode("utf-8", errors="replace")
    except HTTPError as exc:
        detail = _redact_secret(

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · .gitignore (reported line 13)May include surrounding context.

text
venv/

# Secrets and browser credentials
.env
.env.*
!.env.example
cookies.txt

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Confidence
91% confidence
Finding

The README explicitly documents a fallback path using yt-dlp --cookies-from-browser chrome, which accesses local browser authentication material. Even though the text warns about consent and says cookies are not exported, this workflow still authorizes the skill to read sensitive browser credentials and could expose session data or enable unintended authenticated downloads if invoked in an agent context.

Content

Scanner excerpt · README.md (reported line 206)May include surrounding context.

<视频链接>

text

推荐在 Agent 的项目规则中提前约定:

- 默认输出目录;
- 是否启用 ASR;
- 默认 ASR 后端和语言;
- whisper.cpp 模型路径;
- 是否允许读取浏览器 Cookie;
- 是否允许安装或升级系统工具。

## Cookie 与隐私

部分平台无法完全匿名下载。对应 Provider 可能在公开路线失败后调用:

```text
yt-dlp --cookies-from-browser chrome

这会读取本机 Chrome Cookie;在 macOS 上还可能触发钥匙串授权。项目不会生成 cookies.txt,也不会主动将 Cookie 内容写入输出文件,但下载命令本身仍会访问浏览器凭证。

在运行前请确认:

  • 你理解并授权本次浏览器 Cookie 访问;
  • 不把 Cookie 数据库、cookies.txt 或浏览器配置复制进仓库;
  • 远程或无人值守环境中设置 VIDEO_DOWNLOADER_REMOTE=1,使小红书 Provider 在需要 Cookie 时直接报告;
  • 只下载你拥有、获准下载或依法可以保存的�

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Confidence
93% confidence
Finding

The documented fallback to Chrome cookies enables the skill to access browser-authenticated session data to retrieve content. Although framed as a download fallback, browser cookie access is highly sensitive because it can expose authenticated resources and normalize a pattern similar to credential or session-token harvesting if not tightly constrained and explicitly approved.

Content

Scanner excerpt · SKILL.md (reported line 217)May include surrounding context.

md
on metadata.

## Xiaohongshu Provider

The Xiaohongshu provider uses a three-tier download fallback:

1. **Anonymous yt-dlp** — public download without any authentication (no cookies).
2. **Public direct URL** — if metadata is available but anonymous yt-dlp can't download, extracts the highest-quality video stream URL from yt-dlp's formats metadata and downloads it via plain HTTP.
3. **Chrome cookies yt-dlp** — last resort; requires local Chrome browser access.

Metadata extraction is always anonymous — cookies are never triggered just to get author info or metadata.

Important behavior:

- Support `xiaohongshu.com`, `xhslink.com`, and `xhslink.cn` links.
- Store the Xiaohongshu title plus note body in `post_caption.txt`.
- Store `yt-dlp` raw metadata and normalized fields in `metadata.json`.
- Author nickname is taken from anonymous metadata; falls back to `未知作者` when unavailable.
- **Remote assistant**: if both public routes fail, reports "需要在电脑端授权 Chr

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Confidence
92% confidence
Finding

The YARA match is triggered by the use of --cookies-from-browser chrome, which resembles credential-harvesting behavior because it programmatically accesses browser-stored authentication material. Although the apparent purpose is content access rather than outright theft, in an agent-executed environment this is still dangerous because it can silently leverage sensitive browser sessions and normalize infostealer-like behavior.

Content

Scanner excerpt · scripts/providers/bilibili.py (reported line 79)May include surrounding context.

python
"duration_seconds": normalized.get("video", {}).get("duration_seconds"),
        "resolution": normalized.get("video", {}).get("resolution"),
        "download_method": normalized.get("download", {}).get("method"),
    }


def _extract_metadata(url: str) -> dict:
    yt_dlp = _require_ytdlp()
    commands = [
        [yt_dlp, "--no-playlist", "--dump-single-json", url],
        [yt_dlp, "--cookies-from-browser", "chrome", "--no-playlist", "--dump-single-json", url],
    ]
    return json.loads(_run_first_successful(commands))


def _download_video(url: str, folder: Path, filename: str) -> Path:
    yt_dlp = _require_ytdlp()
    output_path = folder / filename
    commands = [
        [
            yt_dlp,
            "--no-playlist",
            "-f",
            "bv*+ba/b",
            "--merge-output-format",
            "mp4",
            "-o",
            str(output_path),
            url,
        ],
        [
            yt_dlp,
            "--cookies-from-browser",

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Confidence
85% confidence
Finding

The info-stealer signature is triggered because the code reads browser cookies from Chrome, which is a sensitive credential-adjacent action. While this is not overt malware by itself and appears aimed at downloader fallback behavior, the capability is still dangerous because it harvests session material from the local browser context without strong scoping or consent controls.

Content

Scanner excerpt · scripts/providers/douyin.py (reported line 263)May include surrounding context.

python
)
                shutil.copyfileobj(response, temp_file)
        temp_path.replace(destination)
    except (HTTPError, URLError) as exc:
        raise RuntimeError(f"Failed to download Douyin video: {exc}") from exc


def _extract_metadata_with_ytdlp(url: str) -> dict:
    yt_dlp = _require_ytdlp()
    commands = [
        [yt_dlp, "--no-playlist", "--dump-single-json", url],
        [yt_dlp, "--cookies-from-browser", "chrome", "--no-playlist", "--dump-single-json", url],
    ]
    return json.loads(_run_first_successful(commands))


def _download_with_ytdlp(url: str, folder: Path, filename: str) -> Path:
    yt_dlp = _require_ytdlp()
    output_path = folder / filename
    commands = [
        [
            yt_dlp,
            "--no-playlist",
            "-f",
            "bv*+ba/b",
            "--merge-output-format",
            "mp4",
            "-o",
            str(output_path),
            url,
        ],
        [
            yt_dlp,
            "--cookies-from-browser",

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/providers/xiaohongshu.py (reported line 36)May include surrounding context.

python
# Regex patterns for cookie auth failure detection
_COOKIE_FAILURE_PATTERNS = [
    r"keychain",
    r"Keychain",
    r"cannot (access|open|read).*cookie",
    r"permission denied.*cookie",

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/providers/xiaohongshu.py (reported line 37)May include surrounding context.

python
# Regex patterns for cookie auth failure detection
_COOKIE_FAILURE_PATTERNS = [
    r"keychain",
    r"Keychain",
    r"cannot (access|open|read).*cookie",
    r"permission denied.*cookie",
    r"cookies?.+not found",

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Confidence
97% confidence
Finding

Using yt-dlp --cookies-from-browser chrome causes the skill to reach into the local Chrome profile and reuse authenticated browser cookies for downloads. In this skill context, that is materially sensitive because it bridges user-triggered content retrieval with access to browser-held credentials, potentially exposing private content access and normalizing implicit credential use without strong user consent boundaries.

Content

Scanner excerpt · scripts/providers/xiaohongshu.py (reported line 465)May include surrounding context.

python
-----------------------------------------------------

def _try_cookie_ytdlp_download(
    url: str,
    folder: Path,
    filename: str,
) -> tuple[Path | None, str | None, bool, dict | None]:
    """Try yt-dlp with Chrome cookies.

    Returns: (video_path, error, cookie_refused)
    """
    yt_dlp = _require_ytdlp()
    output_path = folder / filename
    command = [
        yt_dlp,
        "--cookies-from-browser", "chrome",
        "--no-playlist",
        "-f", "bv*+ba/b",
        "--merge-output-format", "mp4",
        "-o", str(output_path),
        url,
    ]
    try:
        completed = subprocess.run(
            command,
            check=False,
            capture_output=True,
            text=True,
            timeout=900,
        )
        stderr = completed.stderr.strip() or ""
        stdout = completed.stdout.strip() or ""

        if completed.returncode == 0:
            found = _find_output_file(output_path, folder)
            is_valid, validation = _validate_vide

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The provider enables yt-dlp remote component loading from GitHub via --remote-components ejs:github, causing runtime retrieval of external code/components beyond the stated download function. That creates a supply-chain and remote-code trust risk because execution behavior can change based on network-fetched content outside the repository and outside normal review controls.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The provider enables yt-dlp remote component loading from GitHub via --remote-components ejs:github, causing runtime retrieval of external code/components beyond the stated download function. That creates a supply-chain and remote-code trust risk because execution behavior can change based on network-fetched content outside the repository and outside normal review controls.

Content

No source excerpt is available for this finding.

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Confidence
90% confidence
Finding

The YARA match is triggered by direct access to browser cookies via --cookies-from-browser chrome, which overlaps with credential-harvesting patterns because it reads local authenticated session material. In this specific code there is no separate evidence of exfiltration logic, so it is better characterized as risky credential/session access rather than a confirmed stealer, but it is still a real security concern.

Content

Scanner excerpt · scripts/providers/youtube.py (reported line 80)May include surrounding context.

python
solution": normalized.get("video", {}).get("resolution"),
        "download_method": normalized.get("download", {}).get("method"),
    }


def _extract_metadata(url: str) -> dict:
    commands = [
        _base_ytdlp_command() + ["--dump-single-json", url],
        _base_ytdlp_command() + ["--remote-components", "ejs:github", "--dump-single-json", url],
        _base_ytdlp_command()
        + ["--cookies-from-browser", "chrome", "--dump-single-json", url],
    ]
    return json.loads(_run_first_successful(commands))


def _download_video(url: str, folder: Path, filename: str) -> Path:
    output_path = folder / filename
    commands = [
        _download_command(output_path) + [url],
        _download_command(output_path, remote_components=True) + [url],
        _download_command(output_path, cookies=True) + [url],
    ]
    _run_first_successful(commands, timeout=1200)
    if output_path.exists():
        return output_path

    matches = sorted(folder.glob(f"{output_path.stem}.*"))

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The README’s operational instructions, warnings, and usage guidance are presented only in Chinese. Under the policy for natural-language violations, forcing a specific language without user opt-in or a documented justification is a reportable issue.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill describes capabilities that require shell, network, filesystem, and environment access, but it does not declare any explicit tool scope or permission boundaries. This creates an authorization gap where a host agent may execute a powerful downloader/transcriber workflow without clear least-privilege controls or user-visible consent around network access, file writes, and environment-secret usage.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

The skill supports sending extracted audio to a third-party cloud ASR endpoint, which is an external data transmission of potentially sensitive media content. Even if this is intended functionality, it can leak confidential speech, personal data, or regulated content when users or agents do not clearly opt in to cloud processing.

Content

Scanner excerpt · SKILL.md (reported line 146)May include surrounding context.

md
### SiliconFlow (`--asr siliconflow`)

Requires `SILICONFLOW_API_KEY`. Calls `https://api.siliconflow.cn/v1/audio/transcriptions`.

Output artifacts:
- `audio.mp3`

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/asr.py (reported line 15)May include surrounding context.

python
from urllib.error import HTTPError, URLError
from urllib.request import Request, urlopen

SILICONFLOW_TRANSCRIPTION_URL = "https://api.siliconflow.cn/v1/audio/transcriptions"
SILICONFLOW_DEFAULT_MODEL = "FunAudioLLM/SenseVoiceSmall"

# whisper.cpp command and model paths are configurable via environment variables.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The manifest description presents platform-specific video downloading and metadata/caption extraction, with implementation details focused on H5 and yt-dlp routes for supported platforms. This module implements a full audio extraction and ASR pipeline, including backend selection, transcript/SRT generation, and raw transcription artifact writing, which is a materially broader behavior than the manifest's implementation notes describe.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This code can upload extracted audio content to a third-party service using an environment-provided API key, which creates a real privacy and data-governance risk. Videos may contain sensitive speech or personal data, and the transfer occurs at the code level without any built-in policy gate, consent check, or content classification before exfiltrating audio off-host.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The code uploads local audio to a remote transcription endpoint but contains no user-facing warning or consent mechanism in this file. In a downloader/transcription skill, that matters because users may reasonably expect local processing unless remote transfer is made explicit, especially when handling creator content, voice data, or regulated material.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The default prompt instructs the model to use Simplified Chinese and explicitly not use Traditional Chinese whenever the language is Chinese, zh, or Mandarin. This imposes a locale/script preference automatically rather than offering the user a choice, which is a natural-language policy violation under the language/locale rule.

Content

No source excerpt is available for this finding.

Tainted flow: 'data' from pathlib.Path.read_text (line 125, file read) → pathlib.Path.write_text (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/download_video.py (reported line 127)May include surrounding context.

python
return
    data = json.loads(path.read_text(encoding="utf-8"))
    data["asr"] = asr_result
    path.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")


if __name__ == "__main__":

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code falls back to yt-dlp --cookies-from-browser chrome for metadata retrieval, which causes the tool to access local browser authentication cookies without any explicit user consent or warning at this call site. In an agent skill context, that can silently use the operator's logged-in session to access private or account-scoped content and may expose sensitive session-derived data to downstream processing or logs.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/asr.py (reported line 585)May include surrounding context.

python
def _run_first_successful(commands: list[list[str]], *, timeout: int = 240) -> str:
    errors = []
    for command in commands:
        completed = subprocess.run(
            command,
            check=False,
            capture_output=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/providers/bilibili.py (reported line 206)May include surrounding context.

python
def _run_first_successful(commands: list[list[str]], *, timeout: int = 240) -> str:
    errors = []
    for command in commands:
        completed = subprocess.run(
            command,
            check=False,
            capture_output=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/providers/youtube.py (reported line 219)May include surrounding context.

python
def _run_first_successful(commands: list[list[str]], *, timeout: int = 240) -> str:
    errors = []
    for command in commands:
        completed = subprocess.run(
            command,
            check=False,
            capture_output=True,