Back to skill

Security audit

Bilibili Video Parser

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly does what it says, but its URL handling can make the agent contact non-Bilibili or internal network addresses despite claiming a narrower network boundary.

Install only if you are comfortable with a local tool that makes outbound network requests and downloads Python dependencies/models. Use trusted Bilibili links, prefer full bilibili.com/video/BV... URLs over short links, run it in a constrained environment if possible, and consider pinning faster-whisper before use.

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

Warning
Location
scripts/transcribe.py:107
Finding
Arbitrary outbound requests through weak short-link validation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/transcribe.py:107-116` **Vulnerability Type**: Server-Side Request Forgery through insufficient URL validation **Risk Level**: Medium ### Vulnerable Code ```python # Short link b23.tv: follow one redirect if "b23.tv" in url: try: req = urllib.request.Request(url, headers={"User-Agent": PC_UA}) with urllib.request.urlopen(req, timeout=10) as resp: final_url = resp.geturl() m = re.search(r'(BV[0-9A-Za-z]{10})', final_url) if m: return m.group(1) except Exception as e: print(f"[WARN] Failed to follow short link: {e}", file=sys.stderr) ``` ### Technical Analysis The condition only checks whether the literal string `b23.tv` occurs anywhere in the user-supplied value. It does not parse the URL or verify that its hostname is actually `b23.tv`. Consequently, inputs such as the following pass the check even though their destination is not Bilibili: ```text http://127.0.0.1:8080/?source=b23.tv http://169.254.169.254/latest/meta-data/?host=b23.tv https://attacker.example/path/b23.tv ``` The complete user-controlled URL is then passed to `urllib.request.urlopen`. The library also follows HTTP redirects by default, and the code validates neither intermediate redirect targets nor the final target before making the requests. This behavior exceeds the documented minimum-privilege network boundary, which states that the Skill accesses Bilibili endpoints and Hugging Face model infrastructure only. ### Attack Path 1. An attacker supplies a URL whose path, query, or user-information component contains `b23.tv`. 2. `extract_bvid` fails to find a directly embedded BVID. 3. The substring condition evaluates to true. 4. The Skill submits a GET request to the attacker-selected destination. 5. The target can redirect the request to another public or internal endpoint. 6. Response timing, errors, and behavioral differences may allow ...[truncated 874 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse the URL with `urllib.parse.urlsplit` or `urllib.parse.urlparse`. 2. Require the `https` scheme. 3. Require an exact normalized hostname match against `b23.tv`, or a narrowly defined and reviewed subdomain allowlist. 4. Reject URLs containing credentials, unexpected ports, malformed hostnames, or ambiguous encodings. 5. Resolve the hostname and reject loopback, private, link-local, multicast, unspecified, and reserved IP addresses using the `ipaddress` module. 6. Disable automatic redirects or use a custom redirect handler that validates every destination before following it. 7. Apply the same validation after DNS resolution and on every redirect to mitigate DNS rebinding. 8. Add tests covering URLs where `b23.tv` appears only in the path, query, fragment, user-information component, or a different hostname. A safe validation pattern should resemble: ```python from urllib.parse import urlsplit parsed = urlsplit(url) if parsed.scheme != "https" or parsed.hostname != "b23.tv": raise ValueError("Only HTTPS b23.tv short links are accepted") ``` This hostname check should be supplemented with resolved-address and redirect validation. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/transcribe.py:185
Finding
Unvalidated API-provided subtitle and audio URLs permit unintended network access<![CDATA[ ## Vulnerability Details **File Location**: `scripts/transcribe.py:185-193`, `scripts/transcribe.py:242-252` **Vulnerability Type**: Unrestricted use of remote-provided URLs **Risk Level**: Medium ### Vulnerable Code Subtitle retrieval trusts a URL returned by the Bilibili API: ```python sub_url = zh_sub.get("subtitle_url", "") if not sub_url: return None # Bilibili subtitle URLs normally begin with // if sub_url.startswith("//"): sub_url = "https:" + sub_url sub_raw = _http_get(sub_url, BILI_HEADERS, max_timeout=15) sub_data = json.loads(sub_raw) ``` Audio retrieval similarly returns and downloads an API-provided URL without validating its destination: ```python # Select the first entry with the highest bitrate return audio_list[0]["baseUrl"] def download_audio(url: str, dest: str) -> None: """Download the audio file to the specified path.""" print(f"[1/3] Download audio -> {dest}") headers = { "User-Agent": PC_UA, "Referer": "https://www.bilibili.com", } if not _http_download(url, dest, headers, max_timeout=300): sys.exit("[ERROR] Audio download failed") ``` ### Technical Analysis The subtitle and audio URLs originate from a remote API response and are treated as trusted destinations. Before requesting them, the code does not validate: - The URL scheme. - The destination hostname. - The resolved IP address. - Redirect targets. - The response content type. - The maximum subtitle or audio response size. Although the expected values are Bilibili CDN URLs, the implementation does not enforce that expectation. If an upstream response is compromised, manipulated, or changes format, the process can be directed to an arbitrary public or internal endpoint. For audio, the downloaded response is subsequently parsed by the media stack used by `faster-whisper`, including PyAV. This expands the risk from unintended network access to processing attacker-controlled malformed media. The requests inc ...[truncated 1676 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Define an explicit allowlist of reviewed Bilibili subtitle and media CDN hostnames. 2. Require HTTPS for every subtitle and audio request. 3. Resolve destinations before connecting and reject private, loopback, link-local, multicast, unspecified, and reserved addresses. 4. Validate every redirect destination rather than relying on automatic redirect handling. 5. Revalidate the resolved address immediately before connection to reduce DNS-rebinding exposure. 6. Reject URLs containing credentials or unexpected ports. 7. Enforce response-size limits: - Use a small maximum for subtitle JSON. - Derive a reasonable audio limit from video duration and expected bitrate. - Stop downloading when the configured limit is exceeded. 8. Verify `Content-Type` and, where practical, file signatures before passing content to PyAV. 9. Store downloads in uniquely created temporary files rather than a predictable filename. 10. Keep PyAV, FFmpeg libraries, and `faster-whisper` dependencies pinned and updated because they process untrusted media. 11. Do not forward sensitive headers, cookies, or authorization data to CDN URLs unless the destination has been validated. ]]>

T08 · Insecure Dependencies

Note
Location
SKILL.md:58
Finding
Unpinned third-party dependency installation creates supply-chain risk<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:58-65`, `README.md:26-29`, `skill.yaml:32-34` **Vulnerability Type**: Unpinned package installation from the active package index **Risk Level**: Low ### Vulnerable Code The Skill instructs the Agent to install the latest package version available from its configured pip index: ```bash python3 -c "import faster_whisper; print('ok')" ``` If the import fails, the instructions require: ```bash pip3 install faster-whisper ``` The manifest likewise declares the dependency without a version constraint or integrity information: ```yaml dependencies: pip: - faster-whisper ``` The README repeats the same unrestricted installation command: ```bash pip install faster-whisper ``` ### Technical Analysis No exact version, lock file, package hash, or reviewed transitive dependency set is provided. Installation therefore depends on whichever package and dependency versions the active pip index resolves at execution time. Python package installation can execute package build logic, and imported runtime dependencies execute with the privileges of the Agent process. An unpinned dependency creates non-reproducible builds and increases exposure to: - A future compromised package release. - Compromised transitive dependencies. - Malicious or incorrectly configured private package indexes. - Dependency-resolution changes that introduce vulnerable versions. The package name is consistent throughout the project, and no suspicious package index or obvious typosquatting name was found. The issue is therefore an unsafe dependency-management practice rather than evidence that the current named package is malicious. ### Attack Path 1. The Agent follows the mandatory environment check in `SKILL.md`. 2. `faster_whisper` is absent from the current Python environment. 3. The Agent executes `pip3 install faster-whisper`. 4. pip resolves the latest permitted package and transitive dependency versions from the e ...[truncated 904 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin `faster-whisper` to a reviewed exact version. 2. Create a lock file that also pins all transitive dependencies. 3. Use hash verification, such as pip requirements with `--require-hashes`. 4. Install from the official Python Package Index or an explicitly documented, trusted internal mirror. 5. Install dependencies in a dedicated virtual environment rather than the Agent's global Python environment. 6. Run installation and transcription with the minimum filesystem and network privileges required. 7. Review and update pinned dependencies through a controlled process with vulnerability scanning. 8. Where supported, use prebuilt, verified wheels and reject unexpected source builds. For example: ```text faster-whisper==<reviewed-version> --hash=sha256:<verified-wheel-hash> ``` The exact version and hash should be selected after reviewing the target platform's official artifact rather than copied from an untrusted source. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (5)

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill requests or instructs use of powerful capabilities (environment access, file read/write, network, and shell/Python execution) but does not declare an explicit machine-readable tool scope such as permissions or allowed-tools. This creates a policy gap: an agent or reviewer cannot reliably enforce least privilege, increasing the chance the skill is executed with broader access than intended.

External Transmission

Medium
Category
Data Exfiltration
Content
def fetch_video_info(bvid: str) -> dict:
    """从B站公开 API 获取视频元数据"""
    api_url = f"https://api.bilibili.com/x/web-interface/view?bvid={bvid}"
    raw = _http_get(api_url, BILI_HEADERS, max_timeout=20)
    data = json.loads(raw)
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
def fetch_video_info(bvid: str) -> dict:
    """从B站公开 API 获取视频元数据"""
    api_url = f"https://api.bilibili.com/x/web-interface/view?bvid={bvid}"
    raw = _http_get(api_url, BILI_HEADERS, max_timeout=20)
    data = json.loads(raw)
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
def fetch_video_info(bvid: str) -> dict:
    """从B站公开 API 获取视频元数据"""
    api_url = f"https://api.bilibili.com/x/web-interface/view?bvid={bvid}"
    raw = _http_get(api_url, BILI_HEADERS, max_timeout=20)
    data = json.loads(raw)
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Natural-Language Policy Violations

Low
Confidence
92% confidence
Finding
This code sets the output document language to `zh-CN`, which enforces a specific locale in the generated report. The file also defaults the transcription language to Chinese elsewhere, and there is no user-facing opt-in or explanation that the HTML report is intended to be Chinese-only.

Static analysis

No suspicious patterns detected.