Back to skill

Security audit

学术文献检索与引用工具

Security checks for vulnerabilities and agentic risk

Overview

This skill appears to be a DBLP literature helper, but it under-discloses sensitive credential storage and third-party data handling that users should review before installing.

Install only if you are comfortable giving a XiaoBenYang API key to this skill, having it stored in a plaintext .env file in the working directory, and sending searches, citation selections, statistics inputs, and export paths to the XiaoBenYang MCP service. Prefer a revised version that uses secure secret storage, clearly documents the upstream service, avoids sending local-only data such as export paths, and removes unrelated gaokao references.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/config.py:45
Finding

API Key Persisted in Plaintext in an Uncontrolled Working-Directory File

Content
View full analysis

Vulnerability Details

File Location: scripts/config.py:45-78; mandated by SKILL.md:17-18, 34
Vulnerability Type: Plaintext credential storage and unsafe configuration-file handling
Risk Level: Medium

Vulnerable Code

python
def save_api_key_to_env(api_key: str) -> bool:
    """Save the API key to the .env file."""
    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
    except Exception as e:
        print(f"Failed to save API key: {e}")
        return False


def set_api_key(api_key: str) -> bool:
    """Set the API key and persist it to .env."""
    if not api_key or not api_key.strip():
        return False
    api_key = api_key.strip()
    if not save_api_key_to_env(api_key):
        return False
    settings.api_key = api_key
    return True

The corresponding Skill instructions require this behavior:

markdown
- On first use, if `.env` does not contain `XBY_APIKEY`, the user must be asked for the API key.
- After receiving the key, call `scripts.config.set_api_key(api_key)` to save it.

Technical Analysis

The Skill persistently writes a user-provided API credential in plaintext to Path(".env"), which resolves relative to the process's current working directory rather than a dedicated Skill configuration directory.

The implementation does not:

  • Apply restrictive permissions such as mode 0600.
  • Check whether .env is a symbolic link. ...[truncated 1898 chars]
Remediation
View remediation

Remediation Suggestions

  1. Do not persist credentials by default. Prefer a session-only environment variable or an operating-system credential manager.
  2. If persistence is explicitly requested by the user, use a dedicated per-user configuration directory rather than the current working directory.
  3. Create the credential file with restrictive permissions such as 0600, and verify those permissions whenever it is loaded.
  4. Reject symbolic links and non-regular files before reading or writing the credential file.
  5. Update the file atomically using a securely created temporary file in the same directory, then replace the destination.
  6. Warn users never to commit the credential file and provide an appropriate .gitignore entry.
  7. Avoid placing the key in the process environment unless required, because child processes may inherit it.
  8. Provide key revocation and rotation guidance in the Skill documentation.

other

Warning
Location
scripts/call_api.py:53
Finding

Unnecessary Disclosure of User Data and Local Filesystem Paths to a Third-Party Service

Content
View full analysis

Vulnerability Details

File Location: scripts/call_api.py:53-76; affected wrappers in scripts/tools.py:185-200, 203-224, 227-251
Vulnerability Type: Excessive third-party data disclosure and violation of least-data principles
Risk Level: Medium

Vulnerable Code

The generic request client sends every supplied parameter and the API credential to the fixed third-party endpoint:

python
def call_tool(
    self,
    mcp_id: str,
    tool_name: str,
    params: dict[str, Any],
) -> HttpResult:
    """Call a XiaoBenYang MCP tool."""
    url = f"{settings.base_url}/api"
    mcp_id = mcp_id or settings.mcp_id

    api_key = get_api_key()
    if not api_key:
        raise UpstreamError("API key is not configured; call set_api_key() first")
    
    headers = {
        "XBY-APIKEY": api_key,
        "func": tool_name,
        "mcpid": mcp_id,
        "Content-Type": "application/json",
    }

    t0 = time.time()
    try:
        resp = self._session.post(
            url=url,
            headers=headers,
            data=json.dumps(params),
            timeout=settings.timeout_seconds,
        )
        resp.raise_for_status()

The destination is configured as:

