Back to skill

Security audit

股票数据接口服务

Security checks for vulnerabilities and agentic risk

Overview

This stock-data skill is not clearly malicious, but it needs review because it stores an API key in a local plaintext file and has mismatched school/gaokao configuration that can affect where credentials are sent.

Install only if you are comfortable giving this skill a XiaoBenYang API key and having it saved as plaintext in .env in the current working directory. Use an isolated workspace, check for unexpected XBY_GAOKAO_BASE_URL or related .env settings before use, avoid committing .env, and rotate the API key if it may have been exposed.

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

API Key Persisted in a Plaintext Environment File Without Permission Hardening

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 Skill persists a user-provided API key directly into a plaintext `.env` file. It does not explicitly restrict the file to the owner, verify that the path is not a symbolic link, or use an atomic and securely created temporary file. For a newly created file, its permissions are determined by the process umask. In environments with permissive defaults, other local users or processes may be able to read it. If `.env` already exists, the code preserves potentially insecure permissions. The relative path also causes the credential to be written into the current working directory rather than a controlled application configuration directory. The read-modify-write operation is not atomic. Moreover, following an existing `.env` symbolic link could cause the API key to be written to another file selected by a local attacker who can prepare the working directory. ### Attack Path 1. A user activates the Skill without an existing API key. 2. The Skill requests the A ...[truncated 1018 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/config.py:10
Finding

Environment-Controlled API Endpoint Can Receive the User API Key

Content
View full analysis
HttpResult: """调用小笨羊MCP工具""" 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", } # data = {k: str(v) if v is not None else "" for k, v in params.items()} t0 = time.time() try: resp = self._session.post( url=url, headers=headers, data=json.dumps(params), timeout=settings.timeout_seconds, ) ``` ### Technical Analysis `pydantic-settings` maps the `base_url` field to the environment variable `XBY_GAOKAO_BASE_URL`. The client then constructs a request from that value and transmits the API key in the `XBY-APIKEY` header. There is no validation that the configured URL: - Uses HTTPS. - Resolves to the expected `mcp.xiaobenyang.com` hostname. - Uses an approved port. - Is free of embedded user information ...[truncated 1587 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
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (26)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill is presented as a stock-market data interface, but the documented behavior includes persisting API keys to a local .env file and references configuration for an apparently unrelated gaokao/school service. That mismatch increases the risk of credential mishandling, misleading data routing, and accidental reuse of secrets in the wrong service context.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill is presented as a stock-market data interface, but the documented behavior includes persisting API keys to a local .env file and references configuration for an apparently unrelated gaokao/school service. That mismatch increases the risk of credential mishandling, misleading data routing, and accidental reuse of secrets in the wrong service context.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

Settings 类的文档字符串写明这是“小笨羊高考Skill配置”,但当前技能清单名称和用途是股票数据接口服务。这不是单纯信息缺失,而是把模块意图指向了完全不同的业务域,容易误导审计者和使用者对代码真实用途的判断。

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

The model_post_init method force-reads .env and extracts XBY_APIKEY manually, bypassing the more conventional and auditable settings flow. While local file reading alone is not necessarily malicious, this custom secret-harvesting behavior increases suspicion and broadens access to plaintext credentials beyond what is necessary.

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

The code checks for the existence of .env and reads its full contents to locate a specific API key. This creates an avoidable plaintext secret access path and, combined with write-back support elsewhere, indicates the component is actively managing local credentials rather than simply consuming runtime 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
94% confidence
Finding

This function explicitly persists an API key into a local .env file in plaintext, which is a concrete secret-handling weakness. If the host is shared, backed up, inspected by other tools, or the workspace is accidentally committed, the credential can be exposed and abused to access the associated 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
86% confidence
Finding

