Back to skill

Security audit

bili-review

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real Bilibili video summarizer, but it can automatically extract and persist browser login cookies with insufficient warning and containment.

Review carefully before installing. Use only if you are comfortable letting the skill read browser login cookies for Bilibili, store them locally as cookies.txt, and send them to Bilibili APIs. Prefer a disposable or low-risk Bilibili account, avoid running it inside shared repositories, and delete any generated cookie file when finished.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • 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
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
Findings (4)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/bili_review.py:204
Finding

Automatic Broad Browser Cookie Extraction and Persistent Session Storage

Content
View full analysis
bool: """用 yt-dlp 的 python 调用 extract_cookies.py 从指定浏览器提取 cookie. 仅提取 B站 相关域名, 不导出其他网站; 保存为 600 权限.""" try: cmd = [find_ytdlp_python(), str(SCRIPTS_DIR / "extract_cookies.py"), browser, str(output)] subprocess.run(cmd, check=True, capture_output=True, text=True, timeout=60) if output.exists() and output.stat().st_size > 0: os.chmod(output, 0o600) return True except (subprocess.CalledProcessError, FileNotFoundError): return False return False ``` ```python # scripts/bili_review.py:204-219 def get_cookie_file() -> Path: """获取有效 cookie 文件; 无则自动从浏览器提取(首次需授权一次).""" if COOKIE_FILE.exists() and validate_login(COOKIE_FILE): return COOKIE_FILE print("未检测到有效登录态, 正在从浏览器提取 cookie ...", file=sys.stderr) for browser in BROWSERS: tmp = Path(tempfile.mkdtemp()) / "cookies.txt" if extract_cookies_from_browser(browser, tmp) and validate_login(tmp): os.chmod(tmp, 0o600) tmp.replace(COOKIE_FILE) print(f"已从 {browser} 提取登录态 -> {COOKIE_FILE}", file=sys.stderr) return COOKIE_FILE raise RuntimeError( "浏览器 cookie 提取失败(弹窗被取消或无B站登录)。" f"请确认浏览器已登录B站后重试: python3 {SCRIPTS_DIR / 'bili_review.py'} login") ``` ```python # scripts/extract_cookies.py:13-29 BILI_DOMAINS = ("bilibili.com", "b23.tv", "biligame.com", "bilibili.tv", "bstar.app", "biligame.net") def main() -> None: if len(sys.argv) != 3: print("用法: extract_cookies ...[truncated 2943 chars]
Remediation
View remediation

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:34
Finding

Indirect Prompt Injection Through Untrusted Subtitles, Comments, and Danmaku

Content
View full analysis
None: info = result['info'] if include_meta: print(f"# 视频: {info['title']}") print(f"# BVID: {info.get('bvid', '')}") print(f"# UP主: {info['author']}") print(f"# 发布时间: {info.get('pubdate', '')}") s = info['stats'] print(f"# 播放: {fmt_num(s['view'])} / 点赞: {fmt_num(s['like'])} / 评论: {fmt_num(s['comment'])}") print(f"# 评论总数(接口返回): {fmt_num(result['total'])}") print() print(f"## 热门评论 TOP {len(result['comments'])}") for i, c in enumerate(result['comments'], 1): date_str = f"[{c['date']}] " if c.get('date') else "" print(f"{i}. {date_str}[点赞 {fmt_num(c['like'])}] {c['author']}: {c['text']}") for j, r in enumerate(c.get('replies', []), 1): r_date_str = f"[{r['date']}] " if r.get('date') else "" print(f" └ 楼中楼{j}. {r_date_str}[点赞 {fmt_num(r['like'])}] {r['author']}: {r['text']}") ``` ```python # scripts/bili_review.py:576-582 sub_req = urllib.request.Request(sub_url, headers={'User-Agent': UA}) with opener.open(sub_req, timeout=12) as resp: sub_json = json.loads(resp.read().decode('utf-8')) body = ...[truncated 3206 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
SKILL.md:17
Finding

