Back to skill

Security audit

视频深读 video-digest

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed YouTube transcript-to-notes helper with ordinary dependency, proxy, and local-storage cautions, not evidence of malicious behavior.

Install only if you are comfortable with YouTube requests, local transcript/note storage under the configured output directory, and yt-dlp being installed from the package ecosystem. Avoid credential-bearing HTTPS_PROXY values or use a local credential-free proxy, and keep transcripts in a directory you are comfortable having the agent read later.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:6
Finding
Unpinned yt-dlp Dependency Creates a Supply-Chain Risk## Vulnerability Details **File Location**: `SKILL.md:6`, `SKILL.md:49`, `README.md:33-36` **Vulnerability Type**: Unpinned third-party dependency **Risk Level**: Medium ### Vulnerable Code `SKILL.md:6`: ```yaml metadata: { "openclaw": { "requires": { "bins": ["python3"], "env": ["HTTPS_PROXY"] }, "install": [ { "kind": "uv", "package": "yt-dlp", "bins": ["yt-dlp"] } ] } } ``` `SKILL.md:49`: ```markdown - 需要 yt-dlp:脚本自动定位托管 venv(`~/.workbuddy/binaries/python/envs/default/bin/python`);若提示找不到,安装:`pip install yt-dlp` ``` `README.md:33-36`: ```bash pip install yt-dlp ``` ```markdown > 供应链提示:为可复现安装,建议固定 yt-dlp 版本(如 `pip install yt-dlp==2025.xx.x`),并按需升级。 ``` ### Technical Analysis The automated installation metadata and primary installation commands resolve `yt-dlp` without an exact version or integrity hash. Consequently, the installed code can change over time without any corresponding change to the reviewed Skill package. The README acknowledges version pinning, but the illustrative `2025.xx.x` value is not an installable exact version, and the actual package metadata remains unpinned. There is also no lockfile, package hash, or other mechanism that guarantees installation of a reviewed artifact. Because `yt-dlp` is imported and executed as Python code through `python -m yt_dlp`, a compromised or unexpectedly malicious future release would execute inside a process launched with the invoking user's privileges. ### Attack Path 1. An attacker compromises the upstream package publication process, maintainer account, package repository, or a future `yt-dlp` release. 2. A user installs or updates this Skill using the unpinned dependency declaration or runs `pip install yt-dlp`. 3. The package resolver retrieves the affected latest release rather than a previously reviewed version. 4. Malicious package code executes during installation, import, or invocation through `python -m yt_dlp`. 5. The depe ...[truncated 731 chars]
Remediation
## Remediation Suggestions 1. Pin `yt-dlp` to an exact, reviewed version in the Skill installation metadata: ```yaml package: "yt-dlp==<reviewed-version>" ``` 2. Replace all generic installation commands with the same exact version. 3. Use a lockfile or hash-verified installation, such as: ```bash pip install --require-hashes -r requirements.txt ``` 4. Record the expected distribution hash from a trusted package source. 5. Test upgrades in an isolated environment before updating the pinned version. 6. Document a controlled update policy, including review of release notes and package provenance. 7. Avoid placeholder versions such as `2025.xx.x`; provide a real, installable version known to be compatible with the Skill.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/fetch_video.py:290
Finding
Authenticated Proxy Credentials Are Exposed in Child-Process Arguments## Vulnerability Details **File Location**: `scripts/fetch_video.py:290-301`, `scripts/fetch_video.py:311-315`, `scripts/fetch_video.py:373-384` **Vulnerability Type**: Plaintext sensitive data in process arguments **Risk Level**: Medium ### Vulnerable Code `scripts/fetch_video.py:290-301`: ```python def yt_dlp_proxy_args(proxy): """构造 yt-dlp 的 --proxy 参数。 本地代理(Clash/V2ray)通常无凭据,只传 scheme://host:port,凭据零暴露; 带凭据的代理只能传完整 URL(受限于 yt-dlp 仅支持参数传代理), 此时打印提示告知进程参数对本机同用户可见。 注:实测 yt-dlp 不读取 HTTPS_PROXY 等环境变量代理,故不能用 env 方式。 """ if not proxy: return [] if "@" in proxy: print(" ⚠ 代理含凭据:将以完整 URL 传入 yt-dlp 参数(仅本机同用户进程可见)", flush=True) return ["--proxy", proxy] ``` `scripts/fetch_video.py:311-315`: ```python dump_cmd = [py, "-m", "yt_dlp", "--dump-json", "--skip-download", "--no-warnings"] dump_cmd += proxy_args dump_cmd.append(url) try: proc = subprocess.run(dump_cmd, capture_output=True, text=True, timeout=120) ``` `scripts/fetch_video.py:373-384`: ```python def build_cmd(): # 同上:固定解释器/模块/参数,仅 URL 与输出路径来自已校验输入,列表传参无 shell cmd = [py, "-m", "yt_dlp", "--skip-download", "--no-warnings"] cmd += proxy_args cmd += ["--write-auto-subs"] if is_auto else ["--write-subs"] cmd += ["--sub-langs", lang_code, "--sub-format", "vtt/best", "-o", os.path.join(vdir, "%(id)s.%(ext)s"), url] return cmd proc2 = None for attempt in (1, 2): try: proc2 = subprocess.run(build_cmd(), capture_output=True, text=True, timeout=180) ``` ### Technical Analysis The script correctly sanitizes proxy URLs before printing them or writing them to `meta.json`. However, when `HTTPS_PROXY` contains user information such as `http://user:password@proxy.example:8080`, the complete value is deliberately inserted into the `yt-dlp` command-line argument l ...[truncated 1939 chars]
Remediation
## Remediation Suggestions 1. Reject credential-bearing proxy URLs by default rather than automatically placing them in process arguments. 2. Require an explicit opt-in flag for authenticated proxies and clearly explain the process-list exposure before execution. 3. Prefer a protected proxy configuration mechanism supported by the dependency that does not expose credentials in command-line arguments. 4. If feasible, invoke a library API in-process and supply proxy authentication through protected runtime configuration rather than spawning a child process with plaintext secrets. 5. Consider using a local credential-free forwarding proxy whose protected configuration contains the upstream credentials. 6. Keep log and metadata sanitization, but do not treat it as sufficient protection for subprocess arguments. 7. Add automated tests confirming that credential-bearing proxy values never appear in logs, persisted metadata, exception output, or child-process arguments under the default configuration. 8. Recommend dedicated, least-privileged, short-lived proxy credentials and prohibit reuse of those credentials for unrelated services.
Vulnerability Patterns
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (6)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The documentation claims the code only fetches YouTube subtitles, but it also supports local transcript retrieval from user-supplied paths and acknowledges out-of-directory reads with only a warning. That mismatch is dangerous because operators may trust the skill as a narrowly scoped network fetcher while it can in practice access arbitrary local files, creating a path for unintended local data exposure.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill uses sensitive capabilities including shell, network, environment-variable access, and file read/write, but it does not declare an explicit tool/permission scope. That weakens enforcement and reviewability: an agent runtime may grant broader access than intended, making it easier for the skill to read or write local data and invoke commands without a clear allowlist.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
for c in candidates:
        if os.path.exists(c) and _is_trusted_interpreter(c):
            try:
                r = subprocess.run([c, "-c", "import yt_dlp"], capture_output=True, timeout=15)
                if r.returncode == 0:
                    return c
            except Exception:
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
dump_cmd += proxy_args
    dump_cmd.append(url)
    try:
        proc = subprocess.run(dump_cmd, capture_output=True, text=True, timeout=120)
    except subprocess.TimeoutExpired:
        return (None, "error", "获取视频信息超时(网络慢或视频较大),可稍后重试")
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
proc2 = None
    for attempt in (1, 2):
        try:
            proc2 = subprocess.run(build_cmd(), capture_output=True, text=True, timeout=180)
            if proc2.returncode == 0:
                break
        except subprocess.TimeoutExpired:
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The docstring states that interface prompts default to Chinese as a localization choice by the author. Because this is a code file and the policy applies to natural-language content in code, this is a language-policy issue: the skill imposes a specific UI language without an explicit user choice or opt-in.

Static analysis

No suspicious patterns detected.