Back to skill

Security audit

Bilibili Fav Downloader

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly behaves like a Bilibili favorites downloader, but its documentation asks users to collect unrelated Douyin session cookies and the installer uses broad system-level dependency installation.

Review carefully before installing. Do not follow the Douyin cookie instructions for a Bilibili downloader, do not export complete browser cookies, and keep any Bilibili cookie file private with restrictive permissions. Prefer a user-local or virtual-environment install with pinned verified dependencies, and enable cron or Telegram only after deciding that scheduled downloads and third-party notifications fit your risk tolerance.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (4)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
references/cookie-guide.md:5
Finding
Collection of Unrelated Douyin Authentication Credentials<![CDATA[ ## Vulnerability Details **File Location**: `references/cookie-guide.md:5-30`; also repeated in `SKILL.md:93-96` **Vulnerability Type**: Unnecessary credential collection and violation of least privilege **Risk Level**: High ### Vulnerable Documentation Segment The following is an English translation of the relevant instructions: ```text 1. Open Chrome/Edge and visit www.douyin.com (note that this is not bilibili.com). 2. Open Developer Tools and select the Network tab. 3. Select a request and copy the complete Cookie header. Alternatively, obtain cookies from: Application → Cookies → https://www.douyin.com Collect sessionid, SESSDATA, uid_tt, and ttwid. Example cookie entries: .douyin.com TRUE / FALSE 0 sessionid your-session-id .douyin.com TRUE / FALSE 0 uid_tt your-user-id douyin.com FALSE / FALSE 0 ttwid your-token ``` ### Technical Analysis The Skill downloads Bilibili favorites and communicates with Bilibili endpoints. It has no legitimate functional requirement for Douyin authentication credentials such as `sessionid`, `uid_tt`, or `ttwid`. The guide nevertheless explicitly directs users to extract a complete Cookie header from `douyin.com`. A complete Cookie header may contain multiple authentication, tracking, and session-management tokens beyond anything required by this Skill. The downloaded script passes the supplied cookie file to Bilibili and `yt-dlp`. Browser-style cookie domain restrictions should normally prevent `.douyin.com` cookies from being sent to Bilibili, and the audited code does not explicitly transmit the file to an attacker-controlled endpoint. Nevertheless, collecting and persistently storing unrelated account credentials violates least-privilege principles and needlessly expands the consequences of local file disclosure. The guide also incorrectly combines Douyin cookie names with Bilibili credentials such as `SESSDATA`, making it more likely that users will export credentials fro ...[truncated 1250 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace every reference to `douyin.com` with the correct Bilibili domain. 2. Remove all requests for Douyin-specific credentials, including `sessionid`, `uid_tt`, and `ttwid`. 3. Request only the minimum Bilibili cookies required for private-favorites access. 4. Do not instruct users to copy an entire Cookie header when a narrower export is sufficient. 5. Provide a correct Netscape-format example containing only `.bilibili.com` entries. 6. Instruct users to restrict cookie-file permissions: ```bash chmod 600 /path/to/cookie.txt ``` 7. Recommend storing the cookie in a user-owned configuration directory rather than a shared or system-wide path. 8. Correct the duplicated Douyin instructions in `SKILL.md:93-96`. 9. Clearly state that authentication cookies must never be committed to source control, included in logs, or shared in support requests. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/setup.sh:39
Finding
Unpinned and Unverified Installation of Executable Dependencies<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup.sh:39-48` **Vulnerability Type**: Mutable dependency retrieval without version or integrity verification **Risk Level**: Medium ### Vulnerable Code ```bash if ! command -v yt-dlp &>/dev/null; then echo "[*] Installing yt-dlp..." if command -v pip3 &>/dev/null; then pip3 install --break-system-packages yt-dlp elif command -v pip &>/dev/null; then pip install yt-dlp else sudo curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o /usr/local/bin/yt-dlp sudo chmod a+rx /usr/local/bin/yt-dlp fi fi ``` The displayed English status message is a translation; the executable commands are unchanged. ### Technical Analysis The installer obtains `yt-dlp` through one of two mutable dependency channels: - `pip install yt-dlp` installs the latest package version available at execution time. - The fallback downloads from a URL containing `/releases/latest/`, whose content can change after this Skill has been reviewed. Neither path pins a reviewed version or validates a cryptographic digest or signature. The fallback then writes the downloaded file to `/usr/local/bin/yt-dlp` with `sudo`, making it a system-wide executable. The PyPI project name and GitHub URL correspond to the expected upstream project; the audit found no typographical package substitution or known attacker-controlled source. The weakness is that future upstream content is trusted without reproducible versioning or integrity validation. Use of `--break-system-packages` also bypasses distribution safeguards and may modify the system Python environment rather than isolating the dependency for this Skill. ### Attack Path 1. A user executes `scripts/setup.sh`. 2. The installer requests the current PyPI release or follows the mutable GitHub `latest` redirect. 3. An upstream account compromise, package-index compromise, malicious future release, or compromised delivery ...[truncated 1135 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin `yt-dlp` to a specifically reviewed version rather than installing the latest release. 2. Verify downloaded binaries against a hardcoded SHA-256 digest obtained through a trusted release process. 3. Where supported, verify the upstream release signature in addition to the checksum. 4. Avoid using a mutable `/releases/latest/` URL. 5. Install Python dependencies into an isolated virtual environment: ```bash python3 -m venv .venv .venv/bin/python -m pip install --require-hashes -r requirements.txt ``` 6. Use a locked requirements file containing exact versions and hashes. 7. Remove `--break-system-packages`; do not modify the distribution-managed Python environment. 8. Prefer a user-local executable directory over `/usr/local/bin` unless system-wide installation is explicitly requested and justified. 9. Display the version and expected checksum before installation, and fail closed if verification does not succeed. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/bilibili_fav_dl.py:107
Finding
Telegram Bot Token Exposed Through Process Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/bilibili_fav_dl.py:107-116` **Vulnerability Type**: Secret exposure in child-process arguments **Risk Level**: Medium ### Vulnerable Code ```python def send_tg(msg): token = os.environ.get("BILIBILI_TG_BOT_TOKEN") chat_id = os.environ.get("BILIBILI_TG_CHAT_ID") if not token or not chat_id: return url = f"https://api.telegram.org/bot{token}/sendMessage" subprocess.run([ "curl", "-s", url, "-d", f"chat_id={chat_id}", "-d", f"text={msg}", "-d", "parse_mode=HTML" ], capture_output=True) ``` ### Technical Analysis Telegram's Bot API embeds the bot token in the URL path. Passing that URL directly as an argument to `curl` places the full token-bearing URL in the child process's command-line argument vector. Depending on the operating system's process-visibility configuration, other local users, monitoring tools, process-accounting services, audit systems, or diagnostic collectors may be able to observe the command line while `curl` is running. Command arguments may also be retained by telemetry even after the process exits. The destination is Telegram's official API, and the message contains aggregate download statistics rather than the Bilibili cookie. The issue is therefore local and operational secret exposure, not evidence of attacker-directed exfiltration. ### Attack Path 1. The user configures `BILIBILI_TG_BOT_TOKEN` and `BILIBILI_TG_CHAT_ID`. 2. At least one video downloads successfully, causing `send_tg()` to run. 3. The script starts `curl` with `https://api.telegram.org/bot<TOKEN>/sendMessage` in its argument list. 4. A local process observer or monitoring agent records the `curl` command line during execution. 5. The observer extracts the bot token. 6. The token is used with Telegram's Bot API to perform actions allowed to that bot until the token is revoked. The observation window may be short, but scheduled execution makes ...[truncated 516 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the `curl` subprocess with an in-process HTTPS client such as `urllib.request` or a carefully managed HTTP library. 2. Ensure the token is never included in process arguments, logs, exception messages, or shell history. 3. Apply explicit connection and read timeouts. 4. Handle non-success HTTP responses without printing the token-bearing URL. 5. Restrict access to the environment or secret store from which the token is loaded. 6. Rotate the existing bot token if process command lines may have been collected. 7. Limit the bot's chat memberships and administrative permissions to the minimum required for notifications. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/bilibili_fav_dl.py:28
Finding
Hard-Coded Global State and Log Paths Bypass User Configuration<![CDATA[ ## Vulnerability Details **File Location**: `scripts/bilibili_fav_dl.py:28-37, 99-101, 128-149` **Vulnerability Type**: Unsafe shared-path usage and inconsistent state-file handling **Risk Level**: Low ### Vulnerable Code ```python DEFAULT_COOKIE_FILE = os.environ.get( "BILIBILI_COOKIE_FILE", "/opt/bilibili-favorites/cookie.txt" ) DEFAULT_OUT_DIR = os.environ.get( "BILIBILI_OUT_DIR", "/opt/bilibili-favorites/downloads" ) STATE_FILE = "/opt/bilibili-favorites/downloaded_bvid.txt" LOG_FILE = "/opt/bilibili-favorites/download.log" def log(msg, also_print=True): ts = datetime.now().strftime("%Y-%m-%d %H:%M:%S") line = f"[{ts}] {msg}" if also_print: print(line) with open(LOG_FILE, "a") as f: f.write(line + "\n") def write_state(bvid): with open(STATE_FILE, "a") as f: f.write(bvid + "\n") ``` The argument and read path are handled separately: ```python parser.add_argument( "--state-file", default=STATE_FILE, help="Downloaded-record file" ) if os.path.exists(args.state_file): with open(args.state_file) as f: downloaded = set(l.strip() for l in f if l.strip()) ``` The displayed help text is an English translation; program behavior is unchanged. ### Technical Analysis The `--state-file` option is used when reading prior state, but `write_state()` ignores it and always appends to the hard-coded `/opt/bilibili-favorites/downloaded_bvid.txt` path. Similarly, all logging is forced into `/opt/bilibili-favorites/download.log`, regardless of the selected output directory or user configuration. This creates a read/write inconsistency: the program may read one state file and write another. In multi-user or scheduled environments, a global path may also mix metadata from separate users or jobs if directory permissions permit shared access. The script does not create `/opt/bilibili-favorites` before opening these files. Running under a normal user account will therefore commonl ...[truncated 1585 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pass the configured path into the state-writing function: ```python def write_state(state_file, bvid): with open(state_file, "a", encoding="utf-8") as file: file.write(bvid + "\n") ``` 2. Call it with `write_state(args.state_file, bvid)`. 3. Add a `--log-file` option and avoid hard-coding `/opt`. 4. Default state and logs to a user-owned directory, such as an XDG state directory or a subdirectory of the selected output directory. 5. Create required directories with restrictive permissions. 6. Open newly created sensitive files with user-only permissions. 7. Do not recommend making `/opt/bilibili-favorites` globally writable. 8. Where practical, reject symbolic-link destinations or use safe file-opening flags appropriate to the target operating system. 9. Use separate state and log files for each configured favorite ID to avoid cross-job interference. 10. Update the cron example to use user-owned state and log locations instead of `/var/log` and `/opt`. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (23)

Ssd 3

High
Confidence
97% confidence
Finding
The workflow directly instructs users to obtain and supply browser session cookies, which are reusable authentication secrets. Normalizing credential extraction in the skill increases the chance of accidental disclosure, unsafe storage, or misuse by downstream tooling.

Ssd 3

High
Confidence
99% confidence
Finding
The cookie acquisition section provides step-by-step instructions to extract authentication cookies from browser developer tools and export them to a file. This is a credential collection flow, and in this case the domain mismatch further raises the risk of collecting the wrong account secrets.

Intent-Code Divergence

High
Confidence
99% confidence
Finding
The file is a Bilibili cookie guide, but it instructs users to visit douyin.com, collect Douyin cookies, and mix Douyin tokens such as sessionid, uid_tt, and ttwid with Bilibili tokens like SESSDATA and bili_jct. This cross-service credential harvesting is inconsistent with the stated skill purpose and could trick users into disclosing unrelated high-value session tokens, enabling account compromise or unauthorized access on another platform.

Missing User Warnings

High
Confidence
97% confidence
Finding
The guide tells users to copy the full Cookie header or export complete cookie data, which exposes active authentication material well beyond the minimum needed. In a downloader skill context, this is especially dangerous because users are being normalized into exfiltrating reusable session secrets that could be abused for account takeover, private data access, or long-lived unauthorized API use.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill clearly instructs use of shell commands, environment variables, cron persistence, and file paths, but it declares no explicit tool scope or permissions boundaries. That omission weakens reviewability and can cause an agent or user to execute broader capabilities than expected without a clear trust contract.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill asks users to provide authentication cookies but gives no warning that these are equivalent to session credentials and may grant account access if leaked. Users may store or transmit them insecurely because the workflow normalizes handling them like ordinary input files.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
或手动安装:
```bash
# Ubuntu/Debian
sudo apt install ffmpeg
pip3 install yt-dlp

# macOS
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Session Persistence

Medium
Category
Rogue Agent
Content
设置每2小时自动运行(crontab):
```bash
# 编辑 crontab
crontab -e

# 添加:
0 */2 * * * /usr/bin/python3 /path/to/bilibili_fav_dl.py --cookie /path/to/cookie.txt --fav-id 你的收藏夹ID --out-dir /path/to/downloads >> /var/log/bilibili_dl.log 2>&1
Confidence
85% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Intent-Code Divergence

Medium
Confidence
99% confidence
Finding
The cookie instructions tell the user to log into douyin.com even though the skill is for Bilibili favorites. This mismatch is a strong indicator of copied or careless credential-handling guidance and could trick users into exporting unrelated session cookies, exposing accounts unnecessarily.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
f.write(line + "\n")

def curl_api(url, cookie_file):
    r = subprocess.run([
        "curl", "-s", url,
        "-b", cookie_file,
        "-H", "User-Agent: Mozilla/5.0",
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Tainted flow: 'url' from os.environ.get (line 106, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Content
f.write(line + "\n")

def curl_api(url, cookie_file):
    r = subprocess.run([
        "curl", "-s", url,
        "-b", cookie_file,
        "-H", "User-Agent: Mozilla/5.0",
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.

External Transmission

Medium
Category
Data Exfiltration
Content
all_items = []
    pn = 1
    while True:
        url = f"https://api.bilibili.com/x/v3/fav/resource/list?media_id={fav_id}&pn={pn}&ps=20&jsonp=jsonp&type=0"
        data = curl_api(url, cookie_file)
        if data.get("code") != 0:
            log(f"API page{pn} error: {data.get('message')}")
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
return True, "skipped"

    # yt-dlp 最高画质:bestvideo+bestaudio 合并
    result = subprocess.run([
        "yt-dlp",
        "--cookies", cookie_file,
        "-f", "bestvideo[ext=mp4]+bestaudio[ext=m4a]/bestvideo+bestaudio/best",
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

External Transmission

Medium
Category
Data Exfiltration
Content
chat_id = os.environ.get("BILIBILI_TG_CHAT_ID")
    if not token or not chat_id:
        return
    url = f"https://api.telegram.org/bot{token}/sendMessage"
    subprocess.run([
        "curl", "-s", url,
        "-d", f"chat_id={chat_id}",
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if not token or not chat_id:
        return
    url = f"https://api.telegram.org/bot{token}/sendMessage"
    subprocess.run([
        "curl", "-s", url,
        "-d", f"chat_id={chat_id}",
        "-d", f"text={msg}",
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Tainted flow: 'url' from os.environ.get (line 106, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Content
if not token or not chat_id:
        return
    url = f"https://api.telegram.org/bot{token}/sendMessage"
    subprocess.run([
        "curl", "-s", url,
        "-d", f"chat_id={chat_id}",
        "-d", f"text={msg}",
Confidence
83% confidence
Finding
The Telegram bot token from the environment is interpolated directly into the request URL and then passed as a command-line argument to curl. On many systems, process command lines are observable to other local users or monitoring tools, which can expose the bot token and enable unauthorized use of the Telegram bot.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
if ! command -v ffmpeg &>/dev/null; then
    echo "[*] 安装 ffmpeg..."
    if [ "$PKG_MANAGER" = "apt-get" ]; then
        sudo apt-get install -y ffmpeg
    else
        sudo $PKG_MANAGER install -y ffmpeg
    fi
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
if ! command -v ffmpeg &>/dev/null; then
    echo "[*] 安装 ffmpeg..."
    if [ "$PKG_MANAGER" = "apt-get" ]; then
        sudo apt-get install -y ffmpeg
    else
        sudo $PKG_MANAGER install -y ffmpeg
    fi
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
if ! command -v ffmpeg &>/dev/null; then
    echo "[*] 安装 ffmpeg..."
    if [ "$PKG_MANAGER" = "apt-get" ]; then
        sudo apt-get install -y ffmpeg
    else
        sudo $PKG_MANAGER install -y ffmpeg
    fi
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
This shell script uses sudo to install packages and writes an executable into /usr/local/bin, which modifies the host system in a privileged and potentially hard-to-reverse way. Although it prints status messages, it does not warn the user before making these changes or ask for confirmation.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
pip install yt-dlp
    else
        # 下载二进制
        sudo curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o /usr/local/bin/yt-dlp
        sudo chmod a+rx /usr/local/bin/yt-dlp
    fi
else
Confidence
87% confidence
Finding
The script downloads an executable from the network with curl and writes it directly to /usr/local/bin using sudo, without checksum or signature verification. If the download source, release channel, TLS trust chain, or network path is compromised, this could install a trojanized binary with broad system impact.

Missing User Warnings

Low
Confidence
89% confidence
Finding
The Telegram notification feature sends download-related metadata to a third-party messaging service, but the skill does not disclose that data leaves the local machine. This can expose titles, identifiers, timing, and usage patterns, especially when monitoring private favorites.

Natural-Language Policy Violations

Low
Confidence
86% confidence
Finding
All user-visible comments and echo messages are in Chinese, with no indication that the skill is region-specific or that users may select another language. This can violate language/locale policy when a skill imposes a specific language without user opt-in.

Static analysis

No suspicious patterns detected.