Back to skill

Security audit

越南股市数据服务

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly acts like a Vietnam stock-data API wrapper, but it saves an API key in a local plaintext .env file and contains stale references to a different gaokao skill, so users should review it before installing.

Install only if you are comfortable giving this skill a xiaobenyang API key and having it stored in a local .env file. Prefer using a limited or revocable key, keep the workspace private, do not commit the .env file, and treat the stale gaokao references as a reason to ask the publisher for a cleaned-up release.

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:48
Finding

API Key Persisted in a Plaintext Working-Directory File Without Permission or Symlink Protections

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 ``` ### Technical Analysis The function stores the API key as plaintext in `.env`, resolved relative to the process's current working directory. It does not select a fixed, application-owned configuration directory or enforce restrictive file permissions such as `0600`. When `.env` is newly created, its effective permissions depend on the process umask. If the file already exists, its existing permissions are retained without validation or correction. As a result, the key can be exposed to other local users or processes where directory or file permissions allow access. The implementation also performs an ordinary path-based read followed by `Path.write_text()`. It does not reject symbolic links, verify file ownership, or use an atomic secure-file creation mechanism. A locally accessible attacker who can prepare the working directory could create `.env` as a symbolic link to another file writable by the Skill's process. The function would follow that link and rewrite the ...[truncated 2424 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 (23)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The file’s declared purpose is a Vietnam stock market data service, but the documented behavior and project structure point to a different service ('xiaobenyang_gaokao_skill') and include local .env modification and API key persistence not clearly disclosed in the description. This mismatch is dangerous because users and reviewers may consent to a finance-data skill while actually granting a mispackaged skill access to secrets, files, and network resources under false expectations.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The configuration is clearly mismatched to the advertised skill: it references a different service name, different env prefix, different API key variable, and a different base URL/domain. In a security-sensitive agent skill, this kind of cross-skill contamination can route credentials and requests to the wrong backend, causing secrets to be exposed or operations to occur against an unintended external service.

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
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 32)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
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 48)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
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 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
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
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")

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill advertises broad capabilities that imply environment access, local file read/write, and network use, but it does not declare any tool scope restrictions such as permissions or allowed-tools. In a skill ecosystem, this weakens least-privilege controls and makes it harder for reviewers and users to understand what the skill can access, especially because the document also instructs persistent API key storage.

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’s name, description, and operational instructions are entirely written as mandatory Chinese-language guidance, with no indication that users may choose another language or locale. Under the policy for natural-language violations, forcing a specific language without user opt-in is a reportable issue unless the locale restriction is clearly justified, which is not stated here.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The project structure and call examples reference a gaokao/school-search skill rather than the claimed stock-market service, indicating the documentation is internally inconsistent and likely copied from another project. In security terms, this is risky because it undermines trust in the stated behavior and suggests the packaged code or configuration may target different APIs, data, or side effects than users expect.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The function persists an API key directly into a local .env file and also exports it into the current process environment with no warning, consent flow, permission checks, or file hardening. In an agent/skill setting, this increases the risk of long-lived secret exposure through local file leakage, accidental commit, workspace sharing, or other tools reading the same directory.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

L026 声称“代码只负责调用API”,但 L034 与 L018 明确要求调用 scripts.config.set_api_key(...) 保存用户提供的密钥。保存配置属于本地状态写入,不是单纯的 API 调用,因此该说明与预期行为存在直接意图冲突。

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

The dependency is specified with a lower bound only, so builds may resolve to different versions over time. This weakens reproducibility and can unintentionally introduce vulnerable or breaking upstream releases into deployments.

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

Requests has multiple known advisories, and because the manifest does not pin a specific version, it is not possible to verify whether deployed environments are using an affected release. The risk is contextual rather than immediate from this file alone, but the inability to attest to a safe version is a real supply-chain weakness.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

Using an unpinned pydantic version allows future installs to pull in any newer release that satisfies the minimum constraint. That creates supply-chain and stability risk because security posture depends on whatever version happens to be installed later.

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

Pydantic has published advisories, but the unconstrained upper range means installations may resolve to vulnerable versions without notice. This prevents reliable security verification and increases maintenance risk for the service.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The pydantic-settings package is not version-pinned, so environments may install different releases with different security characteristics. This makes it harder to verify whether the deployed package is affected by known issues.

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

Because pydantic-settings is not pinned, the project cannot demonstrate that it avoids known affected versions. While exploitability depends on how the package is used elsewhere, leaving the version floating undermines supply-chain assurance.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

A minimum-only version for python-dotenv permits drift to later versions without explicit review. In dependency-managed services, this is a common supply-chain hygiene weakness that can expose deployments to newly introduced vulnerabilities or behavior changes.

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

Python-dotenv has known advisories, and an unpinned requirement means the actual installed version is unverifiable from the manifest. In a service that may process environment files or local configuration, this uncertainty raises avoidable security risk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

This file contains natural-language docstrings and error/status messages exclusively in Chinese, such as the class/method descriptions and the API key error and failure message. Under the policy rule, forcing a specific language without user opt-in is a locale/language policy concern, and no alternative language option or opt-in is provided here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The class docstring is written only in Chinese, and the surrounding user-facing strings in this file are also Chinese-only. Under the policy, forcing a specific language without user opt-in can be a natural-language policy issue unless the locale constraint is explicitly justified.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

L31 的注释描述为“强制从 .env 文件读取”,暗示 .env 是决定性来源;但 L39-L42 立即又读取环境变量并在有值时覆盖 .env 中的值。该注释与实际优先级逻辑相矛盾,可能误导维护者对凭据来源和覆盖行为的理解。

Content

No source excerpt is available for this finding.