python
base_url: str = "https://mcp.xiaobenyang.com"

Even operations that can be performed locally transmit their complete input to that service:

python
def calculate_statistics(
    results: null
) -> Dict[str, Any]:
    arguments = {
        "results": results
    }
    
    return call_api("1777419064649731", "calculate_statistics", arguments)

The export wrapper transmits an absolute local path:

python
def export_bibtex(
    path: str
) -> Dict[str, Any]:
    arguments = {
        "path": path
    }
    
    return call_api("1777419064649731", "export_bibtex", arguments)

The remote service also receives bibliography identifiers and user-selected citation keys:

python
def add_bibtex_entry(
    dblp_key: str,
    citation_key: str
) -> Dict[str, Any]:
 
...[truncated 3162 chars]
Remediation
View remediation

Remediation Suggestions

  1. Implement calculate_statistics entirely locally; no network request is needed for aggregate counts.
  2. Maintain the BibTeX collection locally in process memory or in a user-approved local file.
  3. Implement export_bibtex as a validated local file write. Never send the user's absolute path to a remote service.
  4. If BibTeX content must be retrieved remotely, send only the DBLP key, return the content, and perform citation-key replacement and export locally.
  5. Apply field-level data minimization to every request and omit parameters whose values are None.
  6. Clearly disclose that searches are processed by XiaoBenYang rather than directly by DBLP.
  7. Obtain explicit user consent before sending user-provided datasets or potentially identifying values to a third party.
  8. Document the upstream service's retention, logging, and privacy behavior.
  9. Validate export destinations locally, restrict writes to user-approved locations, reject symbolic links where appropriate, and use atomic file creation.
  10. Align the documented behavior with the implementation so users are not led to believe a remote call directly writes a local file.
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
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (27)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill claims to be for DBLP access, but it also collects and persists API credentials locally and references naming consistent with an unrelated 'gaokao' service. That combination strongly suggests repurposed or misleading packaging, increasing the risk of credential capture, confused-deputy behavior, and users sending secrets to an unexpected backend.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill claims to be for DBLP access, but it also collects and persists API credentials locally and references naming consistent with an unrelated 'gaokao' service. That combination strongly suggests repurposed or misleading packaging, increasing the risk of credential capture, confused-deputy behavior, and users sending secrets to an unexpected backend.

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

The custom post-init logic explicitly reads a specific API key from .env, bypassing normal settings abstraction and introducing bespoke credential access behavior. In the context of a literature search tool, this is more dangerous because it adds secret-harvesting capability unrelated to core functionality and makes credential handling less transparent.

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

This line opens and reads the local .env file to obtain credentials, creating a direct credential access path in application code. Such file-based secret scraping is broader than necessary for the declared purpose and increases the chance of accidental exposure, misuse, or propagation of secrets.

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

This function is dedicated to saving an API key into a local .env file, establishing plaintext credential storage and persistence. If exploited through misuse, logs, repo leakage, local compromise, or later packaging of the workspace, the credential can be stolen and abused against the external service.

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

The skill exposes capabilities consistent with environment access, file read/write, and network operations but does not declare any explicit tool scope or permissions boundary. In an agent setting, this weakens least-privilege controls and makes it harder for users or the platform to understand and constrain what the skill can actually do.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
80% confidence
Finding

The skill name and all operational instructions are presented exclusively in Chinese, which effectively imposes a language/locale constraint on use. There is no indication that users may choose another language, nor is there a documented justification that this is a region-specific or compliance-driven skill.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The instructions tell the model to ask the user for an API key during normal chat interaction and persist it locally. Collecting secrets through conversational flow and storing them in local config/.env increases the risk of accidental disclosure, improper retention, and use of credentials for a service that may not match the stated DBLP purpose.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