Security-Sensitive Dependency Installed Without Version or Integrity Pinning

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/bili_review.py:37
Finding

Credential File Stored in Project Root Without the Documented Ignore Protection

Content
View full analysis
Path: """获取有效 cookie 文件; 无则自动从浏览器提取(首次需授权一次).""" if COOKIE_FILE.exists() and validate_login(COOKIE_FILE): return COOKIE_FILE print("未检测到有效登录态, 正在从浏览器提取 cookie ...", file=sys.stderr) for browser in BROWSERS: tmp = Path(tempfile.mkdtemp()) / "cookies.txt" if extract_cookies_from_browser(browser, tmp) and validate_login(tmp): os.chmod(tmp, 0o600) tmp.replace(COOKIE_FILE) print(f"已从 {browser} 提取登录态 -> {COOKIE_FILE}", file=sys.stderr) return COOKIE_FILE ``` The documentation claims a safeguard that is absent from the audited package: ```markdown # README.md:218-221 ## 🔒 隐私与安全机制 - **安全沙箱隔离**:`cookies.txt` **仅筛选提取 B 站相关域名**,绝不读取或触碰其他网站数据。 - **本地权限保护**:本地 Cookie 保存为系统权限 `600`(仅当前系统用户可读写),已严格配置 `.gitignore`,绝不外泄。 ``` The supplied project contains only `README.md`, `SKILL.md`, and the `scripts/` directory. No `.gitignore` was present in the audited artifact. ### Technical Analysis The application stores a Netscape-format cookie jar directly in the repository root. Although the file is assigned mode `0600`, it remains plaintext data inside a location commonly committed, archived, synchronized, or shared. The README states that `.gitignore` has been strictly configured to exclude the credential file, but that file is absent from the supplied artifact. Therefore, the documented source-control safeguard is not actually present in the reviewe ...[truncated 1226 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (28)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Reading cookies from a local browser and writing them to disk is access to sensitive authentication data, but the skill metadata presents the feature primarily as subtitle/comment retrieval and summary generation. This mismatch is dangerous because users or host agents may approve the skill under a lower-risk mental model while it actually handles credentials.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Reading cookies from a local browser and writing them to disk is access to sensitive authentication data, but the skill metadata presents the feature primarily as subtitle/comment retrieval and summary generation. This mismatch is dangerous because users or host agents may approve the skill under a lower-risk mental model while it actually handles credentials.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The login commands explicitly describe extracting cookies from the browser and saving them locally, yet the document omits an explicit security warning or handling guidance. This is especially dangerous because persisted cookies can often be reused to impersonate the user on the target service if the file is exposed, copied, or read by other tools.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill enumerates many local browsers and invokes a helper to extract cookies automatically, creating a credential-access capability disproportionate to its purpose. In skill context, that makes the finding more serious because a content-summary tool has no obvious need to scan multiple browser profiles for reusable session secrets.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill description and all user-facing documentation are written exclusively in Chinese, and the README presents the tool as producing Chinese-language output without mentioning any option to choose another language. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is clearly documented and justified.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The README instructs users to run a login flow that automatically extracts browser cookies and emphasizes convenience ('免输密码') without a prominent, up-front warning about the sensitivity of those credentials. In a skill context, browser cookie extraction is inherently high-risk because session tokens can grant account access if mishandled, and the README's reassuring language may cause users to underestimate that risk.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill declares shell, file-read, and network-capable behavior but does not define any explicit tool scope or permission boundaries. In this context, the workflow includes executing local Python commands, invoking yt-dlp, and accessing locally stored browser-derived authentication state, so the absence of least-privilege restrictions materially increases the chance of overbroad execution or unintended data access.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The trigger phrases include broad everyday expressions such as '看评论区' and '视频讲了什么', which can cause the skill to activate unintentionally in unrelated conversations. Because this skill can launch shell commands, perform network retrieval, and potentially interact with stored authentication state, accidental invocation increases operational and privacy risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation states that official AI subtitles are fetched using local cookies, but it does not provide a clear warning that these cookies are sensitive authentication credentials. In a skill that interacts with browser-derived login state, missing privacy and credential-risk disclosures can lead users to unknowingly expose account access or leave persistent secrets on disk.

