Back to skill

Security audit

video-downloader-by-browser

Security checks for vulnerabilities and agentic risk

Overview

This skill is a browser-based downloader for gated streaming sites, but it keeps reusable login sessions and can expose cookies and passwords in local files.

Install only if you are comfortable with a tool that controls a visible browser, preserves login sessions across future downloads, and may create local files containing session cookies, page text, screenshots, and password diagnostics. Use a dedicated browser profile/account, avoid sensitive unrelated sites in that profile, delete cookies.json/logininfo.txt/pwinfo.txt/browser logs after use, and only download media you are authorized to save.

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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/browser_ctl.mjs:328
Finding
Unprotected Plaintext Export of Authentication Cookies## Vulnerability Details **File Location**: `scripts/browser_ctl.mjs`, lines 328-337 **Vulnerability Type**: Plaintext credential exposure through an insufficiently protected command channel **Risk Level**: High ### Vulnerable Code ```javascript } else if (op === 'cookies') { // Export all cookies, including HttpOnly cookies such as SESSDATA try { const cookies = await ctx.cookies(); fs.writeFileSync(path.join(ROOT, 'cookies.json'), JSON.stringify(cookies, null, 2)); const names = cookies.map(c => c.name); log('[cookies] dumped', cookies.length, 'cookies;', 'SESSDATA=' + (names.includes('SESSDATA') ? 'present' : 'absent'), '| bili_jct=' + (names.includes('bili_jct') ? 'present' : 'absent')); } catch (e) { log('[cookies err]', e.message.slice(0, 100)); } } ``` ### Technical Analysis The browser controller uses a persistent browser profile and exposes a filesystem command channel through `cmd.txt`. When that file contains the `cookies` command, the controller calls `ctx.cookies()`, which returns all cookies available to the browser context, including HttpOnly authentication cookies. The complete cookie objects and their plaintext values are then written to `cookies.json` in the work directory. The implementation does not: - Restrict exported cookies to the current target domain. - Exclude authentication or anti-CSRF tokens. - Require interactive user confirmation. - Apply an explicit restrictive file mode such as `0600`. - Encrypt the exported data. - Automatically remove the file after use. Because browser cookies frequently function as bearer credentials, possession of this file may be sufficient to impersonate the authenticated user without knowing the account password. This behavior also conflicts with the statement in `README.md` that the tool does not store credentials. ### Attack Path 1. The user signs in to a supported website through the persiste ...[truncated 1261 chars]
Remediation
## Remediation Suggestions 1. Remove the `cookies` command unless cookie export is essential to the documented workflow. 2. If export must remain, require explicit, interactive user approval for every export. 3. Restrict retrieval to an allowlisted domain associated with the current task. 4. Exclude known authentication, session, and anti-CSRF cookies by default. 5. Avoid writing cookie values to disk. Pass narrowly scoped values directly to the process that requires them. 6. If temporary storage is unavoidable, create the file atomically with mode `0600`, use a dedicated private directory, and delete it immediately after use. 7. Add warnings identifying the file as equivalent to an active login session. 8. Update the documentation so it accurately discloses any credential storage or export behavior. 9. Consider isolating each service in a separate browser context so a request for one service cannot expose cookies belonging to another service.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/browser_ctl.mjs:263
Finding
Viewing Passwords and Partial Session Cookies Are Written to Logs and Diagnostic Files## Vulnerability Details **File Location**: `scripts/browser_ctl.mjs`, lines 263-267, 305-326, and 344-397 **Vulnerability Type**: Sensitive information exposure through logging and diagnostic artifacts **Risk Level**: High ### Vulnerable Code ```javascript const lines = fs.readFileSync(CMD, 'utf8') .split('\n') .map((s) => s.trim()) .filter(Boolean); fs.unlinkSync(CMD); for (const line of lines) { log('[CMD]', line); const [op, arg] = line.split(/\s+/); ``` ```javascript const loginCookies = cookies .filter(c => /^(unb|tracknick|cookie2|_l_g_)$/.test(c.name)) .map(c => `${c.name}=${String(c.value).slice(0, 16)}`); fs.writeFileSync(path.join(ROOT, 'logininfo.txt'), JSON.stringify({ loggedIn, hasUnb, pageHasLoginBtn: pageLoginBtn, loginCookies, allCookieNames: names }, null, 2)); log('[logininfo]', loggedIn ? 'logged in' : 'not logged in', '| login cookies:', loginCookies.join(', ') || '(none)'); ``` ```javascript } else if (op === 'pwinfo') { const js = `(() => { let el = document.querySelector('${PW_INPUT}'); if (!el) return 'no-input'; let node = el; for (let i=0;i<6 && node.parentElement;i++) node = node.parentElement; return JSON.stringify({ inputVal: el.value, containerClass: node.className, html: node.outerHTML.slice(0,1500) }); })()`; try { fs.writeFileSync( path.join(ROOT, 'pwinfo.txt'), String(await page.evaluate(js)) ); log('[pwinfo] saved'); } catch (e) { log('[pwinfo err]', e.message.slice(0, 60)); } } ``` ```javascript } else if (op === 'pwauto') { const pwd = line.slice(7).trim(); try { const handle = await page.$(PW_INPUT); if (!handle) { log('[pwauto] no-input'); continue; } await handle.click({ clickCount: 3 }).catch(() => {}); awai ...[truncated 2542 chars]
Remediation
## Remediation Suggestions 1. Replace `log('[CMD]', line)` with operation-only logging: ```javascript log('[CMD]', op); ``` 2. Maintain a sensitive-command list and ensure arguments to `pwauto`, `pwfill`, `type`, and `ktype` are never logged. 3. Remove `inputVal` from all `pwauto` and `pwinfo` output. 4. Never persist cookie values in `logininfo.txt`; store only Boolean status and non-sensitive cookie names when necessary. 5. Create diagnostic files with mode `0600` and place them in a private directory with mode `0700`. 6. Automatically remove password and authentication diagnostics when the operation completes. 7. Add tests that submit recognizable secret values and fail if those values appear in any generated file or log. 8. Document a cleanup process for existing `browser.log`, `pwinfo.txt`, `logininfo.txt`, and related backups.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/cleanup.py:45
Finding
AppleScript Injection Through an Unescaped Cleanup Path## Vulnerability Details **File Location**: `scripts/cleanup.py`, lines 45-50 **Vulnerability Type**: Command injection through dynamically constructed AppleScript source **Risk Level**: High ### Vulnerable Code ```python def to_trash_macos(path): """macOS: Move to Trash using Finder, with a direct Trash fallback.""" r = subprocess.run([ 'osascript', '-e', f'tell application "Finder" to delete POSIX file "{path}"' ], capture_output=True, text=True) if r.returncode == 0: return True ``` ### Technical Analysis Although `subprocess.run` is invoked without `shell=True`, the path is embedded directly into AppleScript source passed to `osascript -e`. Shell avoidance therefore does not prevent injection at the AppleScript language layer. The `path` value is derived from user-controlled command-line arguments: ```python root = args[0] segdir = args[1] if len(args) > 1 else 'seg' segpath = os.path.join(root, segdir) ``` A path containing a double quote followed by valid AppleScript syntax can terminate the intended string literal and append attacker-controlled statements. When cleanup reaches `to_trash_macos`, `osascript` evaluates the resulting script with the privileges and automation permissions of the invoking user. ### Attack Path 1. An attacker creates or causes the user to operate on a directory whose name contains AppleScript metacharacters and injected source. 2. The attacker ensures that the directory contains segment files and that a sufficiently large apparent merged video exists, allowing the cleanup safety checks to pass. 3. The user invokes `cleanup.py` on the crafted work or segment path. 4. On macOS, the program interpolates the crafted path into: ```applescript tell application "Finder" to delete POSIX file "<attacker-controlled path>" ``` 5. The embedded quote terminates the path string and the appended AppleScript is parsed a ...[truncated 693 chars]
Remediation
## Remediation Suggestions Do not interpolate a path into executable AppleScript source. Pass it as an argument to a fixed script: ```python script = ''' on run argv set targetPath to item 1 of argv tell application "Finder" delete POSIX file targetPath end tell end run ''' r = subprocess.run( ['osascript', '-e', script, path], capture_output=True, text=True ) ``` Additional hardening measures: 1. Prefer a maintained native trash API that does not evaluate source code. 2. Resolve the segment path with `os.path.realpath`. 3. Verify that the resolved segment directory remains beneath the intended work directory. 4. Reject paths containing null bytes and handle symbolic links explicitly. 5. Add regression tests using paths containing quotes, backslashes, newlines, and AppleScript-like text. 6. Retain the existing user confirmation and size checks, but do not treat them as defenses against code injection.

