Back to skill

Security audit

火焰检测

Security checks for vulnerabilities and agentic risk

Overview

This fire-detection skill appears to call a remote image-analysis API, but it has stale unrelated gaokao/school-search references and stores an API key in a local plaintext .env file.

Review before installing. Only use this skill with images you are comfortable sending to xiaobenyang's remote service, and avoid sensitive security-camera or traffic footage unless that data sharing is acceptable. Prefer providing the API key through a secure secret mechanism rather than allowing the skill to write it to .env. The publisher should remove gaokao/school-search leftovers, document remote image transmission, validate API-key values, and harden or avoid local secret storage.

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:44
Finding
API Key Stored in a Plaintext Dotenv File Without Input Sanitization or Restrictive Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/config.py:44-65` **Vulnerability Type**: Plaintext credential storage and dotenv injection **Risk Level**: Medium ### Vulnerable Code ```python def save_api_key_to_env(api_key: str) -> bool: 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"Failed to save API key: {e}") return False def set_api_key(api_key: str) -> bool: if not api_key or not api_key.strip(): return False api_key = api_key.strip() if not save_api_key_to_env(api_key): return False ``` ### Technical Analysis The application persists the API key directly in a plaintext `.env` file. It does not explicitly apply restrictive file permissions such as mode `0600`. When the file is created, its effective permissions therefore depend on the process umask. In an environment with a permissive umask, another local user or process may be able to read the credential. The API key is also interpolated directly into dotenv file contents without rejecting embedded carriage-return or newline characters. Calling `strip()` removes only leading and trailing whitespace; it does not remove newline characters within the value. A value such as `legitimate-key\nADDITIONAL_SETTING=attacker-value` can consequently introduce an additional persistent dotenv entry. The file update is not atomic. An inte ...[truncated 1952 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Prefer a platform credential manager, secret-management service, or session-scoped environment variable instead of writing the API key to the project directory. 2. If dotenv persistence is required, reject carriage returns and newlines before writing: ```python if "\r" in api_key or "\n" in api_key: raise ValueError("API key contains invalid characters") ``` 3. Create the secret file with restrictive permissions and verify them after replacement: ```python os.chmod(env_path, 0o600) ``` 4. Update the file atomically by creating a mode-`0600` temporary file in the same directory, flushing and synchronizing it, and replacing `.env` with `os.replace()`. 5. Avoid constructing dotenv records through unrestricted string interpolation. Use a serializer that safely quotes values, while still rejecting line separators. 6. Ensure `.env` is excluded from version control, build artifacts, logs, backups, and diagnostic bundles. 7. Avoid retaining the credential in both a plaintext file and `os.environ` unless both storage locations are operationally required. 8. Document the local threat model and warn users that persistent storage places the key on disk. ]]>
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
98% confidence
Finding
The document mixes a fire-detection identity with configuration management, .env modification, API-key storage, and even references to gaokao-related server settings. Such cross-domain mismatch is a strong indicator of copy-paste errors or repurposed code, which can hide unsafe behavior and cause users to authorize actions unrelated to the stated purpose.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The document mixes a fire-detection identity with configuration management, .env modification, API-key storage, and even references to gaokao-related server settings. Such cross-domain mismatch is a strong indicator of copy-paste errors or repurposed code, which can hide unsafe behavior and cause users to authorize actions unrelated to the stated purpose.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
Most of the document content appears inconsistent with the stated fire-detection purpose and instead describes a different workflow lineage, suggesting the skill may be mislabeled or assembled from unrelated materials. This is dangerous because reviewers and users cannot reliably determine what the agent will do, which undermines trust and can conceal unauthorized data handling.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The file implements configuration and persistence for a '高考' API key and endpoint even though the declared skill is '火焰检测'. This strong intent mismatch is suspicious because it suggests code reuse from an unrelated skill or hidden functionality that handles credentials outside the expected fire-detection scope, increasing the risk of unauthorized secret collection or exfiltration.

Intent-Code Divergence

High
Confidence
99% confidence
Finding
The class docstring explicitly says this is configuration for a different skill ('小笨羊高考Skill配置'), directly conflicting with the advertised fire-detection function. Such a mismatch is dangerous in security review because it indicates the package may include unrelated behavior, hidden dependencies, or repurposed code paths that operators would not expect or authorize.

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
86% confidence
Finding
The model_post_init method explicitly opens and parses the local .env file to extract XBY_APIKEY, bypassing normal settings abstraction and directly handling credential material. In the context of a fire-detection skill with unrelated gaokao identifiers, this manual secret collection is more suspicious and broadens the risk of unauthorized credential use.

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
84% confidence
Finding
The code checks for and reads a local .env file specifically to obtain an API key, which is direct credential access logic. While not exfiltration on its own, it unnecessarily increases secret exposure and is made more concerning by the mismatch between the skill's advertised purpose and the credential namespace being accessed.

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.

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
93% confidence
Finding
This function persists an API key into a local .env file, creating durable secret storage in the application workspace. That is dangerous because the key may be exposed through weak file permissions, backups, logs, accidental source-control commits, or later access by unrelated code, especially in a skill whose declared purpose does not justify managing external gaokao credentials.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill declares no explicit tool scope or permission boundaries even though its documented workflow implies access to environment variables, file reads/writes, and outbound network calls. Missing scope declarations increase the chance of overbroad execution or accidental abuse because the runtime may grant more capability than users expect.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The example instructs use of `search_schools`, which directly contradicts the declared fire-detection tools and indicates stale or incorrect operational guidance. Incorrect examples can cause the agent or maintainers to invoke unrelated capabilities, potentially exposing user data to the wrong backend or executing unintended workflows.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill asks users to provide image URLs or base64 image data for processing by an external API but does not warn that this content will leave the local environment. For security and privacy-sensitive contexts like security cameras or traffic feeds, undisclosed external transmission can expose sensitive imagery, metadata, or regulated data.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The project structure names the package `xiaobenyang_gaokao_skill`, which conflicts with the fire-detection identity and suggests the skill may be a rebranded or repurposed package. Identity confusion at the package level raises supply-chain and maintainability concerns because imported modules or configurations may belong to a different application domain than users were told.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
This code sends `params` to a remote `/api` endpoint and includes the `XBY-APIKEY` credential in request headers. While the module logs success/failure for developers, there is no user-facing warning, confirmation, or explanatory comment/docstring disclosing that user/system data may be transmitted off-host.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
The code can persist an API key into a local .env file and mirror it into process environment variables, which exceeds what is obviously necessary for a fire-detection skill module. Local credential persistence increases the attack surface because secrets may be stored insecurely, committed accidentally, or read later by unrelated code running in the same environment.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
This code file sends user-supplied image data to an external API via call_api, which is a network operation that may transmit user content off-system. The function includes only a technical docstring and no confirmation prompt, logging, or explicit warning that the image link/data will be sent to a remote service.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The function accepts raw base64-encoded image data and forwards it to call_api, which implies external transmission of potentially sensitive user content. The surrounding documentation describes the input format but does not warn users that the image payload leaves the local environment.

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
96% confidence
Finding
The dependency uses a lower-bound specifier only, which permits installation of any later version and makes builds non-reproducible. This increases supply-chain risk because vulnerable or incompatible releases could be pulled in without review, especially for a security-relevant skill that may process external inputs.

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
89% confidence
Finding
Requests has multiple known advisories, and because the manifest does not pin an exact version, it is impossible to determine from this file whether deployment will use a patched or vulnerable release. This uncertainty is itself a supply-chain risk, though the file alone does not prove a specific exploitable CVE is present.

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 pydantic>=2.7.0 without an exact pin allows unreviewed future releases to be installed, reducing reproducibility and making it hard to verify whether vulnerable versions are in use. This is a genuine supply-chain hygiene weakness rather than an immediate exploit by itself.

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 known advisories, and the lack of exact version pinning prevents verification that the installed release is patched. This is dangerous because validation libraries often process attacker-controlled input, so known parser or regex issues could become reachable if an affected version 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
The unpinned pydantic-settings dependency allows resolution to arbitrary newer releases, which can introduce vulnerable code or breaking behavior unexpectedly. In a skill that likely uses environment-based configuration, dependency integrity matters because settings libraries may interact with secrets and filesystem sources.

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
90% confidence
Finding
pydantic-settings has a known advisory history, and the open-ended dependency specification means the deployed version cannot be verified from the manifest. Since settings libraries may read secrets or interact with filesystem-backed configuration, unresolved version ambiguity can expose the application to avoidable risk.

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
python-dotenv is specified only with a minimum version, so future dependency resolution may install an unreviewed release. Because dotenv tooling commonly reads or writes sensitive configuration, lack of pinning increases the chance of supply-chain exposure or accidental adoption of vulnerable behavior.

Static analysis

No suspicious patterns detected.