Content

No source excerpt is available for this finding.

Whitespace Padding

Medium
Category
Prompt Injection
Confidence
70% confidence
Finding

Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Content

Scanner excerpt · SKILL.md (reported line 70)May include surrounding context.

md
根据视频核心诉求,直接选用对应的总结分析骨架:

| 视频类型               | 核心关注点                         | 总结方法                 | 交付的核心价值                                                                                                         |
| ---------------------- | ---------------------------------- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
| **测评 / 避坑 / 选型** | 到底买不买、翻车没、有什么暗病     | **红黑榜对比法**         | 🟢 **红榜**(宣称亮点)<br/>🔴 **黑榜**(弹幕/评论扒出的槽点)<br/>⚖️ **选型建议与民间平替**                             |
| **教程 / 实操 / 配置** | 怎么做最快、别让我踩坑、跳过弯路   | **步骤清单(做减法)**   | 🛠️ **准备工作与依赖**<br/>📋 **核心步骤(直接抄作业)**<br/>✂️ **做减法与避坑(跳过冗余步骤)**                          |

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code and description explicitly implement browser login-state extraction and long-term local persistence, which is materially more sensitive than the advertised function of summarizing subtitles, danmaku, and comments. This mismatch increases the chance of over-collection of secrets and makes the skill dangerous in environments where users would not expect credential handling.

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/bili_review.py (reported line 59)May include surrounding context.

python
if m_aid:
        aid = m_aid.group(1)
        try:
            data = http_get_json(f"https://api.bilibili.com/x/web-interface/view?aid={aid}")
            if data.get('code') == 0 and data.get('data', {}).get('bvid'):
                return data['data']['bvid']
        except Exception:

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/bili_review.py (reported line 103)May include surrounding context.

python
if m_aid:
        aid = m_aid.group(1)
        try:
            data = http_get_json(f"https://api.bilibili.com/x/web-interface/view?aid={aid}")
            if data.get('code') == 0 and data.get('data', {}).get('bvid'):
                return data['data']['bvid']
        except Exception:

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/bili_review.py (reported line 285)May include surrounding context.

python
if m_aid:
        aid = m_aid.group(1)
        try:
            data = http_get_json(f"https://api.bilibili.com/x/web-interface/view?aid={aid}")
            if data.get('code') == 0 and data.get('data', {}).get('bvid'):
                return data['data']['bvid']
        except Exception:

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/bili_review.py (reported line 381)May include surrounding context.

python
if m_aid:
        aid = m_aid.group(1)
        try:
            data = http_get_json(f"https://api.bilibili.com/x/web-interface/view?aid={aid}")
            if data.get('code') == 0 and data.get('data', {}).get('bvid'):
                return data['data']['bvid']
        except Exception:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/bili_review.py (reported line 154)May include surrounding context.

python
# 3. macOS Homebrew 常见路径探测
    candidates = []
    try:
        prefix = subprocess.run(['brew', '--prefix', 'yt-dlp'], capture_output=True,
                                text=True, timeout=5)
        if prefix.returncode == 0:
            candidates.append(str(Path(prefix.stdout.strip()) / "libexec" / "bin" / "python3"))

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
88% confidence
Finding

The skill automatically extracts browser cookies via a subprocess and writes them to a persistent local file, which exposes authenticated session material far beyond simple video summarization. In context, this is especially risky because the capability is broad, probes multiple browsers, and can silently harvest reusable Bilibili login state that could later be abused if the file or helper script is compromised.

Content

Scanner excerpt · scripts/bili_review.py (reported line 173)May include surrounding context.