The skill declares no explicit tool scope or allowed-tools despite requiring environment access, local file read/write, and network access to manage API keys and call remote services. In an agent setting, missing scope declarations weakens least-privilege boundaries and can let the skill operate with broader capabilities than users or reviewers expect.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Including an unrelated school-search example in a stock-data skill is a strong indicator of copy-paste drift and unreliable instructions. In agent systems, such mismatches can cause the model to select incorrect tools, mis-handle user data, or invoke unintended functionality, especially when combined with broad permissions and remote calls.

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 names a gaokao/school-related project even though the skill claims to be for stock data. This contradiction undermines trust in the package identity and suggests the skill may be repurposed code with stale references, which can conceal unintended endpoints, data handling, or credential usage.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code includes Chinese-only docstrings and error/message strings such as '小笨羊MCP API客户端', 'API密钥未设置,请先调用 set_api_key()', and 'API调用失败', with no indication that the skill is region-specific or that users can opt into a language preference. That creates a natural-language locale policy issue because the skill effectively enforces a specific language in user-visible outputs without documented justification.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The module implements mutation and persistence of an API key by writing it into a local .env file and updating process environment state. For a stock data interface that is described primarily as a data access service, adding credential write-back behavior expands the trust boundary and creates unnecessary secret exposure risk on disk, especially if file permissions, backups, or source-control hygiene are poor.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code provides local credential persistence capability without a strong justification visible from the skill’s stated purpose of serving stock market data. Persisting secrets to .env increases the chance of accidental disclosure through local file reads, backups, logs, or repository inclusion, and is broader than what a read-oriented data client typically needs.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The function writes an API key to a local .env file without any user-facing warning, consent, or indication that the secret will persist beyond the current session. This can surprise users and lead to sensitive credential retention in plaintext where other local processes, users, backups, or accidental commits may expose it.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

The dependency specification uses a lower-bound constraint (requests>=2.31.0) instead of pinning to a specific version or constrained range. This weakens reproducibility and can allow installation of an unexpected future release or a vulnerable transitive resolution, which is a supply-chain risk even though no exploit is present in this file by itself.

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 multiple known advisories, and because the dependency is not pinned, it is impossible to determine from this manifest whether the deployed version includes fixes. In a network-facing stock data service, an affected requests release could expose credentials or weaken transport/request handling depending on how the library is used elsewhere.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

The manifest allows any pydantic version at or above 2.7.0, so builds are not deterministic and may pull in later releases with breaking changes or security issues. In a service that processes external data, dependency drift increases supply-chain exposure and makes it hard to verify whether deployed versions are safe.

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 published advisories, and the unpinned specification prevents verification that the installed version contains the necessary fixes. Since this service likely validates external market data and user-supplied parameters, vulnerable parsing or regex behavior could become reachable if an affected version is resolved.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

Using pydantic-settings>=2.2.0 leaves the installed version unconstrained above the minimum, which prevents reproducible builds and can silently introduce vulnerable or incompatible releases. This is a dependency hygiene issue rather than direct malicious logic in the skill.

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 manifest does not pin pydantic-settings, so the presence of an advisory means the actual deployed risk cannot be assessed from this file alone. If the application uses secret-loading features and an affected version is installed, filesystem traversal via symlinks could expose unintended files.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

python-dotenv is specified with only a minimum version, so the environment may install any newer release without review. That creates avoidable supply-chain uncertainty, especially for a package that can read or modify environment configuration used by the service.

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

python-dotenv has known advisories, and the unpinned requirement makes the actual installed security posture unverifiable. In deployments that manipulate .env files or load configuration from writable paths, an affected version could contribute to file overwrite or path/symlink abuse.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The file uses Chinese-only natural-language descriptions in docstrings and comments, which suggests the skill may be designed around a single language without any visible opt-in or language-selection mechanism in this file. Under the language/locale policy, forcing one language without user choice can be a policy concern when not clearly documented as region-specific.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The docstring for get_hist_data states 'Returns: null' at L33-L35, but the implementation returns the result of call_api at L48. The same pattern appears throughout the file, so the inline documentation contradicts the actual behavior rather than merely omitting detail.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.