Back to skill

Security audit

bilibili summary skill

Security checks for vulnerabilities and agentic risk

Overview

The skill’s Bilibili subtitle workflow is mostly coherent, but it handles live account cookies in ways that need careful review before installation.

Review this skill before installing. Use it only if you are comfortable creating and storing Bilibili session cookies locally; keep cookie.txt out of shared folders and repositories, restrict its permissions, and consider using a separate low-risk Bilibili account. Avoid automatic use on incidental links, and prefer a fixed reviewed version with pinned dependencies.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/fetch_subtitle.py:139
Finding

Authentication Cookies Sent to Unvalidated Subtitle URLs

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/cookie_login.py:156
Finding

Sensitive Session Cookies Stored Without Restrictive File Permissions

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
SKILL.md:14
Finding

Unpinned Executable Dependencies and Installer Commands

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (23)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

声明描述的是一个覆盖登录、字幕提取、摘要和时间定位的完整 B 站视频理解 skill;但当前代码片段只包含 cookie_login.py,功能限于扫码登录并保存 Cookie。已实现的登录能力与声明中的第(1)点一致,但其余核心能力均未出现在代码中。因此,代码实际行为明显窄于声明的主要用途,构成描述与行为不匹配。未发现超出声明范围的可疑未声明能力;问题在于严重过度声明。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

代码与描述部分重合:确实支持 B 站链接/BVID 输入、优先 AI 字幕并回退 CC 字幕、使用 Cookie 提升获取能力。但描述中的多个核心能力在代码中完全不存在。首先,没有扫码登录、浏览器交互、二维码生成或 Cookie 获取流程,只是读取本地 cookie.txt。其次,没有任何摘要算法、LLM 调用或文本总结逻辑。再次,也没有检索字幕内容并返回对应时间段的问答/定位功能,虽然会生成带时间戳的 srt/vtt,但并未实现查询定位。整体上,代码的实际用途是“字幕抓取与导出脚本”,明显窄于声明的“完整内容理解工作流”,因此属于描述与行为不一致。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

声明描述的是一个面向 B 站视频内容理解的完整多步骤技能,而提供的代码片段只是其中很小的一部分:在已有 SRT 文件中搜索关键词并返回时间戳。这与声明中的主要能力和主要用途存在实质性差异。代码确实部分支持“从字幕中定位时间段”这一子能力,但前提是用户已经有本地 SRT 文件;它没有任何 B 站相关网络访问、身份登录、字幕抓取、AI/CC 回退、摘要生成或链接/BVID 处理逻辑。因此该描述不能准确代表此代码块的实际行为,应判定为 mismatch。

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The trigger conditions are explicitly broad: the skill says it must activate for many generic Bilibili-related phrases and even for a casual mention of a bilibili link. Because this skill can lead to login guidance, cookie collection, network access, and local file writes, over-triggering increases the chance of invoking sensitive workflows without clear user intent. In context, that makes accidental credential-handling and unnecessary external requests more likely.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
91% confidence
Finding

The README instructs users to run npx skills add BAIKEMARK/bilibili-summary-skill without pinning a specific version of the skills package or the installed skill artifact. Unpinned package execution can cause users to fetch and run a newer or compromised release than the one reviewed, creating a supply-chain risk that is especially relevant for an agent skill that handles login flows and local cookie files.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill directs the agent to perform file reads/writes and network-backed subtitle retrieval, but it declares no explicit tool or permission scope. That creates an authorization ambiguity where a host may permit broader actions than users expect, especially because the workflow includes writing cookie.txt and subtitle files locally. In a skill ecosystem, undeclared capabilities reduce transparency and weaken least-privilege controls.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill instructs users to obtain and store sensitive Bilibili session cookies locally, including manual extraction of SESSDATA and bili_jct, but it does not provide a strong warning about credential sensitivity, storage risks, or scope of access. These cookies may grant account access and can be abused if exposed through logs, shared directories, backups, or other tools. The context makes this more dangerous because the workflow normalizes credential collection as a routine step for subtitle access.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script saves live Bilibili authentication material (SESSDATA and bili_jct) in plaintext on disk without strong warnings, permission hardening, or any storage protection. These cookies can often be reused to access the user's account session, so any local compromise, accidental sharing, backup sync, or multi-user system exposure could lead to account takeover or unauthorized actions.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/fetch_subtitle.py (reported line 140)May include surrounding context.