python
仅提取 B站 相关域名, 不导出其他网站; 保存为 600 权限."""
    try:
        cmd = [find_ytdlp_python(), str(SCRIPTS_DIR / "extract_cookies.py"), browser, str(output)]
        subprocess.run(cmd, check=True, capture_output=True, text=True, timeout=60)
        if output.exists() and output.stat().st_size > 0:
            os.chmod(output, 0o600)
            return True

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

This request sends locally extracted cookies to Bilibili to validate login state, meaning authenticated session material is transmitted and operationalized by the skill. In context, this is risky because it confirms and reuses harvested browser credentials as part of an automation workflow unrelated to the minimally necessary public-data features.

Content

Scanner excerpt · scripts/bili_review.py (reported line 195)May include surrounding context.

python
return False
    opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
    try:
        req = urllib.request.Request("https://api.bilibili.com/x/web-interface/nav",
                                     headers={'User-Agent': UA, 'Referer': 'https://www.bilibili.com/'})
        with opener.open(req, timeout=15) as resp:
            data = json.loads(resp.read().decode('utf-8'))

External Transmission

Medium
Category
Data Exfiltration
Confidence
83% confidence
Finding

The skill uses stored cookies to query the logged-in username, further extending its use of extracted authentication data beyond a one-time technical check. This increases privacy sensitivity by linking local session material to account identity and normalizing account introspection within a summarization tool.

Content

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

python
cj = http.cookiejar.MozillaCookieJar(str(cookie_file))
    cj.load(ignore_discard=True, ignore_expires=True)
    opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
    req = urllib.request.Request("https://api.bilibili.com/x/web-interface/nav",
                                 headers={'User-Agent': UA})
    data = json.loads(opener.open(req, timeout=15).read().decode())
    return data.get('data', {}).get('uname', '')

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

Standalone login and status account-management commands extend the skill from content retrieval into credential lifecycle management. That broader capability increases attack surface and normalizes storing and reusing authentication artifacts for a task that users may assume is mostly public-data scraping.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

This request may include browser-derived cookies when calling the Bilibili nav endpoint to retrieve WBI signing keys, coupling sensitive local authentication state to ordinary metadata/signing operations. In this skill context, the dangerous part is not the Bilibili request itself but the unnecessary dependency on harvested login state for routine automation.

Content

Scanner excerpt · scripts/bili_review.py (reported line 500)May include surrounding context.

python
def get_wbi_keys(cookie_file: Path = None) -> tuple:
    """获取 WBI 签名所必需的 img_key 和 sub_key."""
    opener = get_cookie_opener(cookie_file)
    req = urllib.request.Request("https://api.bilibili.com/x/web-interface/nav",
                                 headers={'User-Agent': UA})
    try:
        with opener.open(req, timeout=10) as resp:

External Transmission

Medium
Category
Data Exfiltration
Confidence
81% confidence
Finding

The subtitle-fetch path may send authenticated requests using locally harvested cookies to access subtitle metadata and content, operationalizing persistent browser-derived session state. Because the skill's public-facing purpose is content summarization, this authenticated transmission materially increases privacy and credential-handling risk compared with a public-only design.

Content

Scanner excerpt · scripts/bili_review.py (reported line 548)May include surrounding context.

python
img_key, sub_key = get_wbi_keys(cookie_file)
    signed_params = sign_wbi_params({'aid': aid, 'cid': cid, 'bvid': bvid}, img_key, sub_key)
    query_str = urllib.parse.urlencode(signed_params)
    url = f"https://api.bilibili.com/x/player/wbi/v2?{query_str}"

    opener = get_cookie_opener(cookie_file)
    req = urllib.request.Request(url, headers={

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/bili_review.py (reported line 671)May include surrounding context.

python
f"https://www.bilibili.com/video/{bvid}",
        ])
        try:
            subprocess.run(cmd, cwd=temp_dir, check=True, capture_output=True, text=True)
        except subprocess.CalledProcessError as e:
            err = (e.stderr or "").lower()
            if "412" in err or "rate" in err: