Back to skill

Security audit

基金知识查询服务

Security checks for vulnerabilities and agentic risk

Overview

This skill appears to be an API-backed fund lookup tool, but it stores an API key in a local plaintext file and has mismatched, broken tool definitions that warrant review.

Review this skill before installing. Only provide an API key if you trust the publisher and are comfortable with the key being written to a local .env file; avoid running it in shared directories, rotate any exposed key, and verify the API endpoint and broken tool implementation are fixed before relying on it.

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/config.py:10
Finding

Plaintext API-Key Storage and Redirectable Credential Transmission

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 except Exception as e: print(f"保存API key失败: {e}") return False ``` ```python 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密钥未设置,请先调用 set_api_key()") headers = { "XBY-APIKEY": api_key, "func": tool_name, "mcpid": mcp_id, "Content-Type": "application/json", } resp = self._session.post( url=url, headers=headers, data=json.dumps(params), timeout=settings.timeout_seconds, ) ``` ### Technical Analysis The Skill persistently stores the API key as plaintext in `.env` by using `Path.write_text()`. It does not explicitly create or enforce owner-only permissions such as mode `0600`. The r ...[truncated 2061 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Unbounded Third-Party Dependency Versions

Content
View full analysis
=2.31.0 pydantic>=2.7.0 pydantic-settings>=2.2.0 python-dotenv>=1.0.1 ``` ### Technical Analysis All dependencies specify only minimum versions. Consequently, a future installation may resolve to package versions that were not present during this audit and have not been reviewed with the Skill. This does not prove that any currently named package is malicious or vulnerable. The weakness is that builds are not reproducible and their effective third-party code can change without a corresponding source-code change in this project. The absence of package hashes also prevents integrity verification against an approved dependency set. ### Attack Path 1. A user or deployment pipeline installs the requirements at a later date. 2. The package resolver selects newer versions than those tested or audited. 3. A selected release contains a security regression, compromised code, or an incompatible behavioral change. 4. Package installation or runtime import executes that unaudited code with the privileges of the user or service running the Skill. This attack path requires compromise or vulnerability of a dependency release, package index, or dependency-delivery process; no such compromise was confirmed in the reviewed files. ### Impact Assessment Potential impact is bounded by the privileges of the installation and runtime process. Depending on the behavior of a compromised dependency, possible effects could include access to the API key, modification of files writable by the process, interception of API requests, or arbitrary code execution. These are potential supply-chain consequences rather than confirmed behavior in the current dependency versions. ]]>
Remediation
View remediation

other

Warning
Location
scripts/tools.py:5
Finding

Invalid Tool Definitions Prevent All Documented Tools from Loading

Content
View full analysis
Dict[str, Any]: """ Echo back a message. Example interface for scaffold. """ arguments = { "message": message } return call_api("1777316659313667", "fund.echo", arguments) def fund.knoewledge( kw: Optional[str] = None, pageSize: Optional[float] = None, pageNum: Optional[float] = None ) -> Dict[str, Any]: """ 获取的知识库列表信息 """ arguments = { "kw": kw, "pageSize": pageSize, "pageNum": pageNum } return call_api("1777316659313667", "fund.knoewledge", arguments) def fund.stock_search( input: str, count: Optional[float] = 10.0 ) -> Dict[str, Any]: """ 搜索股票信息,基于东方财富API """ arguments = { "input": input, "count": count } return call_api("1777316659313667", "fund.stock_search", arguments) ``` ### Technical Analysis Python does not permit a dotted name such as `fund.echo` in a function declaration. Parsing therefore fails at the first `def fund.echo` statement, and `scripts.tools` cannot be imported. The module also refers to `Dict` and `Any` without importing them. Postponed annotation evaluation avoids immediate evaluation in some contexts, but it does not correct the invalid function-declaration syntax. Moreover, no `fund` class, object, or namespace is defined. This is primarily an availability and integrity defect rather than an attacker-controlled privilege escalation. It directly contradicts the documented workflow, which requires calls to `scripts.tools.fund.*`. ### Attack Path 1. The Agent or application follows `SKILL.md` and imports `scr ...[truncated 624 chars]
Remediation
View remediation
Dict[str, Any]: ... def knowledge( kw: Optional[str] = None, page_size: Optional[int] = None, page_num: Optional[int] = None, ) -> Dict[str, Any]: ... def stock_search( input: str, count: int = 10, ) -> Dict[str, Any]: ... ``` 2. Alternatively, define an explicit class or object named `fund` and attach valid methods to it. 3. Import `Any` and `Dict`, or use built-in generic annotations such as `dict[str, Any]`. 4. Align exported names with `SKILL.md`; in particular, correct the apparent `knoewledge` misspelling consistently. 5. Add an automated syntax check such as `python -m compileall scripts`. 6. Add tests that import `scripts.tools` and invoke each documented wrapper with a mocked API client. 7. Validate numeric parameters as integers and enforce documented bounds, including the maximum stock result count. ]]>
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 (32)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The documented behavior materially diverges from the stated purpose: a supposed fund knowledge MCP service includes mismatched high-school-search references, secret collection/persistence instructions, and unclear implementation of the advertised service. This kind of description-behavior mismatch is dangerous because it can mislead users and reviewers into authorizing credentials and capabilities for a skill that does not transparently describe what it actually does.

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

The model_post_init method forcibly reads .env and extracts XBY_APIKEY manually, bypassing the normal settings abstraction and increasing direct handling of plaintext credentials. In this skill context, that secret-reading logic is more concerning because the service is described as a fund knowledge query tool, not a credential management utility.

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

The code reads the full .env file contents into memory and scans for a specific API key, which is unnecessary direct access to a plaintext secret file. This increases the chance of mishandling credentials and normalizes secret access in code that does not need to manage secrets beyond configuration.

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 explicitly saves the API key into a local .env file, creating durable plaintext credential storage. If the host is shared, compromised, backed up insecurely, or the repository is later committed with the .env file, the key can be recovered and abused to access upstream services.

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

The skill declares no explicit tool scope or permission boundaries even though it is documented to use environment access, file reads/writes, and network calls. In an agent setting, missing scope constraints can let the model invoke capabilities beyond the user's reasonable expectations, especially because the workflow also instructs persistent storage of an API key.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill name, description, and all operating instructions are written exclusively in Chinese, and the workflow implicitly requires interaction such as asking for the API key in that language. There is no opt-in, language-selection mechanism, or stated justification that the skill is limited to Chinese users, which creates a locale policy concern.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest says the skill provides '基金相关知识的查询和检索功能', which implies a fund-focused knowledge service. However, the documented tool list includes scripts.tools.fund.stock_search for searching stock information via the Eastmoney API, expanding the behavior beyond fund knowledge retrieval into stock lookup.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The workflow example references an unrelated function (search_schools) in a fund knowledge skill, which is a strong sign of copy-paste drift and inadequate review. In agent skills, contradictory invocation guidance can cause the model to call the wrong tools or route user data into unrelated operations, increasing the risk of unintended data handling and unsafe execution paths.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The function retrieves an API key via get_api_key() and injects it into the outbound request header. Although this is likely necessary for the client, the code does not include any user-facing warning or descriptive comment indicating that stored credentials will be used for remote calls.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code performs a network POST request and sends both an API key in headers and user-supplied parameters in the request body. While it logs success and failure internally, there is no confirmation prompt, print statement, or explanatory comment/docstring disclosing to the user that data and credentials are being sent to an upstream service.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The code persists an API key into a local .env file, creating a plaintext credential at rest on disk. For a read-oriented fund knowledge query skill, this exceeds the minimum necessary behavior and increases the chance of secret exposure through accidental commits, local file disclosure, backups, or multi-user host access.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The module implements local credential persistence and runtime mutation of a global settings object, which is not obviously required for a knowledge retrieval service. This expands the attack surface by adding secret-handling behavior that can expose credentials without providing core query functionality.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The API key is written to .env in plaintext without any user-facing warning or disclosure. This is dangerous because users may assume the key is transient while the software silently leaves a recoverable local secret that can be leaked via source control, support bundles, backups, or other local access.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest says this skill is a 基金知识库服务器 focused on 基金相关知识的查询和检索. The function fund.stock_search specifically searches stock information via an external stock API, which expands the behavior from fund knowledge retrieval into a different financial domain.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

A stock search tool is not an obvious requirement for a service described as a fund knowledge base server that provides fund-related knowledge query and retrieval. This capability materially broadens the skill into securities lookup without that scope being declared in the manifest.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

An echo-back function is not an obvious implementation detail of a fund knowledge query service. Its presence indicates the skill exposes extra behavior beyond the declared fund knowledge retrieval purpose.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

Earlier sections document callable tools under a nested namespace scripts.tools.fund, which suggests a package/module hierarchy. The project structure instead presents scripts/tools.py as a single file, creating a direct inconsistency in how the code is said to be organized and invoked.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The dependency specification uses a lower-bound only constraint for requests, which makes builds non-reproducible and can result in different environments resolving to different versions. This is risky because a vulnerable or behaviorally incompatible release could be installed without visibility, especially since requests has multiple known advisories across versions.

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

The manifest does not pin requests, so it is impossible to verify whether the installed version is affected by any of the known advisories listed for that package. This is dangerous because the actual deployed environment may resolve to a vulnerable release, and network-facing libraries like requests can directly affect confidentiality of credentials and transport security behavior.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
93% confidence
Finding

The pydantic dependency is not pinned to an exact version, so installations may pull different releases over time. In a service component such as this MCP-based knowledge server, that creates supply-chain uncertainty and may expose the deployment to versions affected by known vulnerabilities or breaking validation behavior.

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

Because pydantic is unpinned, there is no assurance that deployments avoid versions with known security issues such as denial-of-service conditions. In a service that validates external or semi-trusted input, a vulnerable parser or validator library can become an attack surface even if the application code itself is simple.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
92% confidence
Finding

Using pydantic-settings with only a minimum version allows future or transitive resolution drift, reducing reproducibility and making it unclear which code is actually deployed. Because settings libraries often interact with secrets and environment-derived configuration, version ambiguity can increase exposure if a flawed release is selected.

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

The version of pydantic-settings cannot be verified from this manifest, so the deployment may include a release affected by known issues. Given that settings packages may load secrets or filesystem-based configuration, uncertainty around the exact version increases operational and security risk.

Content

No source excerpt is available for this finding.