python
"""尝试获取 AI 自动生成的字幕。"""
    # 方法1: wbi/v2 接口
    try:
        url = f"https://api.bilibili.com/x/player/wbi/v2?bvid={bvid}&cid={cid}"
        data = requests.get(url, headers=headers, timeout=10).json()
        subtitles = data.get("data", {}).get("subtitle", {}).get("subtitles", [])
        for sub in subtitles:

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/fetch_subtitle.py (reported line 158)May include surrounding context.

python
"""尝试获取 AI 自动生成的字幕。"""
    # 方法1: wbi/v2 接口
    try:
        url = f"https://api.bilibili.com/x/player/wbi/v2?bvid={bvid}&cid={cid}"
        data = requests.get(url, headers=headers, timeout=10).json()
        subtitles = data.get("data", {}).get("subtitle", {}).get("subtitles", [])
        for sub in subtitles:

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/fetch_subtitle.py (reported line 188)May include surrounding context.

python
"""尝试获取 AI 自动生成的字幕。"""
    # 方法1: wbi/v2 接口
    try:
        url = f"https://api.bilibili.com/x/player/wbi/v2?bvid={bvid}&cid={cid}"
        data = requests.get(url, headers=headers, timeout=10).json()
        subtitles = data.get("data", {}).get("subtitle", {}).get("subtitles", [])
        for sub in subtitles:

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/fetch_subtitle.py (reported line 209)May include surrounding context.

python
"""尝试获取 AI 自动生成的字幕。"""
    # 方法1: wbi/v2 接口
    try:
        url = f"https://api.bilibili.com/x/player/wbi/v2?bvid={bvid}&cid={cid}"
        data = requests.get(url, headers=headers, timeout=10).json()
        subtitles = data.get("data", {}).get("subtitle", {}).get("subtitles", [])
        for sub in subtitles:

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/fetch_subtitle.py (reported line 225)May include surrounding context.

python
"""尝试获取 AI 自动生成的字幕。"""
    # 方法1: wbi/v2 接口
    try:
        url = f"https://api.bilibili.com/x/player/wbi/v2?bvid={bvid}&cid={cid}"
        data = requests.get(url, headers=headers, timeout=10).json()
        subtitles = data.get("data", {}).get("subtitle", {}).get("subtitles", [])
        for sub in subtitles:

Tainted flow: 'url' from requests.get (line 209, network input) → requests.get (network output)

Medium
Category
Data Flow
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.

Content

Scanner excerpt · scripts/fetch_subtitle.py (reported line 141)May include surrounding context.

python
# 方法1: wbi/v2 接口
    try:
        url = f"https://api.bilibili.com/x/player/wbi/v2?bvid={bvid}&cid={cid}"
        data = requests.get(url, headers=headers, timeout=10).json()
        subtitles = data.get("data", {}).get("subtitle", {}).get("subtitles", [])
        for sub in subtitles:
            if sub.get("type") == 1:

Tainted flow: 'sub_url' from requests.get (line 229, network input) → requests.get (network output)

Medium
Category
Data Flow
Confidence
88% confidence
Finding

Here the code follows subtitle_url returned by a remote API and reuses authenticated headers, including the user's Cookie, for the second request without validating the destination. If Bilibili or a man-in-the-middle/compromised upstream returned an attacker-controlled URL, the script could leak the user's Bilibili cookie to another host or be used for limited SSRF-style outbound requests.

Content

Scanner excerpt · scripts/fetch_subtitle.py (reported line 150)May include surrounding context.

python
continue
                if sub_url.startswith("//"):
                    sub_url = "https:" + sub_url
                body = requests.get(sub_url, headers=headers, timeout=10).json()
                if "body" in body:
                    return body["body"]
    except Exception:

