Back to skill

Security audit

Bilibili All In One

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real Bilibili toolkit, but users should review it because full session cookies can be attached to broader network requests than the documentation promises.

Install only if you are comfortable giving the skill full Bilibili session cookies. Prefer using it without credentials where possible, avoid BILIBILI_PERSIST, use a throwaway account for publishing or high-quality downloads, and run it in an isolated environment while reviewing outbound traffic.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
src/subtitle.py:158
Finding

Full Session Cookies Sent to an Unvalidated API-Provided Subtitle URL

Content
View full analysis
httpx.AsyncClient: """Create an authenticated async HTTP client. Returns: httpx.AsyncClient configured with credentials. """ return httpx.AsyncClient( headers=self.get_headers(), cookies=self.cookies, timeout=30.0, follow_redirects=True, ) ``` `main.py:52-61` supplies this authentication object to the subtitle module even though public subtitle operations do not normally require authentication: ```python # Initialize all modules self.hot_monitor = HotMonitor(auth=self.auth) self.downloader = BilibiliDownloader(auth=self.auth) self.watcher = BilibiliWatcher(auth=self.auth) self.player = BilibiliPlayer(auth=self.auth) self.subtitle = SubtitleDownloader( auth=self.auth, downloader=self.downloader, player=self.player, ) ``` `src/subtitle.py:158-164` takes a URL returned by the remote API and requests it through the authenticated client without validating the destination: ```python # Download subtitle JSON sub_url = target_sub["url"] if sub_url.startswith("//"): sub_url = "https:" + sub_url async with self._get_client() as client: resp = await client.get(sub_url) sub_data = resp.json() ``` ### Technical Analysis The authentication client is initialized with the complete cookie set returned by `self.cookies`, including `SESSDATA`, `bili_jct`, and `buvid3`. These are full browser-session credentials rather than narrowly scoped API tokens. The subtitle URL originates in the Bilibili subtitle metadata response and is not checked against an HTTPS ho ...[truncated 2242 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/publisher.py:571
Finding

Bilibili Session Cookies Unnecessarily Transmitted to the Upload CDN

Content
View full analysis
httpx.AsyncClient: """Create an authenticated async HTTP client. Returns: httpx.AsyncClient configured with credentials. """ return httpx.AsyncClient( headers=self.get_headers(), cookies=self.cookies, timeout=30.0, follow_redirects=True, ) ``` `src/publisher.py:571-649` uses that authenticated client for upload-CDN requests even though the upload is separately authorized using `X-Upos-Auth`: ```python upos_uri = preupload["upos_uri"] auth = preupload.get("auth") biz_id = preupload.get("biz_id") chunk_size = preupload.get("chunk_size", 4 * 1024 * 1024) file_size = preupload["file_size"] # Extract upos key from URI upos_key = upos_uri.replace("upos://", "") filename = upos_key.split("/")[-1].split(".")[0] # Calculate chunk count chunk_count = (file_size + chunk_size - 1) // chunk_size # Init upload upload_base = f"https://upos-sz-upcdnbda2.bilivideo.com/{upos_key}" async with self._get_client() as client: # Fetch upload ID resp = await client.post( upload_base, params={ "uploads": "", "output": "json", }, headers={"X-Upos-Auth": auth} if auth else {}, ) try: init_data = resp.json() upload_id = init_data.get("upload_id", "") except Exception: return {"success": False, "message": "Failed to initialize upload"} # Upload chunks with open(file_path, "rb") as f: for chunk_idx in range(chunk_count): chunk_data = f.read(chunk_size) start = chunk_idx * chunk_size end = min(start + len(chunk_data), file_s ...[truncated 3752 chars]
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (38)

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

The README instructs users to place active Bilibili session cookies in a local credentials.json file. Storing reusable authentication material in a plaintext file materially increases the risk of credential theft via local malware, accidental commits, backups, shell history, or other users on the same machine, especially because these cookies enable authenticated actions such as publishing or high-quality downloads.

Content

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

方式二:凭据文件

创建 credentials.json:

json
{

Credential Access

High
Category
Privilege Escalation
Confidence
94% confidence
Finding

The documented optional persistence feature automatically saves sensitive Bilibili cookies to .credentials.json and reloads them on startup. Even with 0600 permissions, disk persistence expands the attack surface by leaving long-lived session material available to local compromise, backups, accidental inclusion in archives, or unsafe workspace sharing; in this skill context the impact is elevated because the same credentials can authorize account actions like video upload and editing.

Content

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

app.auth.clear_persisted()

text

启用后,凭据自动保存到项目根目录的 `.credentials.json`(权限 `0600`,仅所有者可读写),下次启动时自动加载。

> 💡 **如何获取 Cookie?** 登录 [bilibili.com](https://www.bilibili.com) → 按 F12 打开开发者工具 → Application → Cookies → 复制 `SESSDATA`、`bili_jct`、`buvid3` 的值。

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Yes, this is a mismatch. The declared description is about end-user Bilibili features: trending, downloading, playback, subtitles, and video publishing to Bilibili. The actual code chunk does none of those things. Instead, it is a developer-facing release helper that bumps a semantic version in skill.json and runs clawhub publish to publish the skill itself. That is a materially different purpose and uses different resources than declared. Although the comment notes this script is excluded from the shipped package, the supplied code chunk itself still does not implement the described Bilibili functionality.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The supplied code is specifically a downloader module (src/downloader.py). It supports getting video info, enumerating formats, downloading single or multiple videos, selecting DASH audio/video streams, and merging them with ffmpeg. It does not implement trending monitoring, playback, subtitle download, or publishing in this chunk. There is no evidence here of upload/publish flows or subtitle APIs. While the code is consistent with part of the declared description (video downloading, optional auth integration, HTTPS requests to Bilibili endpoints), the declared purpose materially overstates what this supplied code chunk actually does. This is a description-versus-code mismatch for the chunk provided.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The code shown is narrowly focused on monitoring and retrieving Bilibili trending/ranking data via HTTP GET requests. It does not implement downloading videos, playing/watching videos, downloading subtitles, or publishing content. While the monitoring portion matches part of the declared description, the declared purpose presents a much broader unified toolkit than this code chunk actually demonstrates. Optional auth support exists only as a client source and is not used here for publishing. Therefore the description overstates the implemented capabilities for the provided code.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The supplied code is narrowly focused on subtitle handling rather than the full toolkit described. It does accurately include subtitle downloading from Bilibili and uses HTTPS requests via httpx to Bilibili API/URLs, so that part aligns. However, the chunk also performs additional subtitle-adjacent capabilities not stated in the description: converting and merging local subtitle files, generating subtitles through speech recognition using faster-whisper after downloading audio, and exporting danmaku as SRT-like text via a player dependency. Those are undeclared capabilities. Also, this chunk does not evidence the broader declared functions like hot trending monitoring, playback, video publishing, or general video downloading; while absence alone in a partial chunk is not necessarily a mismatch, the actual behavior here is materially narrower and includes extra fallback processing capabilities not mentioned.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

The supplied code is narrowly focused on a watcher module. It parses Bilibili video URLs, calls video detail/info APIs, returns metadata and engagement metrics, tracks those metrics over time, and compares stats across videos. That partially matches the declared 'video watching/playback' aspect, but the declared description presents a comprehensive multi-capability toolkit including downloading, subtitles, publishing, and trending monitoring. Those capabilities are not present in this code chunk. Because the evaluation is description versus this supplied code chunk, the description overstates the functionality materially, so this should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

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 · main.py (reported line 46)May include surrounding context.

python
credential_file: Path to JSON credential file.
            persist: Whether to persist credentials to disk (default: False).
                Set to True or env BILIBILI_PERSIST=1 to auto-save/load
                credentials from .credentials.json.
        """
        self.auth = BilibiliAuth(
            sessdata=sessdata,

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 · skill.md (reported line 119)May include surrounding context.

md
credential_file: Path to JSON credential file.
            persist: Whether to persist credentials to disk (default: False).
                Set to True or env BILIBILI_PERSIST=1 to auto-save/load
                credentials from .credentials.json.
        """
        self.auth = BilibiliAuth(
            sessdata=sessdata,

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 · src/auth.py (reported line 73)May include surrounding context.

python
credential_file: Path to JSON credential file.
            persist: Whether to persist credentials to disk (default: False).
                Set to True or env BILIBILI_PERSIST=1 to auto-save/load
                credentials from .credentials.json.
        """
        self.auth = BilibiliAuth(
            sessdata=sessdata,

Known Vulnerable Dependency: aiohttp==3.10.11 — 16 advisory(ies): CVE-2026-54279 (aiohttp: Host-Only Cookies Become Domain Cookies After CookieJar Persistence); CVE-2026-34514 (AIOHTTP has CRLF injection through multipart part content type header constructi); CVE-2026-34517 (AIOHTTP has late size enforcement for non-file multipart fields causes memory Do) +13 more

High
Category
Supply Chain
Confidence
97% confidence
Finding

The dependency is pinned to aiohttp 3.10.11, which the finding reports as affected by multiple high-severity advisories including cookie scope handling and multipart parsing issues. In a network-heavy skill that performs authenticated requests and may handle uploads/downloads, these flaws can plausibly expose session cookies, enable request/header manipulation, or cause denial of service if attacker-controlled responses or content are processed.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: lxml==5.3.0 — 2 advisory(ies): CVE-2026-41066 (lxml: Default configuration of iterparse() and ETCompatXMLParser() allows XXE to); CVE-2026-41066 (lxml is a library for processing XML and HTML in the Python language. Prior to 6)

High
Category
Supply Chain
Confidence
93% confidence
Finding

lxml 5.3.0 is flagged for XXE-related issues in parser configurations such as iterparse() and ETCompatXMLParser(). Because this skill includes HTML/XML parsing libraries and interacts with remote web content, an unsafe parser path could let crafted XML trigger external entity resolution, potentially disclosing local files, making network requests, or consuming resources.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
83% confidence
Finding

The skill supports optional persistence of live Bilibili session cookies to a local .credentials.json file. Even with opt-in behavior and documented 0600 permissions, persisted session cookies are replayable bearer credentials, so compromise of that file could let other software act as the user on Bilibili.

Content

Scanner excerpt · skill.json (reported line 53)May include surrounding context.

json
{
      "name": "BILIBILI_PERSIST",
      "type": "string",
      "description": "Set to '1', 'true', or 'yes' to enable automatic credential persistence. When enabled, credentials are saved to .credentials.json (0600 permissions) and auto-loaded on next startup. Default: disabled (in-memory only).",
      "required": false,
      "sensitive": false
    }

Credential Access

High
Category
Privilege Escalation
Confidence
87% confidence
Finding

The storage model explicitly allows auto-save/auto-load of Bilibili session cookies from .credentials.json when persistence is enabled. Because these cookies can be replayed against official Bilibili endpoints, local disclosure of the file could result in account takeover within the scope of the stored session.

Content

Scanner excerpt · skill.json (reported line 70)May include surrounding context.

json
"revocation": "Log out from bilibili.com or clear cookies to invalidate the credential at any time."
    },
    "credential_scope_warning": "These are Bilibili session cookies. Although the skill only uses them against official Bilibili endpoints listed in `scope_limitations.outbound_destinations`, the cookies themselves — if they leak outside this process — could be replayed against Bilibili by other software. Use a test/throwaway account and rotate cookies after use.",
    "storage": "in-memory by default. Set persist=True (or env BILIBILI_PERSIST=1) to auto-save/load credentials from .credentials.json with 0600 permissions. The file is ignored if older than 30 days, refused if the containing directory is group/world-writable, and can be removed via auth.clear_persisted().",
    "security_notes": [
      "Credentials are NOT persisted to disk by default. Persistence must be explicitly opted-in via persist=True or BILIBILI_PERSIST=1.",
      "When persisted, the credential file is written with mode 0600, refused in unsafe directories, and auto-expires after 30 days.",

Credential Access

High
Category
Privilege Escalation
Confidence
86% confidence
Finding

This documents automatic persistence of full Bilibili session cookies to a predictable local file (.credentials.json). Even with 0600 permissions, storing reusable browser session cookies on disk materially increases the attack surface through local compromise, accidental backup/sync leakage, or mishandling in shared/containerized environments.

Content

Scanner excerpt · skill.md (reported line 158)May include surrounding context.

text

When persistence is enabled:
- Credentials are auto-saved to `.credentials.json` (with `0600` permissions) after initialization
- On next startup, credentials are auto-loaded from this file
- You can toggle persistence at runtime: `app.auth.persist = True` / `app.auth.persist = False`
- To delete the persisted file: `app.auth.clear_persisted()`

Credential Access

High
Category
Privilege Escalation
Confidence
83% confidence
Finding

This section explicitly states that credentials can be persisted to .credentials.json and manually saved with auth.save_to_file(), confirming support for disk storage of full browser session cookies. In the context of a publishing/downloading skill that accepts broad account cookies, persistence makes compromise more damaging because theft of the file can grant account access beyond the intended action.

Content

Scanner excerpt · skill.md (reported line 177)May include surrounding context.

md
| **Which features require authentication?** | Publishing (upload/edit/schedule/draft), downloading 1080p+/4K quality videos |
| **Which features work WITHOUT credentials?** | Hot monitoring, standard-quality downloads, subtitle listing, danmaku fetching, stats viewing |
| **Where are credentials sent?** | To official Bilibili API endpoints (`api.bilibili.com`, `member.bilibili.com`) over HTTPS only |
| **Are credentials persisted to disk?** | **NO** by default — credentials stay in memory. Set `persist=True` or `BILIBILI_PERSIST=1` to opt-in to automatic persistence (saved to `.credentials.json` with `0600` permissions). You can also manually call `auth.save_to_file()` |
| **File permissions for saved credentials** | `0600` (owner read/write only) — restrictive by default |

### Best Practices

Credential Access

High
Category
Privilege Escalation
Confidence
82% confidence
Finding

The module supports persisting live Bilibili session credentials to a predictable file within the project tree. Even though the code applies permission checks and 0600 file mode, storing reusable session cookies on disk increases the attack surface: local compromise, accidental inclusion in backups, repo packaging, or workspace exposure can lead to account takeover for authenticated actions such as publishing.

Content

Scanner excerpt · src/auth.py (reported line 19)May include surrounding context.

python
# Default path for persisted credentials (relative to project root)
DEFAULT_CREDENTIAL_FILE = os.path.join(
    os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
    ".credentials.json",
)

# Maximum age (in seconds) of a persisted credential file before it is

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% 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).

Content

Scanner excerpt · src/auth.py (reported line 140)May include surrounding context.

python
if hasattr(os, "geteuid") and (st.st_mode & (stat.S_IRGRP | stat.S_IROTH)):
            _logger.warning(
                "Ignoring credential file %s: permissions %o allow other users "
                "to read it. Fix with: chmod 600 %s",
                filepath, st.st_mode & 0o777, filepath,
            )
            return

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The file presents the skill description entirely in Chinese and labels this README as the Chinese documentation, while the skill is described as a general-purpose Bilibili tool rather than a region-locked compliance tool. Under the policy rule, forcing a specific language without user opt-in or an explicit justified locale constraint is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: requests==2.32.3 — 4 advisory(ies): CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2026-25645 (Requests has Insecure Temp File Reuse in its extract_zipped_paths() utility func); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs) +1 more

Medium
Category
Supply Chain
Confidence
91% confidence
Finding

requests 2.32.3 is reported as affected by advisories including .netrc credential leakage via malicious URLs. This matters more in a skill that makes outbound HTTPS requests and may run in environments with developer or user credentials present, because attacker-influenced URLs or redirects could potentially cause unintended credential disclosure or unsafe file handling in affected utility code.

Content

No source excerpt is available for this finding.

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
70% confidence
Finding

Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Content

Scanner excerpt · skill.json (reported line 70)May include surrounding context.

json
"""Refuse to write credentials into world/group-accessible locations.

    Guards against "Memory and Context Poisoning": if the project directory
    is shared (e.g. /tmp, a world-writable CI workspace, or a network share),
    another process could read or replace the saved credentials.
    """
    directory = os.path.dirname(os.path.abspath(filepath)) or "."

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
70% confidence
Finding

Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Content

Scanner excerpt · src/auth.py (reported line 34)May include surrounding context.

python
"""Refuse to write credentials into world/group-accessible locations.

    Guards against "Memory and Context Poisoning": if the project directory
    is shared (e.g. /tmp, a world-writable CI workspace, or a network share),
    another process could read or replace the saved credentials.
    """
    directory = os.path.dirname(os.path.abspath(filepath)) or "."

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
70% confidence
Finding

Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Content

Scanner excerpt · src/auth.py (reported line 44)May include surrounding context.

python
"""Refuse to write credentials into world/group-accessible locations.

    Guards against "Memory and Context Poisoning": if the project directory
    is shared (e.g. /tmp, a world-writable CI workspace, or a network share),
    another process could read or replace the saved credentials.
    """
    directory = os.path.dirname(os.path.abspath(filepath)) or "."

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
70% confidence
Finding

Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Content

Scanner excerpt · src/auth.py (reported line 48)May include surrounding context.

python
"""Refuse to write credentials into world/group-accessible locations.

    Guards against "Memory and Context Poisoning": if the project directory
    is shared (e.g. /tmp, a world-writable CI workspace, or a network share),
    another process could read or replace the saved credentials.
    """
    directory = os.path.dirname(os.path.abspath(filepath)) or "."

Static analysis

No suspicious patterns detected.