T08 · Insecure Dependencies

Warning
Location
scripts/setup.sh:61
Finding
Unpinned Third-Party Packages Installed During Setup## Vulnerability Details **File Location**: `scripts/setup.sh`, lines 61, 73, and 91-95 **Vulnerability Type**: Non-reproducible dependency installation and supply-chain exposure **Risk Level**: Medium ### Vulnerable Code ```bash ( cd "$WORKSPACE" && "$NPM" install playwright-core --no-audit --no-fund ) \ && PW_CORE="$WORKSPACE/node_modules/playwright-core" ``` ```bash ( cd "$SCRIPT_DIR" && "$NPM" install --prefix "$SCRIPT_DIR" playwright-core --no-audit --no-fund ) ``` ```bash echo "==> No system ffmpeg found; attempting to install imageio-ffmpeg..." if [ -n "${PY:-}" ]; then "$PY" -m pip install -q imageio-ffmpeg 2>/dev/null \ && echo "==> imageio-ffmpeg installed" \ || echo "imageio-ffmpeg installation failed" fi ``` ### Technical Analysis The setup script installs `playwright-core` and `imageio-ffmpeg` without exact version constraints, a committed lockfile, or package-hash verification. Each execution can therefore resolve to a different dependency version than the one originally audited. The npm commands also use `--no-audit`, suppressing npm’s vulnerability-audit stage. The pip command suppresses standard error, reducing visibility into registry, certificate, package-resolution, and installation warnings. The package names appear legitimate and are installed through ordinary package managers; no malicious dependency was confirmed. The vulnerability is that the effective code installed and later imported can change after the Skill package itself has been reviewed. ### Attack Path 1. A user follows the documented instruction to run `bash scripts/setup.sh`. 2. The script contacts the configured npm or Python package registry. 3. Because no exact version or integrity hash is specified, the package manager resolves the currently available release. 4. A compromised upstream release, compromised registry account, malicious mirror, or unexpected ...[truncated 781 chars]
Remediation
## Remediation Suggestions 1. Pin exact reviewed versions, for example: ```bash npm install --save-exact playwright-core@<reviewed-version> ``` 2. Commit `package.json` and `package-lock.json`, then use `npm ci` rather than resolving the latest release. 3. Do not disable auditing by default. Run and preserve `npm audit` results. 4. Pin `imageio-ffmpeg` in a requirements file and require hashes: ```text imageio-ffmpeg==<reviewed-version> --hash=sha256:<reviewed-hash> ``` 5. Install Python dependencies with: ```bash python -m pip install --require-hashes -r requirements.txt ``` 6. Avoid suppressing package-manager errors; surface registry and integrity warnings to the user. 7. Use a dedicated project-local environment instead of modifying a shared managed workspace where feasible. 8. Periodically update pins through an explicit review process that includes provenance, vulnerability, and compatibility checks.
Vulnerability Patterns
  • 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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (39)

Ssd 3

Critical
Confidence
100% confidence
Finding
Exporting all cookies, including httpOnly session tokens, to a file for downstream use is a critical capability because it enables full session hijacking outside the browser's security model. In this skill's context, the danger is heightened by the shared persistent profile and support for multiple logged-in streaming platforms, turning a downloader into a credential/session extraction tool.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
声明描述的是一个面向受限流媒体站点的手动辅助下载工具,核心能力应包括有头浏览器交互、网络流拦截、分片下载与 MP4 合并。实际代码仅是一个离线的 MP4 结构解析器:读取本地文件,解析 moov/tkhd/mvhd/stsd 等 box,提取编码、分辨率、音频参数和时长。它既不访问网络,也不处理网页、登录态、验证码、m3u8、TS 分片或下载流程。因此代码实际行为与声明用途存在明显且实质性的功能不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The declared description presents a full end-to-end assisted downloader workflow: open a user-visible browser, let the user manually pass access controls, capture the actual media URL, download segmented media from various streaming formats/sites, and merge into a final MP4. The supplied code chunk only implements a downstream download stage for already-known chunk URLs and sizes loaded from chunks_full.json. Its behavior is limited to parallel byte-range downloading of chunk files, integrity checks, retry logic, caching via .ok markers, and reporting failures. Those are consistent with one component of a segmented video downloader, but several central advertised capabilities are absent from this code: browser-based manual intervention, stream URL interception, support for protected access flows, playlist handling, and final merge/cleanup. Therefore the code chunk does not accurately represent the declared end-to-end purpose on its own.

Ssd 4

High
Confidence
98% confidence
Finding
The skill explicitly instructs the agent to help users defeat site access controls by using a visible browser for manual authentication and then intercepting the real media stream URL for out-of-band download. This facilitates unauthorized copying of protected or access-restricted content after login, captcha, password, or membership checks, undermining platform controls and potentially exposing authenticated session-derived media URLs.

Ssd 4

High
Confidence
97% confidence
Finding
The intervention template coaches the agent to prefill login-related information and walk the user through SMS verification, captcha completion, quality selection, and playback so the system can proceed to capture the stream. This materially lowers the friction of bypassing provider safeguards and operationalizes extraction of protected media using the user's authenticated context.

Ssd 4

High
Confidence
98% confidence
Finding
The skill directs use of a globally shared persistent browser profile so one successful login can be reused across future tasks and sites, preserving authenticated state for repeated capture of protected content. Persistent session reuse increases the blast radius of account compromise, reduces user awareness of continued access, and enables scalable repeated extraction from restricted services.

Ae1

High
Category
analysis-evasion
Content
1. 用 `browser_ctl.mjs` 打开视频页,播放,观察 `netlog2.jsonl` 里的媒体 URL 形态
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
1. 用 `browser_ctl.mjs` 打开视频页,播放,观察 `netlog2.jsonl` 里的媒体 URL 形态
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ssd 3

High
Confidence
90% confidence
Finding
The documented diagnostic behavior explicitly captures visible text and input details from the main document and all iframes. That collection can include sensitive user content and is broader than needed for intercepting media requests, increasing privacy and data-handling risk.

Ssd 3

High
Confidence
95% confidence
Finding
The design intentionally uses a shared persistent browser profile across tasks and sites so login state can be reused. In combination with cookie inspection/export and generic page control, this significantly expands blast radius: compromise in one task can access authenticated state for many unrelated services.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The `cookies` command exports the full browser cookie jar to disk, including authenticated and httpOnly session cookies, for any sites open in the shared profile. In the context of a downloader skill, this exceeds the minimum capability needed to capture media URLs and creates a direct credential/session theft pathway if the work directory, logs, or downstream tools are compromised.

Missing User Warnings

High
Confidence
99% confidence
Finding
This command writes all cookies to `cookies.json` without any confirmation or limitation, including live authentication tokens. That enables silent exfiltration or later replay of authenticated sessions, especially dangerous because the skill intentionally reuses a persistent cross-task browser profile.

Missing User Warnings

High
Confidence
99% confidence
Finding
The `pwinfo` command saves the current password-field value along with surrounding HTML to disk. Writing secrets in plaintext to the filesystem is highly sensitive because it exposes viewing passwords or potentially reused credentials to any local process, user, or downstream log collection.

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Content
import imageio_ffmpeg
        return imageio_ffmpeg.get_ffmpeg_exe()
    except Exception:
        ff = os.popen('which ffmpeg').read().strip()
        if ff:
            return ff
        raise SystemExit('未找到 ffmpeg,请先 pip install imageio-ffmpeg')
Confidence
85% confidence
Finding
Using os.popen('which ffmpeg') relies on shell execution and PATH resolution, which can be influenced by the environment. If an attacker can control PATH or execution context, the script may resolve and later execute a malicious ffmpeg binary, leading to arbitrary code execution under the script's privileges.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
for f in "$SCRIPT_DIR"/*.py; do
    "$PY" -m py_compile "$f" 2>/dev/null && echo "  $(basename "$f") ✓" || echo "  ❌ $(basename "$f") 语法错误"
  done
  rm -rf "$SCRIPT_DIR/__pycache__"
fi

echo ""
Confidence
95% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding
The skill uses 'network' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Vague Triggers

Medium
Confidence
87% confidence
Finding
The manifest description includes generic activation phrases such as “下载视频” and “视频下载”, alongside broader variants like “需要登录的视频” and “需要密码的视频”. In a manifest file, these phrases are not tightly scoped and could collide with ordinary user requests, increasing the chance of unintended invocation.

Natural-Language Policy Violations

Medium
Confidence
82% confidence
Finding
The natural-language description and instructions are presented entirely in Chinese, with no indication that the user may choose another language or that the skill is intended only for a Chinese-language context. Under the policy, a language constraint should be optional or clearly justified.

Session Persistence

Medium
Category
Rogue Agent
Content
### 阶段 1:拉起常驻浏览器

```bash
mkdir -p <工作目录>/shots
node <skill>/scripts/browser_ctl.mjs <工作目录> "<视频页URL>" <正片最小时长>
```
Confidence
91% confidence
Finding
This duplicate finding points to the same session-persistence behavior: a standing browser process plus reusable profile intended to preserve login state. In this skill's context, persistence is more dangerous because it directly supports repeated access to gated content and reduces friction for continued misuse.

Session Persistence

Medium
Category
Rogue Agent
Content
### 阶段 1:拉起常驻浏览器

```bash
mkdir -p <工作目录>/shots
node <skill>/scripts/browser_ctl.mjs <工作目录> "<视频页URL>" <正片最小时长>
```
Confidence
91% confidence
Finding
This duplicate finding points to the same session-persistence behavior: a standing browser process plus reusable profile intended to preserve login state. In this skill's context, persistence is more dangerous because it directly supports repeated access to gated content and reduces friction for continued misuse.

External Transmission

Medium
Category
Data Exfiltration
Content
### 新增平台的标准动作

1. 用 `browser_ctl.mjs` 打开视频页,播放,观察 `netlog2.jsonl` 里的媒体 URL 形态
2. 判断分片规律:改 URL 参数看能取回多大(用 `curl -r 0-0 -D -` 读 `Content-Range` 总长)
3. 找出分片号在 URL 里的位置和进制(**务必确认是十进制还是十六进制**)
4. 写 `scripts/<platform>_collect.py`,复用 `browser_ctl.mjs` 的 seek 通道
5. 若存在“窗口 URL → 整片 URL”的转换,单独写 `<platform>_probe.py`
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
This section documents end-to-end automation of a viewing-password gate, including selectors, input strategy, and browser-level click simulation to defeat front-end protections. In the context of a downloader skill for restricted streaming sites, this materially extends the skill from passive/manual capture into active automation of protected-access controls, which can enable unauthorized acquisition of gated content.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
文档将自动化流程绑定到中文界面文案与特定中文按钮文本,例如“确定”,并以此作为唯一实现路径。该自然语言要求未提供用户选择其他语言/本地化界面的选项,属于语言/locale 约束未显式选择的政策问题。

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The documented capability automates protected UI interaction in a way not necessary for basic browser-assisted downloading: it scripts password entry, submission, success detection, and fallback troubleshooting for a restricted content gate. That makes the skill more dangerous because it operationalizes access-control automation rather than merely observing network requests after a user has legitimately accessed content.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The file command channel exposes generic browser automation primitives such as arbitrary typing, clicking, key presses, and iframe interaction. Because the browser runs with a shared logged-in profile, these commands can be repurposed beyond video playback control to manipulate account settings, approve dialogs, or interact with sensitive pages, making the component effectively a remote browser-control backdoor.

Static analysis

No suspicious patterns detected.