Tainted flow: 'url' from requests.get (line 209, network input) → requests.get (network output)

Medium
Category
Data Flow
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.

Content

Scanner excerpt · scripts/fetch_subtitle.py (reported line 159)May include surrounding context.

python
# 方法2: web-interface/view 接口
    try:
        url = f"https://api.bilibili.com/x/web-interface/view?bvid={bvid}"
        resp = requests.get(url, headers=headers, timeout=10).json()
        if resp.get("code") == 0:
            subs = resp.get("data", {}).get("subtitle", {}).get("subtitles", [])
            if subs:

Tainted flow: 'sub_url' from requests.get (line 229, network input) → requests.get (network output)

Medium
Category
Data Flow
Confidence
88% confidence
Finding

This line makes a second-stage request to a URL obtained from remote response data, again with the same headers that may contain authentication cookies. That creates a real risk of credential leakage or server-side fetching of unexpected endpoints if the returned subtitle URL is malicious or outside the expected Bilibili domain set.

Content

Scanner excerpt · scripts/fetch_subtitle.py (reported line 167)May include surrounding context.

python
if sub_url.startswith("//"):
                    sub_url = "https:" + sub_url
                if sub_url:
                    body = requests.get(sub_url, headers=headers, timeout=10).json()
                    if "body" in body:
                        return body["body"]
    except Exception:

Tainted flow: 'url' from requests.get (line 209, network input) → requests.get (network output)

Medium
Category
Data Flow
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.

Content

Scanner excerpt · scripts/fetch_subtitle.py (reported line 210)May include surrounding context.

python
if not body:
            print("🔍 正在查找 CC 字幕...")
            url = f"https://api.bilibili.com/x/player/v2?bvid={bvid}&cid={cid}"
            info = requests.get(url, headers=headers, timeout=10).json()
            subs = info.get("data", {}).get("subtitle", {}).get("subtitles", [])

            if not subs:

Tainted flow: 'fb_url' from requests.get (line 225, network input) → requests.get (network output)

Medium
Category
Data Flow
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.

Content

Scanner excerpt · scripts/fetch_subtitle.py (reported line 226)May include surrounding context.

python
if not sub_url:
                try:
                    fb_url = f"https://api.bilibili.com/x/player/wbi/v2?bvid={bvid}&cid={cid}"
                    fb = requests.get(fb_url, headers=headers, timeout=10).json()
                    fb_subs = fb.get("data", {}).get("subtitle", {}).get("subtitles", [])
                    if fb_subs:
                        sub_url = fb_subs[0].get("subtitle_url") or fb_subs[0].get("subtitle_url_v2", "")

Tainted flow: 'sub_url' from requests.get (line 229, network input) → requests.get (network output)

Medium
Category
Data Flow
Confidence
90% confidence
Finding

This is the clearest instance of the issue: a subtitle URL from remote API data is fetched directly with headers that may include the user's Cookie. In the context of a skill that explicitly instructs users to log in and store cookies, this increases risk because credential-bearing requests may be sent to untrusted destinations if response data is ever tampered with.

Content

Scanner excerpt · scripts/fetch_subtitle.py (reported line 240)May include surrounding context.

python
sub_url = "https:" + sub_url

            print("⬇️  正在下载字幕...")
            body = requests.get(sub_url, headers=headers, timeout=10).json().get("body")

        if not body:
            return None, "❌ 获取字幕失败:返回数据为空"

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

Natural-language strings throughout the file, including usage instructions and user-facing prompts, are presented only in Chinese. This can constitute a language policy violation when the skill forces a specific language without giving the user an explicit choice or documenting a justified locale restriction.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

该文件的模块说明、CLI 帮助文本和运行时提示均固定为中文,未提供用户可选的语言或 locale 选项。根据规则,强制特定语言而没有用户 opt-in 属于自然语言层面的策略问题。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code file contains natural-language strings that force a specific language/locale for usage instructions and output. Under the policy, language constraints should offer user choice or be clearly justified; here no opt-in or locale justification is provided.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.