Back to skill

Security audit

植物识别

Security checks for vulnerabilities and agentic risk

Overview

This plant-recognition skill appears to use an external API for its stated purpose, but it stores your API key in a local plaintext .env file and contains leftover unrelated gaokao/college-admissions references that warrant review before installation.

Install only if you are comfortable giving this skill a Xiaobenyang API key and sending plant image URLs or image data to that external service. Use a dedicated, revocable API key, avoid running it in a shared or source-controlled workspace unless .env is protected and ignored, and review the gaokao copy/paste remnants with the publisher before relying on the package.

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

API Key Persisted in a Plaintext File Without Permission Hardening

Content
View full analysis

Vulnerability Details

File Location: scripts/config.py:49-70
Vulnerability Type: Plaintext storage of sensitive credentials
Risk Level: Medium

Vulnerable Code

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()
        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 permanently stores the user-provided API key as plaintext in a .env file located in the process's current working directory. When this file is created, its permissions are determined by the process umask. The implementation does not explicitly require owner-only permissions, verify the permissions of an existing file, or use a protected operating-system credential store.

The use of a relative path also means the credential may be written into a shared workspace or project directory. Such a file can be exposed through local file access, workspace synchronization, backups, archive creation, or accidental source-control inclusion.

The function rewrites the file directly rather than creating a protected temporary file and replacing the destination atomically. This can also result in insecure permission inheritance or partial writes, although the principal security concern is plaintext credential exposure.

Attack Path

  1. A user supplies an Xiaoben ...[truncated 1094 chars]
Remediation
View remediation

Remediation Suggestions

  1. Prefer runtime-only secret injection or an operating-system credential manager instead of writing the API key into the project directory.
  2. Obtain explicit user consent before persisting any credential and clearly identify the storage location.
  3. If file-based storage is unavoidable, use a dedicated per-user configuration directory outside the project or shared workspace.
  4. Create the credential file with owner-only permissions, such as mode 0600 on POSIX systems, and reject or repair existing files with broader permissions.
  5. Write updates atomically by creating a protected temporary file in the same directory, flushing it, applying restrictive permissions, and replacing the destination.
  6. Ensure .env is excluded from source control, packaging, logging, workspace publication, and backups where practical.
  7. Support credential revocation and rotation, and advise users to rotate any key that may already have been stored in an exposed workspace.
  8. Avoid printing or returning credential values in exception messages or diagnostic output.
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 (30)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The documentation says the skill recognizes plants, but it also manages local configuration, reads and writes .env, and stores API credentials and service settings. That broader behavior materially changes the trust model because the skill is not merely inferential; it persists secrets and modifies local state.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The documentation says the skill recognizes plants, but it also manages local configuration, reads and writes .env, and stores API credentials and service settings. That broader behavior materially changes the trust model because the skill is not merely inferential; it persists secrets and modifies local state.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The file’s actual behavior is materially inconsistent with the declared skill purpose: instead of plant-identification-specific configuration, it contains configuration for a different remote service and API key handling logic. In a skill ecosystem, this kind of capability mismatch is dangerous because it can conceal unnecessary secret-handling and network-related behavior under an unrelated benign description, reducing reviewer and user scrutiny.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The class docstring labels this as a gaokao skill configuration while the published skill claims to be for plant identification. This discrepancy is a strong trust and provenance red flag: misleading identity can hide unrelated capabilities, especially secret access and remote-service configuration, inside a package users would not expect to perform those actions.

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

This logic explicitly reads .env and extracts XBY_APIKEY, duplicating framework behavior and normalizing direct secret access in skill code. In the context of a mislabeled plant-identification skill, this increases danger because the skill handles credentials unrelated to its declared purpose and broadens the path for secret exposure or misuse.

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

