Back to skill

Security audit

昆虫识别

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly performs insect recognition through an external API, but it stores API keys in a local plaintext .env file and has enough copy-paste configuration drift to require careful review before installation.

Review this skill before installing. Only use it if you trust the Xiaobenyang API with the images you submit and are comfortable with the API key being written to a local .env file in plaintext. Prefer rotating the key after testing, keeping .env out of repositories and backups, and avoiding sensitive personal or location-revealing images unless the provider's privacy terms are acceptable.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/config.py:43
Finding
API Key Stored in an Unprotected Plaintext Environment File## Vulnerability Details **File Location**: `scripts/config.py:43-62` **Vulnerability Type**: Plaintext credential storage and environment-file injection **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 persists an API credential as plaintext in a relative `.env` file. It does not explicitly set restrictive file permissions, so the effective permissions depend on the host's umask and any permissions already assigned to the file. The relative path also causes the secret to be written into the process's current working directory rather than a dedicated, controlled configuration directory. This can result in the credential being stored in an unrelated repository, included in backups, or accidentally committed to version control. The function also interpolates `api_key` directly into dotenv content without rejecting embedded carriage-return or newline characters. Although `set_api_key()` strips leading and trailing whitespace, it does not remove internal newline characters. A caller able to control the submitted key can therefore add additional dotenv entries. Those injected ...[truncated 1909 chars]
Remediation
## Remediation Suggestions 1. Prefer an operating-system credential store, deployment secret manager, or platform-provided secret facility instead of writing credentials to a project file. 2. If file persistence is required, use a fixed Skill-specific configuration directory rather than the current working directory. 3. Create the secret file atomically with owner-only permissions such as `0600`, and verify existing file ownership and permissions before updating it. 4. Reject API keys containing `\r`, `\n`, NUL characters, or characters outside the provider's documented key format. 5. Escape values using a standards-compliant dotenv serializer if arbitrary values must be supported. 6. Ensure `.env` is excluded from version control, build artifacts, diagnostic bundles, and backups that do not require it. 7. Avoid printing or logging credential values, and document a credential-rotation procedure for suspected disclosure.

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding
Dependencies Are Resolved Without Upper Bounds, Locking, or Integrity Hashes## Vulnerability Details **File Location**: `requirements.txt:1-4` **Vulnerability Type**: Unbounded and non-reproducible dependency resolution **Risk Level**: Low ### Vulnerable Code ```text requests>=2.31.0 pydantic>=2.7.0 pydantic-settings>=2.2.0 python-dotenv>=1.0.1 ``` ### Technical Analysis Every third-party package is specified only with an open-ended minimum version. No lock file or package hashes are present. Consequently, installations performed at different times may resolve to different, unreviewed releases, including future major versions. The listed package names correspond to established packages, so the reviewed files do not demonstrate typosquatting, dependency confusion through private package names, or an existing malicious dependency. The issue is that dependency integrity and reproducibility are not enforced, increasing exposure to a compromised future release, registry-account compromise, or incompatible upstream changes. ### Attack Path 1. An upstream package account, release process, or distribution channel is compromised, or a future release introduces malicious behavior. 2. The compromised release retains a version satisfying the project's open-ended `>=` constraint. 3. A user or automated deployment installs the project after that release becomes available. 4. The package resolver selects the unreviewed release because no lock file, exact version, or expected hash prevents it. 5. Package installation or runtime import executes the compromised dependency with the privileges of the installing or running account. This attack path depends on compromise or malicious publication through the configured package source; no such compromise was observed during this source audit. ### Impact Assessment A compromised dependency could execute code with the privileges of the process installing or running the Skill. Depending on the deployment environment, this could expose the API ke ...[truncated 313 chars]
Remediation
## Remediation Suggestions 1. Generate and commit a dependency lock file containing reviewed, exact transitive versions. 2. For pip-based deployments, use hash-verified requirements and install with `pip install --require-hashes`. 3. Define compatible upper bounds where exact application-level pins are not appropriate. 4. Update dependencies through a controlled process that includes vulnerability scanning, changelog review, and automated tests. 5. Use only trusted package indexes and explicitly configure the index source in build and deployment environments. 6. Regenerate locks and hashes after reviewing each dependency update rather than allowing installation-time resolution of arbitrary future releases.
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 skill claims to identify insects, but it also manages local configuration by reading .env, writing persistent API keys, and modifying connection settings such as base_url and retry behavior. This mismatch is dangerous because hidden configuration-management behavior can expose secrets, enable tampering with outbound destinations, and persist sensitive credentials without clear user understanding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill claims to identify insects, but it also manages local configuration by reading .env, writing persistent API keys, and modifying connection settings such as base_url and retry behavior. This mismatch is dangerous because hidden configuration-management behavior can expose secrets, enable tampering with outbound destinations, and persist sensitive credentials without clear user understanding.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The file’s behavior does not match the declared skill purpose of insect identification. Instead, it configures a remote 'gaokao' service and manages API credentials, which is a strong scope mismatch that can conceal unrelated network access and secret handling inside an innocuous-looking skill. In this context, the mismatch materially increases the risk that users or reviewers would grant trust to code that performs unrelated credential operations.

Credential Access

High
Category
Privilege Escalation
Content
model_config = SettingsConfigDict(
        env_prefix="XBY_GAOKAO_",
        env_file=".env",
        env_file_encoding="utf-8",
        extra="ignore",
    )
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
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")
Confidence
90% confidence
Finding
This code explicitly reads a local .env file to extract XBY_APIKEY, bypassing ordinary declarative settings loading and creating direct credential-handling logic inside a skill unrelated to insect identification. While reading one’s own config is not inherently malicious, the hidden, forced secret retrieval increases risk because it normalizes secret access in a misleading context and can expose credentials to unrelated skill logic.

Credential Access

High
Category
Privilege Escalation
Content
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():
Confidence
90% confidence
Finding
Creating a hardcoded path to '.env' and then reading it as part of initialization bakes credential access into normal execution of the skill. In a mismatched skill context, that means merely loading the skill can trigger secret access unrelated to the advertised function, increasing the chance of inappropriate secret use or reviewer deception.

Credential Access

High
Category
Privilege Escalation
Content
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
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The skill persists an API key to a local .env file and the current process environment even though that behavior has no clear need for insect identification. Persisting secrets broadens exposure through accidental source inclusion, local disclosure, backup leakage, and reuse by unrelated processes or components. Because the skill’s advertised function is unrelated, this capability is especially suspicious and dangerous in context.

Credential Access

High
Category
Privilege Escalation
Content
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()
Confidence
96% confidence
Finding
This function is dedicated to saving an API key into a .env file, creating durable local credential storage. Persistent secret writing expands the attack surface through local disclosure, backup leakage, accidental commit, and unauthorized reuse, and it is especially unjustified given the stated insect-identification purpose of the skill.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill declares capabilities that include environment access, file read/write, and network communication, but it does not define any explicit tool scope or permissions boundary. This increases the attack surface because the runtime may permit broader actions than users would reasonably expect from an insect-identification skill, including credential handling and persistent local modification.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill explicitly asks the user for an API key and persists it via set_api_key without warning about storage, retention, or who can access the secret afterward. This creates credential-handling risk because users may disclose reusable secrets to a skill that writes them to local configuration, potentially exposing them to other processes, logs, or future sessions.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The workflow example references an unrelated function for school search, indicating copy-paste documentation drift and weak control over tool-selection instructions. In security terms, this can lead the agent to invoke unintended tools or normalize broader routing behavior than the skill's declared purpose, especially in systems that rely on markdown instructions for execution logic.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill instructs users to provide image URLs or base64 image data and send them to an external API, but it does not warn that user content will leave the local environment. This is a privacy and data-handling issue because images may contain sensitive personal, location, or proprietary information, and users are not given informed consent about external transmission.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
This file contains natural-language strings in Chinese, including the class docstring, and does not indicate that the skill is region-specific or that users can opt into a language preference. Under the policy, forcing a specific language without user opt-in is a locale-policy violation.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The exception text shown to users is only in Chinese and the file provides no mechanism to select another language or confirm that Chinese-only output is intentional for a region-specific skill. This creates a natural-language policy issue for locale handling.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The function docstring and failure message use Chinese-only natural language, and there is no opt-in or justification that the skill must operate only in that language. This can violate organizational language/locale policy for user-facing content.

Intent-Code Divergence

Medium
Confidence
99% confidence
Finding
The class docstring identifies the component as a '小笨羊高考Skill配置', directly conflicting with the declared '昆虫识别' skill. This inconsistency is a supply-chain red flag because it suggests code reuse, mislabeling, or concealed functionality that can mislead review and approval processes. While not an exploit by itself, it undermines trust boundaries and contributes to unsafe deployment decisions.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The code stores an API key into .env without any explicit warning, consent flow, or indication of persistence to the user. Users may believe they are providing a transient credential while the skill silently creates durable local secret storage, increasing the chance of inadvertent disclosure through filesystem access, backups, or repository mistakes.

Intent-Code Divergence

Low
Confidence
93% confidence
Finding
L091 将项目结构根目录写为 `xiaobenyang_gaokao_skill/`,而本技能名称和描述均为昆虫识别。虽然这不直接证明代码行为异常,但属于文档层面对技能意图的明显错配,容易误导调用方或维护者对实际实现目的的理解。

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
Confidence
95% confidence
Finding
The dependency is specified with a lower bound only, so future installs may resolve to different versions over time. This weakens reproducibility and can unintentionally introduce vulnerable or breaking upstream releases into the skill’s environment.

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
requests has multiple known advisories, and because the manifest does not pin a version there is no way to verify whether deployed environments are using a patched release. In a skill that may make outbound HTTP requests, that uncertainty increases supply-chain and runtime risk, even though the file alone does not prove exploitation.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
Confidence
95% confidence
Finding
Using an unpinned pydantic version allows dependency resolution to drift, which can pull in versions with known flaws or incompatible behavior. This is a supply-chain hygiene issue rather than an immediate exploit by itself, but it increases risk over time.

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
pydantic has known advisories, but the version range is open-ended, so the actual installed version may be vulnerable and cannot be verified from this manifest. This is primarily a dependency management weakness that can expose the skill to parser or validation-related flaws if an affected release is resolved.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
Confidence
94% confidence
Finding
An unpinned pydantic-settings dependency means builds are not deterministic and may consume newly released versions without review. If a future or currently vulnerable version is selected, the application may inherit that exposure unnoticed.

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
86% confidence
Finding
Because pydantic-settings is not pinned, the package manager could resolve to a release affected by known issues such as unsafe secret-source handling. The risk is contextual: if the skill reads secrets from the filesystem, this could become more relevant, but from this file alone the exposure remains low-confidence and low-impact.

Static analysis

No suspicious patterns detected.