L026 明确写明“代码只负责调用API”,给人的意图是工具层仅进行远程查询调用;但同一文件随后要求调用 scripts.config.set_api_key(key) 保存密钥,并提供 export_bibtex 将条目保存到指定路径、创建目录并清空集合。这不是简单的遗漏,而是对工具副作用范围的主动性错误描述,容易误导使用者对代码行为的理解。

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The documentation mixes academic literature behavior with gaokao school-search examples and project names, indicating copy-paste inconsistency or hidden multi-purpose behavior. In security terms, inconsistent instructions make operator review unreliable and can conceal functionality outside the user-expected scope.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill allows exporting BibTeX to an arbitrary absolute path and notes that parent directories may be created, but provides no safety guidance or path restrictions. In an agent environment, this can enable overwriting files, planting artifacts in sensitive locations, or causing unintended filesystem changes if the model is tricked into using attacker-chosen paths.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code contains natural-language docstrings and error/messages exclusively in Chinese, such as the class and function docstrings and the API-key error text. The policy only permits a fixed language when the skill offers user opt-in or clearly documents a justified locale constraint, which is not present in this file.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill includes functionality to persist, mutate, and expose an API credential through helper functions, which exceeds the stated DBLP literature search/citation purpose. This increases the attack surface by enabling local secret handling and state mutation that could be abused by other code paths or unintentionally disclose credentials.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Writing API keys into a local .env file creates plaintext secret storage on disk, which is unnecessary for a read/search/citation tool and can lead to credential disclosure through filesystem access, backups, source packaging, or accidental commits. The behavior is especially risky because it silently modifies local configuration state.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The code writes credentials to .env without any visible warning, consent flow, or disclosure to the user. Silent persistence of secrets is dangerous because users may assume the key is ephemeral while it remains stored in plaintext and available to other local processes or future sessions.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency uses a lower-bound specifier (requests>=2.31.0) rather than pinning to an exact version, which makes builds non-reproducible and can result in different packages being installed over time. In a tool that performs network access to external literature services, an unexpected upstream package change or vulnerable transitive resolution can introduce security or reliability regressions.

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

The manifest includes requests without an exact version while the package has multiple known advisories, so auditors cannot determine from this file whether the deployed version is affected. In a networked literature-retrieval skill, this uncertainty matters because requests handles outbound HTTP(S) communication and may expose credential, redirect, or TLS-related weaknesses depending on the resolved version.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

pydantic>=2.7.0 is not version-pinned, so deployments may resolve to different future releases with unknown security properties. Although this is a supply-chain hygiene issue rather than an immediate exploit, it weakens reproducibility and makes it harder to verify whether a given deployment is affected by known advisories.

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

Because pydantic is not pinned and has known advisories, the file does not provide enough assurance that installed versions are free from those issues. This is primarily a dependency governance weakness, but it can affect input validation and parsing behavior in ways that may enable denial of service or unsafe processing if a vulnerable release is resolved.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
93% confidence
Finding

pydantic-settings>=2.2.0 allows installation of any later version, including versions that may later introduce vulnerabilities or breaking behavior. Because this package commonly loads configuration and secrets, weak version control increases supply-chain risk even if no exploit is shown in this file alone.

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

pydantic-settings is referenced without a fixed version despite known advisories, leaving uncertainty about whether secret and configuration loading behavior is secure in deployed environments. Given that settings loaders may read files and environment-derived secrets, unverifiable versions create avoidable supply-chain and configuration-handling risk.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

python-dotenv>=1.0.1 is unpinned, so the environment-loading component may vary across installs and could unexpectedly include insecure behavior from future releases. Since dotenv libraries often influence secret handling and local configuration, reproducibility gaps here are more sensitive than in a purely cosmetic dependency.

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

Unverifiable Dependency: python-dotenv has 2 known advisory(ies) (CVE-2026-28684 (python-dotenv: Symlink following in set_key allows arbitrary file overwrite via ); CVE-2026-28684 (python-dotenv reads key-value pairs from a .env file and can set them as environ)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
87% confidence
Finding

python-dotenv has known advisories, but the unpinned dependency prevents determining whether the installed version is affected. Since dotenv tooling can read and write environment files and influence secrets handling, version ambiguity increases the chance of deploying a release with file-handling or overwrite weaknesses.

Content

No source excerpt is available for this finding.