The code opens and reads the .env file directly, which is explicit credential-access behavior rather than passive configuration. While not inherently malicious, it is unnecessary in this context and contributes to secret exposure risk, especially if combined with unrelated functionality hidden in a benign-seeming skill.

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 .env, creating plaintext credential persistence on disk. In a skill presented as plant identification, that capability is especially suspicious and dangerous because it can retain sensitive tokens beyond the session, expose them to other local processes, and facilitate accidental disclosure.

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 exposes capabilities that imply environment access, local file read/write, and network use, yet the manifest does not declare any tool scope or least-privilege boundaries. This increases the chance that a user or orchestrator cannot accurately understand or constrain what the skill may access, especially since the workflow includes reading and writing .env and calling external APIs.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill instructs the model to ask the user for an API key and persist it, but it does not warn that the credential will be stored locally or explain retention and handling. This creates a meaningful secret-management risk because users may provide a sensitive key without informed consent about persistence, reuse, or exposure through files or logs.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The workflow explicitly instructs collecting a user-provided API key and saving it via set_api_key, which implies persistence of a secret in local configuration. Persisting credentials through conversational flow is dangerous because it can lead to accidental disclosure, insecure storage, or unauthorized reuse if the environment or files are accessible.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill directs the model to display result["raw"] directly after formatting, which risks exposing sensitive upstream fields, internal identifiers, verbose errors, or untrusted content returned by the API. Returning raw remote data without allowlisting fields can also propagate unexpected content to the user and leak implementation details.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code includes Chinese-only docstrings and error/message strings such as the class and function descriptions and the API-key error, which creates a language-specific experience for users and operators. Under the policy, forcing a specific language without opt-in or documented justification is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The code persists an API key to a local .env file and copies it into process environment state, which exceeds what is obviously necessary for a plant recognition skill. Persisting secrets locally increases exposure through accidental commits, insecure file permissions, workspace leakage, or reuse by unrelated code in the same runtime.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The function writes the API key to .env without any user-facing notice, consent flow, or warning about persistence. Silent credential persistence is risky because users may assume the key is used transiently, while in reality it remains on disk and can be exposed through backups, source control, or local compromise.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The function sends a user-supplied image URL to an external API via call_api without any disclosure, consent, or indication of data handling in this file. Even if expected for plant recognition, transmitting user content to a third party can expose sensitive images or internal resource URLs and creates a privacy and data-governance risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This function transmits raw base64-encoded image content to an external API without any explicit warning or consent mechanism in the code shown. Because base64 payloads may contain sensitive photos or embedded metadata, silent forwarding to a third party poses a real privacy and compliance risk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

SQP-3 applies to all file types and covers language/locale policy violations. The skill name, description, and operational instructions are entirely in Chinese and present no option for another language or any justification that this must be a Chinese-only, region-specific skill.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

L037 的文档示例要求调用 scripts.tools.search_schools(score='520', province='北京', category='综合'),但本技能清单和其余文档均声明该技能用于植物识别。这不是单纯信息缺失,而是内联说明直接展示了与当前技能目标不一致的工具调用,表明文档意图与技能实际用途存在明显偏差。

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency is specified with a lower bound only, so installs are not reproducible and may pull in different future releases with security or compatibility regressions. Because this file also uses a package with multiple known advisories, the lack of pinning makes it impossible to verify whether a safe version will actually be installed.

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

requests has multiple known advisories, but the manifest does not pin a version, so the deployed package may or may not be vulnerable. In security terms this is dangerous because maintainers cannot prove that installations avoid affected releases, leaving exposure dependent on resolver behavior and install timing.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

Using pydantic>=2.7.0 allows any newer version to be installed, which weakens supply-chain control and can introduce vulnerable or breaking releases unexpectedly. This is especially relevant because pydantic has known advisories across some versions, and the manifest does not guarantee installation of a patched release.

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

The use of an unpinned pydantic version means the project cannot verify whether installed versions are affected by published CVEs. This creates audit uncertainty and can expose consumers to vulnerable releases during fresh installs or rebuilds.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

An unpinned pydantic-settings dependency permits uncontrolled version drift, which can silently introduce vulnerable behavior or incompatibilities. Since advisories exist for this package family, leaving the version open-ended prevents auditors from determining whether deployments are actually safe.

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