Back to skill

Security audit

哔哩哔哩API服务

Security checks for vulnerabilities and agentic risk

Overview

This Bilibili API skill mostly does what it advertises, but it automatically stores the user's API key in a local plaintext .env file without permission hardening or a clear session-only option.

Review this before installing if the API key has billing, quota, or private-data access. Prefer providing XBY_APIKEY through a secure environment/secret manager, avoid running the skill in a shared or synced project directory, ensure .env is ignored by version control, and rotate the key if it may already have been stored with broad file permissions.

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

Warning
Location
scripts/config.py:45
Finding

API Key Persisted in a Plaintext File Without Restrictive Permissions

Content
View full analysis
bool: """将API key保存到.env文件""" try: env_path = Path(".env") lines = [] if env_path.exists(): lines = env_path.read_text(encoding="utf-8").splitlines() found = False new_lines = [] for line in lines: if line.startswith("XBY_APIKEY="): new_lines.append(f"XBY_APIKEY={api_key}") found = True else: new_lines.append(line) if not found: new_lines.append(f"XBY_APIKEY={api_key}") env_path.write_text("\n".join(new_lines) + "\n", encoding="utf-8") os.environ["XBY_APIKEY"] = api_key return True ``` ### Technical Analysis The function writes the supplied API key directly to `.env` as plaintext. `Path.write_text()` creates or overwrites the file using permissions derived from the process umask, but the code does not explicitly enforce owner-only permissions such as `0600`. If `.env` already exists with permissive permissions, rewriting it does not correct those permissions. If it is newly created under a permissive umask, other local users or processes may be able to read the credential. The secret also remains on disk across sessions until manually removed. The API key is subsequently used as the `XBY-APIKEY` authentication header when communicating with the configured upstream service. Disclosure can therefore allow an attacker to impersonate the affected API client. ### Attack Path 1. A user supplies an API key as required by the skill workflow. 2. `set_api_key()` invokes `save_api_key_to_env()`. 3. The function stores the key in the project working directory as `XBY_APIKEY=<secret>`. 4. The code do ...[truncated 988 chars]
Remediation
View remediation
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (29)

Tp2

High
Category
MCP Tool Poisoning
Confidence
85% confidence
Finding

Mixing characters from multiple Unicode scripts in a single identifier is a common technique to create visually ambiguous tool names.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill description omits that it reads local configuration and persists a user-supplied API key into a .env file, while claiming a narrower Bilibili API purpose. Undisclosed secret storage and local file modification materially expand the skill's behavior and can surprise users into granting or exposing credentials they did not expect to be written locally.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill description omits that it reads local configuration and persists a user-supplied API key into a .env file, while claiming a narrower Bilibili API purpose. Undisclosed secret storage and local file modification materially expand the skill's behavior and can surprise users into granting or exposing credentials they did not expect to be written locally.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/config.py (reported line 13)May include surrounding context.

python
model_config = SettingsConfigDict(
        env_prefix="XBY_GAOKAO_",
        env_file=".env",
        env_file_encoding="utf-8",
        extra="ignore",
    )

Credential Access

High
Category
Privilege Escalation
Confidence
84% confidence
Finding

The code forcibly reads a specific API key directly from .env in model_post_init, bypassing the declared settings abstraction and normal secret-loading controls. This increases secret exposure risk by introducing custom plaintext parsing logic and broadening the set of places and names from which credentials are collected.

Content

Scanner excerpt · scripts/config.py (reported line 31)May include surrounding context.

python
default_year: int = 2025

    def model_post_init(self, __context):
        # 强制从 .env 文件读取 XBY_APIKEY
        env_path = Path(".env")
        if env_path.exists():
            content = env_path.read_text(encoding="utf-8")

Credential Access

High
Category
Privilege Escalation
Confidence
84% confidence
Finding

Opening and reading the .env file directly for secret extraction handles credentials in plaintext and expands the attack surface for leakage through debugging, unexpected file placement, or reuse in shared directories. In this skill context, this is more dangerous because the service only needs an API key for outbound requests, not bespoke credential harvesting logic.

Content

Scanner excerpt · scripts/config.py (reported line 32)May include surrounding context.

python
def model_post_init(self, __context):
        # 强制从 .env 文件读取 XBY_APIKEY
        env_path = Path(".env")
        if env_path.exists():
            content = env_path.read_text(encoding="utf-8")
            for line in content.splitlines():

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/config.py (reported line 39)May include surrounding context.

python
if line.startswith("XBY_APIKEY="):
                    self.api_key = line.split("=", 1)[1].strip()
                    break
        # 如果环境变量有值,覆盖 .env 的值
        env_val = os.getenv("XBY_APIKEY", "")
        if env_val:
            self.api_key = env_val

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

This function is explicitly designed to persist an API key into a .env file, creating a plaintext credential-at-rest issue. If the project directory is shared, backed up, or accidentally committed, the key can be exposed and reused to access the upstream API service, making this more dangerous than a normal read-only config pattern.

Content

Scanner excerpt · scripts/config.py (reported line 48)May include surrounding context.

python
def save_api_key_to_env(api_key: str) -> bool:
    """将API key保存到.env文件"""
    try:
        env_path = Path(".env")
        lines = []
        if env_path.exists():
            lines = env_path.read_text(encoding="utf-8").splitlines()

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill requests or implies access to environment variables, local file read/write, and network capabilities but does not declare an explicit tool scope such as permissions or allowed-tools. This creates an overbroad trust boundary: an agent may use more capabilities than users expect, including persisting secrets and making outbound requests without clear disclosure.

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 the agent to ask the user for an API key and save it locally, but does not clearly warn the user that the credential will be persisted in local configuration. Secret collection without explicit storage disclosure can lead to uninformed consent, credential mishandling, and increased risk if local files are later read, synced, or exposed.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The documentation body describes a Bilibili API skill, but examples and project structure reference a different gaokao/school-search skill. This inconsistency undermines trust in the skill's true function and increases the risk of inappropriate tool use, misrouted data, or accidental disclosure to an unrelated backend.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The workflow example instructs use of a nonexistent and unrelated function search_schools, conflicting with the actual tool list. In an agent setting, contradictory instructions can cause mis-execution, fallback behaviors, or selection of unintended tools, especially when combined with network and file capabilities.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill tells the agent to directly display raw API response data to the user without any filtering or warning. Raw upstream data may contain personal information, identifiers, internal metadata, or unexpected sensitive fields, so blindly relaying it increases privacy leakage risk.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The settings class is configured with the XBY_GAOKAO_ prefix, but the code bypasses that mechanism and manually reads and writes XBY_APIKEY from .env and the environment. This inconsistency can cause operators to misunderstand where secrets are sourced from, leading to misconfiguration, secret sprawl, and accidental exposure of credentials outside the expected namespace.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The module provides functions to persist and mutate an API credential in a local .env file and process environment, which exceeds simple read-only configuration handling and creates a secret-management risk. In the context of a Bilibili content/data API skill, silently storing long-lived credentials on disk is unnecessary for many workflows and increases the chance of accidental disclosure through logs, backups, source control, or shared workspaces.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The save_api_key_to_env function persists a supplied API key to .env without any confirmation, warning, or indication of where the secret will be stored. This can surprise users and result in credentials being left on disk in plaintext, where they may be collected by backups, other local users, or accidental repository commits.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code file sends user-supplied values such as usernames, keywords, and video identifiers to an external API via call_api, but it provides no confirmation prompt, logging, or explicit disclosure that this data is being transmitted off-process. Because the functions handle potentially sensitive lookup targets across multiple endpoints, the absence of any visible warning in the code is a semantic safety gap under the code-file warning criterion.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

本文件整体将技能定义为“哔哩哔哩API服务”,但项目结构部分却标注根目录为 xiaobenyang_gaokao_skill/。这会让维护者和代理误判该技能的真实用途和可用模块来源,属于文档层面的意图偏离。

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The dependency is specified with only a lower bound, so builds may resolve to different versions over time. This weakens supply-chain control and makes it difficult to guarantee that a known-safe release of requests is installed, especially given the package's history of advisories.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
91% confidence
Finding

requests has published security advisories, and because the manifest does not pin an exact version, it is not possible to verify from this file alone whether installation will select an affected release. In an API service, requests is often security-relevant because it handles outbound HTTP and may process attacker-influenced URLs or credentials.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

Using pydantic with a non-exact version allows dependency resolution to drift across environments and deployments. That makes security posture non-deterministic and can silently introduce vulnerable or incompatible releases.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1

Unverifiable Dependency: pydantic has 4 known advisory(ies) (CVE-2021-29510 (Use of "infinity" as an input to datetime and date fields causes infinite loop i); CVE-2024-3772 (Pydantic regular expression denial of service); CVE-2021-29510 (Pydantic is a data validation and settings management using Python type hinting.) +1 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
88% confidence
Finding

pydantic has known advisories, but the unpinned requirement prevents verification that the installed version is safe. Since this package commonly validates untrusted input in service code, unresolved version drift can expose parsing or denial-of-service issues if an affected release is selected.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The pydantic-settings dependency is not pinned to a specific release, so future installations may consume an unexpected version. This creates a supply-chain hygiene issue and complicates assurance that deployed environments are using a non-vulnerable build.

Content

Scanner excerpt · requirements.txt (reported line 3)May include surrounding context.

text
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1

Unverifiable Dependency: pydantic-settings has 1 known advisory(ies) (CVE-2026-58203 (pydantic-settings: NestedSecretsSettingsSource follows symlinks outside secrets_)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
86% confidence
Finding

The manifest does not pin pydantic-settings, so the deployed version may vary and could include an affected release associated with published advisories. In a service that may load configuration or secrets from the environment/filesystem, that uncertainty increases supply-chain and configuration-handling risk.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

python-dotenv is allowed to float to any version above the minimum, which reduces reproducibility and can introduce newly disclosed vulnerable versions into fresh installs. This is a common but real dependency management weakness.

Content

Scanner excerpt · requirements.txt (reported line 4)May include surrounding context.

text
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1

Static analysis

No suspicious patterns detected.