Back to skill

Security audit

卡路里追踪服务

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches a calorie-tracking API workflow, but it has review-worthy credential storage and copy-paste inconsistencies from an unrelated gaokao project.

Review this before installing. Only use an API key you are comfortable storing in a local plaintext .env file, avoid shared or committed workspaces, and rotate the key if exposed. The gaokao references should be fixed by the publisher because they make the service identity and intended backend less clear.

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 Persisted in a Plaintext Environment File

Content
View full analysis

Vulnerability Details

File Location: scripts/config.py, lines 44–67
Vulnerability Type: Plaintext sensitive-data storage
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


def set_api_key(api_key: str) -> bool:
    """设置API key并持久化到.env"""
    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 takes an API key supplied by the user and persistently writes it to .env as unencrypted text. Path.write_text() relies on the process environment and current umask when creating the file; the code does not explicitly enforce owner-only permissions. It also does not reject symbolic links or use an atomic, securely created file.

Consequently, the credential may become accessible to other local users or processes with permission to read the project directory. It may also be exposed through backups, workspace archiving, or an accidental source-control commit. If .env is an attacker-controlled symbolic link, the write may target another file writable by the process.

Attack Path

  1. The user supplies an API key as required ...[truncated 1173 chars]
Remediation
View remediation

Remediation Suggestions

  1. Prefer session-only credential handling or an operating-system credential store instead of persistent plaintext storage.
  2. If file-based storage is unavoidable, securely create the file with owner-only permissions (0600) and verify the resulting permissions.
  3. Reject symbolic links and other unexpected file types before reading or writing .env.
  4. Write updates to a securely created temporary file in the same directory, apply restrictive permissions, and atomically replace the destination.
  5. Add .env to .gitignore and relevant packaging or backup exclusion rules.
  6. Avoid printing, logging, or returning API-key values in error messages.
  7. Document credential rotation and revocation procedures so users can invalidate a key after suspected disclosure.
  8. Consider obtaining the key from a secret-management service or inherited environment variable without copying it to disk.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (28)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill is presented as a calorie tracker, but the content shows unrelated references to a gaokao/school-search project and undisclosed sensitive configuration handling such as reading/writing .env and persisting API keys. This mismatch undermines user trust and can conceal privileged behaviors that users would not reasonably expect from the declared purpose.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The file is configured to talk to an unrelated external service instead of the calorie-tracking functionality described in the manifest. In a user-facing agent skill, this is a serious trust and data-flow issue: user requests and credentials may be sent to a service they did not expect, which can result in unauthorized disclosure or misuse of personal data.

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 code explicitly reads the .env file and extracts XBY_APIKEY outside the normal settings abstraction, creating custom secret-loading logic that can bypass expected secret-management controls and increases the chance of mishandling credentials. In the context of a mismatched skill/backend, this makes secret use more suspicious because the key is being force-loaded for an unrelated external service.

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

Opening and reading .env directly is not inherently malicious, but here it is part of manual credential extraction logic for XBY_APIKEY. That pattern expands the attack surface for accidental disclosure and makes secret handling less auditable and less consistent with secure configuration management.

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 is explicitly designed to persist an API key into a local .env file. Storing credentials in project-local plaintext files materially increases exposure risk, especially if the repository is shared, backed up, inspected by other tools, or accidentally committed; combined with the unrelated service configuration, it may also funnel secrets into an unexpected integration.

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

The skill declares no explicit tool scope or permissions despite documented behavior that uses environment access, local file reads/writes, and networked API calls. Missing least-privilege boundaries increases the blast radius if the skill is misused, compromised, or behaves unexpectedly.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill instructs the agent to solicit a user API key and persist it via set_api_key() without transparency about storage location, retention, masking, or consent. Collecting and storing credentials without clear sensitive-data handling creates significant risk of credential exposure, replay, or accidental disclosure through logs, files, or later tool output.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documented tool invocation example calls search_schools, which is unrelated to calorie tracking and suggests copied or incorrect routing instructions. In an agent setting, wrong tool guidance can cause invocation of unintended functions, data leakage, or execution outside the user's expected task scope.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The instruction to directly display result['raw'] is dangerous because backend APIs often echo request metadata, tokens, identifiers, or debugging details. Since this skill also collects API keys and performs network calls, blindly rendering raw responses materially raises the chance of disclosing secrets or internal data to the user or conversation history.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file contains natural-language strings intended for users or operators, such as docstrings and error messages, exclusively in Chinese. This imposes a locale choice without offering an alternative or documenting that the skill is intentionally region- or language-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The exception text shown when the API key is missing is written only in Chinese, which can prevent comprehension for users operating in other locales. The file does not indicate that this language constraint is optional or justified by a region-specific scope.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code performs an HTTP POST to an upstream service using caller-supplied params and includes the API key in request headers. While the module logs success and error events, it does not provide any user-facing warning, confirmation, or explanatory comment/docstring that user or system data may be transmitted off-box.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The function includes Chinese-only natural-language text in its docstring and in the returned failure message. Because no locale selection or opt-in is provided, this is a natural-language policy concern rather than a technical defect.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The configuration clearly targets a different product/domain ('小笨羊高考', XBY_GAOKAO_*, xiaobenyang.com) than the declared calorie-tracking skill. This kind of skill/implementation mismatch is dangerous because it can misroute user data and secrets to an unrelated backend, undermining informed consent and making the true behavior of the skill opaque.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The code persists the API key into a local .env file automatically, without any confirmation, warning, or controls around file permissions and secret storage. This increases the chance of accidental credential exposure through source-control inclusion, local compromise, backups, logs, or shared environments.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The skill description and operational instructions are entirely in Chinese, and there is no statement that users may interact in another language or choose their preferred locale. Under the policy, forcing a specific language without opt-in can be a natural-language policy concern unless the locale restriction is documented and justified.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

项目结构块中使用 xiaobenyang_gaokao_skill/ 作为根目录名,这与当前“卡路里追踪服务”的功能定位明显不一致。虽然这不直接证明代码行为异常,但属于文档层面对技能意图的主动错误描述,容易误导使用者对该技能真实用途的理解。

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 version constraint (requests>=2.31.0) rather than pinning an exact version. This makes builds non-reproducible and can allow installation of an unintended or newly vulnerable release, increasing supply-chain risk.

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

The manifest does not pin the requests version, and the package has multiple known advisories across versions. Because the exact installed release is not constrained, it is impossible to verify from this file alone whether deployment will avoid affected versions.

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 version constraint (pydantic>=2.7.0) instead of an exact pinned version. This can lead to non-deterministic installs and unexpected exposure to vulnerable upstream releases.

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

pydantic has known advisories, but the requirement is open-ended, so the actual installed version cannot be validated as safe. This leaves the project exposed to accidental installation of vulnerable versions and complicates incident response.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

pydantic-settings>=2.2.0 is unpinned, so different environments may resolve to different package versions over time. That weakens reproducibility and can silently introduce a version with security defects or breaking behavior.

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

Because pydantic-settings is not pinned and has at least one known advisory in some versions, the security posture cannot be verified from the manifest. This uncertainty is itself a supply-chain weakness, especially for software that may process environment-based secrets.

Content

No source excerpt is available for this finding.