Back to skill

Security audit

生物年龄计算服务

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to call a biological-age API, but it automatically stores an API key in a local .env file and contains leftover unrelated exam-service references that users should review carefully.

Install only if you are comfortable giving this skill a XiaoBenYang API key, having it stored in a local .env file, and sending biomarker inputs to the remote API. Review or fix the stale gaokao references, add explicit consent and secure key storage, and pin dependencies before using it in a sensitive environment.

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

API Key Persisted in Plaintext Without Restrictive File Permissions

Content
View full analysis

Vulnerability Details

File Location: scripts/config.py, lines 45-66
Vulnerability Type: Plaintext credential storage with insufficient file-permission controls
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 persistently writes the user's API key as plaintext into a relative .env file. Path.write_text() does not explicitly establish owner-only permissions. For a newly created file, its permissions depend on the process umask; for an existing file, potentially permissive permissions remain unchanged. The implementation also does not verify the ownership, type, or permissions of an existing .env path before overwriting it.

Consequently, a local user or process able to read the working directory may retrieve the credential. A maliciously prepared working environment could also expose the key through a pre-existing permissive file or redirected path. The code does not reject newline characters in the supplied key, which could additionally permit unintended entries to be injected into the generated .env file, although no direct code-execution path was id ...[truncated 1296 chars]

Remediation
View remediation

Remediation Suggestions

  1. Prefer session-only credential handling or an operating-system credential store rather than writing the key to the project directory.
  2. If file persistence is necessary, create the credential file atomically with owner-only permissions such as mode 0600.
  3. For an existing .env file, verify that it is a regular file owned by the expected user and reject unsafe ownership, symbolic links, or group/world-accessible permissions.
  4. Set restrictive permissions explicitly after creation and fail closed if they cannot be enforced.
  5. Validate the API key before storage, including rejecting carriage returns and newline characters.
  6. Store the file at a deterministic, user-private configuration location rather than relative to the current working directory.
  7. Inform the user that the credential will be persisted and obtain consent; provide a supported method to remove or rotate the stored key.
  8. Ensure .env is excluded from version control, backups, diagnostic bundles, and logs.
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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (27)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This finding indicates the skill reads and persists API keys in .env, mutates process environment variables, and uses configuration naming/comments associated with an unrelated 'gaokao' skill. That combination strongly suggests copy-paste reuse and undocumented credential-handling behavior, which can lead to accidental secret exposure, cross-skill confusion, and users consenting to one purpose while enabling another.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This finding indicates the skill reads and persists API keys in .env, mutates process environment variables, and uses configuration naming/comments associated with an unrelated 'gaokao' skill. That combination strongly suggests copy-paste reuse and undocumented credential-handling behavior, which can lead to accidental secret exposure, cross-skill confusion, and users consenting to one purpose while enabling another.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The configuration implements credential handling and remote MCP/high-school exam service settings that do not match the declared biological-age skill. This mismatch is a strong indicator of repurposed or hidden functionality and increases the risk that user secrets are being collected for an unrelated 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
82% confidence
Finding

The code explicitly and forcibly reads XBY_APIKEY from .env regardless of the declared skill purpose, coupling this skill to an unrelated credential source. In the context of a biological-age calculator, this unnecessary secret access is suspicious and expands the blast radius if local files are exposed or the skill is repurposed to exfiltrate credentials.

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

Opening and reading the .env file directly gives this code access to locally stored secrets outside the normal typed configuration path. Because the skill's declared function does not justify unrelated XBY_APIKEY access, this behavior is risky and contextually suspicious.

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

This code prioritizes an environment variable for XBY_APIKEY after manually reading the same secret from disk, reinforcing unnecessary collection and retention of an unrelated credential. In a mismatched skill, repeated secret-handling logic heightens concern about hidden external-service coupling or future misuse.

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

The function is specifically designed to save an API key into .env, creating persistent local secret storage. In this skill context, persisting an unrelated remote-service credential is especially dangerous because it both exceeds the expected behavior of a biological-age calculator and makes accidental exposure much more likely.

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

