Back to skill

Security audit

bilibili-all-in-one

Security checks for vulnerabilities and agentic risk

Overview

This Bilibili tool is mostly purpose-aligned, but it handles full account session cookies with weaker destination boundaries and inconsistent persistence disclosures than users should accept without review.

Install only after reviewing the cookie risk. Use a throwaway Bilibili account, avoid BILIBILI_PERSIST and credential files unless necessary, rotate cookies after use, update the pinned dependencies, and only run publishing actions after checking the dry-run preview. The maintainer should split authenticated and unauthenticated HTTP clients, validate subtitle/download/upload destinations, and disable cross-origin redirects for cookie-bearing requests.

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

T09 · Insecure Skill Coding Practices

Error
Location
src/auth.py:202
Finding

Full-session cookies may be transmitted to insufficiently constrained destinations

Content
View full analysis

Vulnerability Details

File Location: src/auth.py:202-207
Related Sinks: src/subtitle.py:158-163, src/publisher.py:585-613
Vulnerability Type: Cross-domain credential exposure and excessive credential propagation
Risk Level: High

Vulnerable Code

src/auth.py:202-207 creates a reusable client with broadly configured authentication cookies and automatic redirect following:

python
return httpx.AsyncClient(
    headers=self.get_headers(),
    cookies=self.cookies,
    timeout=30.0,
    follow_redirects=True,
)

src/subtitle.py:158-163 uses that authenticated client to request a URL obtained from an API response without validating its hostname:

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

src/publisher.py:585-613 also uses the authenticated client for a separate upload CDN:

python
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_size)

        async with self._get_client() as client:
            resp = await client.put(
                upload_base,

Technical Analysis

...[truncated 3705 chars]

Remediation
View remediation

Remediation Suggestions

  1. Use separate clients by trust boundary.

    • Use an authenticated API client only for exact Bilibili API endpoints that require session cookies.
    • Use an unauthenticated client for subtitle documents, media streams, covers, and public APIs.
    • Use a dedicated upload client containing only X-Upos-Auth for the upload CDN.
  2. Domain-scope every cookie explicitly.

    • Scope account cookies to the minimum required Bilibili hostname and path.
    • Do not create session cookies with an empty or unrestricted domain.
    • Avoid sending bili_jct as a cookie where only a request parameter or body field is required.
  3. Validate remote destinations before each request.

    • Require https.
    • Compare normalized hostnames against a strict allowlist of exact expected domains.
    • Reject embedded credentials, nonstandard schemes, unexpected ports, IP literals, and malformed URLs.
    • Do not rely on substring or suffix-only hostname checks.
  4. Constrain redirects.

    • Disable follow_redirects for authenticated clients.
    • If redirects are operationally required, validate every redirect target and strip cookies and authorization data whenever the origin changes.
  5. Harden subtitle retrieval.

    • Resolve protocol-relative subtitle URLs only after hostname validation.
    • Fetch subtitle JSON with a cookie-free client.
    • Apply response-size limits, timeouts, and content-type validation.
  6. Harden upload requests.

    • Send upload chunks through a dedicated client without SESSDATA, bili_jct, or buvid3.
    • Authenticate the CDN request solely with the short-lived upload authorization returned by the pre-upload endpoint.
    • Validate the returned upload URI and key before constructing the CDN destination.
  7. Add regression tests.

    • Assert that public, subtitle, and CDN requests contain no account cookies.
    • Test malicious absolute sub ...[truncated 148 chars]
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
Findings (36)

Credential Access

High
Category
Privilege Escalation
Confidence
83% confidence
Finding

The README instructs users to place active Bilibili session credentials into a local JSON file, which increases the risk of accidental credential exposure through weak filesystem hygiene, backups, source-control commits, or multi-user environments. In an agent-skill context, requesting raw browser cookie values is especially sensitive because those tokens can enable authenticated publishing actions and higher-privilege API access.

Content

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

方式二:凭据文件

创建 credentials.json:

json
{

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Automatic persistence and reload of Bilibili cookies to .credentials.json creates a real credential-at-rest risk, especially because these tokens can authorize account actions such as uploading, editing, or scheduling videos. Even with 0600 permissions, storing browser-derived session tokens on disk broadens exposure to local compromise, accidental inclusion in archives, workspace syncing, or agent-accessible file reads.

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
99% confidence
Finding

This code does not match the declared operational purpose of the skill. The description promises a unified Bilibili toolkit with multiple media-related capabilities and official Bilibili API usage. Instead, the code is purely a local release helper for maintainers: it computes a semantic version bump, rewrites the version field in skill.json, checks for the clawhub CLI, and publishes the project package. These are unrelated developer workflow functions, not Bilibili features. Although the script mentions 'publish', it is publishing the skill artifact to clawhub, not publishing videos to Bilibili. Therefore this chunk materially differs from the declared purpose and shows undeclared package-management behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code shown is limited to read-only monitoring of Bilibili hot/trending/ranking content via HTTP GET requests. It does not implement downloading videos, playing/watching videos, downloading subtitles, or publishing videos. While the declared description may describe the broader skill, this specific supplied code chunk does not accurately represent those broader capabilities and instead only covers one subset: hot/trending monitoring. The use of optional authentication is present only for authenticated requests generally, not evidence of publishing behavior in this chunk. No suspicious undeclared behavior beyond monitoring is visible.

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 · skill.md (reported line 158)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 · skill.md (reported line 177)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
95% confidence
Finding

The requirement pins aiohttp to 3.10.11, and the provided advisory set indicates multiple known vulnerabilities affecting that version, including cookie scope handling and CRLF/header construction issues. In this skill, aiohttp is relevant because the toolkit performs authenticated network operations against Bilibili APIs; handling session cookies and remote HTTP responses increases the practical risk if a vulnerable client library is used.

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
88% confidence
Finding

The file pins lxml to 5.3.0, which is reported as affected by XXE-related parser weaknesses in default parser configurations. This skill includes HTML/XML parsing libraries and interacts with external content, so if any XML parsing features are used on untrusted input, an attacker could potentially trigger file disclosure, SSRF, or parser abuse through crafted XML.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
91% confidence
Finding

The manifest explicitly supports optional persistence of live Bilibili session cookies to a local .credentials.json file, which increases the attack surface for credential theft from local compromise, backups, logs, or accidental file exposure. These are replayable session credentials for an authenticated account, so disclosure can enable account misuse without needing the user's password.

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
92% confidence
Finding

The storage description confirms the skill can auto-save and auto-load replayable session cookies from .credentials.json, creating a standing secret on disk that may be reused by other local processes or recovered after the original session. Auto-loading persisted credentials also raises the chance of unintended authenticated actions if a later invocation occurs in the same environment.

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
84% confidence
Finding

The code defines a default on-disk credential file in the project tree, which creates a persistent storage location for session cookies and CSRF tokens. Although the implementation adds meaningful protections (permission checks, 0600 mode, stale-file rejection), persisted bearer-style credentials still increase exposure if the host, workspace, backups, or repository directory are compromised or accidentally shared.

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

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.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The constructor docstring states that credentials can be auto-saved and loaded from .credentials.json when persist is enabled or the BILIBILI_PERSIST environment variable is set. Persisting authentication cookies to disk is a sensitive operation, but this file provides no user-facing warning, prompt, or disclosure at the point of execution.

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

The pinned requests version 2.32.3 is identified as having known security issues, including .netrc credential leakage via malicious URLs. Because this skill fetches remote resources and may operate with authenticated sessions or user-supplied URLs/content in download and publishing workflows, a vulnerable HTTP client can expose credentials or mishandle attacker-controlled inputs.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The subtitle skill sets the default language preference to 'zh-CN', which imposes a specific locale by default. The file does not indicate that this locale choice is user-selected, optional by default, or justified as a region-specific compliance constraint.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
77% confidence
Finding

The publisher skill description at L281-L286 makes a strong safety claim that mutations will not occur unless dry_run=false and confirm=true. Separately, the filesystem permission note at L391 says credential files are never auto-created and require explicit save_to_file(), which conflicts with earlier manifest text at L053 and L070 describing automatic credential persistence when BILIBILI_PERSIST is enabled. These active documentation claims are internally inconsistent about what the skill will write automatically.

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 "."

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 261)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.