Is davincievans/bilibili-subtitle-download-skill safe?
https://github.com/openclaw/skills/tree/main/skills/davincievans/bilibili-subtitle-download-skill
The Bilibili subtitle downloader skill is functionally legitimate but has meaningful security hygiene deficiencies: it stores user Bilibili session credentials at predictable, world-readable paths (both a hardcoded home-directory location and a CWD-relative file), creating a persistent cross-skill credential theft surface in multi-skill agent environments. No active exfiltration, prompt injection attacks, or canary tampering were detected during the monitored install phase, and the clone behavior was clean. The primary risk is that stored Bilibili credentials become a standing target for any co-installed malicious skill, and raw subtitle content from an external CDN is passed to sub-agents without injection-safety framing.
Category Scores
Findings (10)
MEDIUM Bilibili auth cookies written to predictable persistent path -15 ▶
download_and_chunk.py uses a hardcoded COOKIE_FILE path (os.path.expanduser('~/.openclaw/workspace/bilibili_cookie.txt')) to store the user's Bilibili session cookies after QR-code login. The file is written in plaintext, never rotated, and is readable by any process or co-installed skill running as the same user. A malicious companion skill installed later could silently read and exfiltrate this credential without requiring any new user interaction.
MEDIUM Cheese session credentials saved to current working directory -15 ▶
cheese_downloader.py writes a JSON file containing full Bilibili session credentials (SESSDATA, bili_jct, buvid3) to the relative path 'bilibili_cheese_session.json' in whatever directory the agent happens to be running from. If the agent's CWD is a cloud-synced folder, a web-served directory, or any shared location, the credentials are silently exposed. No absolute path, no permission restriction, and no cleanup mechanism is implemented.
MEDIUM Subtitle content fetched from API-returned URLs without domain validation -15 ▶
Both scripts resolve subtitle download URLs from the Bilibili player API response and fetch them directly. The only preprocessing applied is prepending 'https:' to protocol-relative URLs starting with '//'. No allowlist of Bilibili CDN domains is enforced. A MITM attack or a compromised api.bilibili.com response could substitute a URL pointing to an attacker-controlled HTTPS server. The response body's 'body' array is parsed as JSON and written to subtitle chunk files, enabling content injection into the agent's context.
LOW Persistent credentials create cross-skill lateral movement surface -20 ▶
The Bilibili session cookie stored at the fixed predictable path ~/.openclaw/workspace/bilibili_cookie.txt is available to all skills and processes running as the same user for the lifetime of the session. In a multi-skill agent environment, a subsequently installed malicious skill can read this file without triggering any login prompt or user interaction, effectively hijacking the Bilibili session established by this skill.
LOW Undeclared Python library dependencies with no version pinning -15 ▶
The skill depends on bilibili_api, requests, aiohttp, and qrcode but ships with no requirements.txt and no install instructions. bilibili_api is a community-maintained reverse-engineering library that accesses Bilibili's undocumented internal APIs and has historically changed behavior across versions. The skill accesses a private name-mangled attribute (_QrCodeLogin__qr_link) indicating it targets specific internal implementation details that may break without notice and have been exploited in past supply chain incidents.
LOW Sub-agent receives raw external subtitle content without injection safety framing -10 ▶
SKILL.md instructs the host agent to spawn a summarization sub-agent by passing the path to a subtitle chunk file. The subtitle chunk contains text fetched directly from Bilibili's CDN. The sub-agent prompt template ('请阅读以下Bilibili视频字幕分块') includes no XML boundary tags, no untrusted-content warnings, and no instruction to treat the file content as data rather than instructions. A video creator could embed prompt injection in their subtitle track to manipulate the sub-agent.
LOW Login QR code image not cleaned up in cheese_downloader.py -5 ▶
cheese_downloader.py saves the Bilibili login QR code to os.getcwd()/bilibili_login_qr.png and never deletes it after the login flow completes. A QR code login session typically has a 3-5 minute validity window. If another process reads this file within that window, it can authenticate as the user. download_and_chunk.py correctly removes the QR file after successful login; cheese_downloader.py does not.
LOW SKILL.md teaches agent to create and depend on persistent credential file -5 ▶
The workflow section of SKILL.md explicitly states 'successful login saves Cookie to ~/.openclaw/workspace/bilibili_cookie.txt' and instructs the agent to check for this file. This trains the agent to expect and reason about a credential side-effect, making the stored-cookie attack surface discoverable by other skills or agents that read the injected system prompt.
INFO Canary file accesses are from oathe monitoring lifecycle, not skill activity 0 ▶
Filesystem events show .env, .ssh/id_rsa, .aws/credentials, .npmrc, .docker/config.json, and GCP credentials opened at two points: audit(1771938965.103) — 5 seconds before the git clone, consistent with oathe establishing its pre-install canary baseline — and audit(1771938987.730) — after all install and analysis steps, consistent with oathe's post-install integrity verification. The skill's Python scripts were not executed during the audit and could not have accessed these files. All canary files confirmed unmodified.
INFO Clean sparse checkout from official openclaw monorepo 0 ▶
Install performed a shallow sparse git clone from github.com/openclaw/skills targeting only the skill's subdirectory path. The only external network connection was to GitHub (140.82.121.4:443). No unexpected processes were spawned, no filesystem changes occurred outside the designated skill directory, and the connection diff shows no new listening ports or persistent connections after install.