The skill exposes capabilities implying environment access, file read/write, and network use, but does not declare any tool scope or allowed-tools boundaries. This weakens least-privilege controls and makes it harder for reviewers and users to understand what the skill can access, increasing the risk of overbroad execution if the backing code is compromised or behaves unexpectedly.

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 agent to collect an API key from the user and store it, but does not warn that the credential is sensitive or that it may be persisted. This creates a clear secret-handling risk: users may disclose credentials without informed consent, and persistent storage in files or environment variables can expose the key to other processes, logs, or future sessions.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The documentation includes a tool invocation example for school-search functionality unrelated to biological-age calculation. In security-sensitive agent skills, inaccurate examples can misroute the model toward unintended tool calls or reveal that the skill was repurposed from another domain without careful review, increasing the chance of unsafe behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The function retrieves a credential via get_api_key() and places it into the XBY-APIKEY request header for an external request. Although this is operationally necessary, the file does not include any user-facing notice or explanatory documentation that the skill accesses stored credentials and sends them to the upstream service.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This code sends the caller-provided params payload to a remote endpoint via requests.Session.post, which can transmit user or system data off-host. While the module has internal logging for success and errors, it does not provide a user-facing warning, confirmation, or explanatory comment/docstring about this outbound data transmission.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The class docstring says this is a '高考Skill配置', which directly contradicts the declared skill purpose. While not an exploit by itself, this inconsistency is a meaningful trust and provenance signal that the file was copied from another project or that the skill may be misrepresenting its behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code persists an API key into a local .env file automatically, without explicit user consent, warning, or secure storage controls. This can expose secrets through local file disclosure, source-control mistakes, backups, or multi-user host access.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
74% confidence
Finding

The skill mandates behavior and instructions primarily in Chinese while parts of the trigger/tool mapping are in English, but nowhere offers the user a language choice or states that the skill is intentionally limited to a Chinese-speaking context. This can amount to a language/locale policy issue because the documentation effectively assumes a language without explicit opt-in or justification.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The project structure names the package as a gaokao skill, which contradicts the stated biological-age purpose. While this is weaker evidence than behavioral mismatch, it still signals possible code provenance issues and insufficient review, making hidden functionality or misconfiguration more plausible.

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, which allows future installs to resolve to different versions over time. This weakens reproducibility and can unintentionally pull in vulnerable or breaking releases, especially for a network-facing library like requests.

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

The manifest does not pin requests, and requests has multiple known advisories across versions. That means the actual installed version cannot be verified as safe, leaving open the possibility of exposure to issues such as credential leakage or TLS-related flaws depending on what resolver selects.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

Using pydantic>=2.7.0 without an exact pin permits non-deterministic installations and may introduce vulnerable or incompatible versions later. For validation libraries, this can expose the service to parser or regex-related flaws present in newly resolved versions.

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

Because pydantic is not pinned, the project may resolve to a version affected by known issues such as denial of service or parser edge-case bugs. In a service that processes user-supplied biomarker data, that uncertainty increases operational risk even if no exploit is evident in this file alone.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
93% confidence
Finding

An unpinned pydantic-settings dependency makes the runtime version uncertain across environments and deployments. If a vulnerable release is selected, settings loading could expose configuration or file-handling risks.

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

The unpinned pydantic-settings package has at least one known advisory, so the security posture of deployed environments is unverifiable from this manifest. If a vulnerable version is installed, secrets-loading behavior could become unsafe.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

python-dotenv is also specified with only a minimum version, so deployments may silently consume later releases with security regressions. Because dotenv tooling can interact with local files and environment configuration, vulnerable versions may have outsized operational impact.

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

python-dotenv has known advisories, and the absence of version pinning means a vulnerable release could be installed without visibility from the manifest. Since dotenv libraries may read or modify local configuration files, vulnerable versions can affect confidentiality or integrity of deployment settings.

Content

No source excerpt is available for this finding.