Back to skill

Security audit

高考志愿

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Gaokao admissions helper, but it stores the user’s API key in a local .env file and can send that key to a configurable API endpoint, so it needs review before installation.

Install only if you are comfortable giving this skill a XiaoBenYang API key, having that key stored in a local plaintext .env file, and sending admissions-query details to the upstream service. Prefer using a low-privilege or revocable API key, check .env file permissions, and avoid running it in workspaces where .env may be committed, shared, synced, or modified by untrusted parties.

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

Plaintext API Key Storage and Credential Exfiltration Through a Configurable API Endpoint

Content
View full analysis

Vulnerability Details

File Location: scripts/config.py:11-20, scripts/config.py:44-61; scripts/call_api.py:51-79
Vulnerability Type: Plaintext credential storage and unsafe endpoint configurability
Risk Level: Medium

Vulnerable Code

scripts/config.py:11-20:

python
model_config = SettingsConfigDict(
    env_prefix="XBY_GAOKAO_",
    env_file=".env",
    env_file_encoding="utf-8",
    extra="ignore",
)

# API configuration
base_url: str = "https://mcp.xiaobenyang.com"
mcp_id: str = "1820705335657482"
api_key: str = ""

scripts/config.py:44-61:

python
def save_api_key_to_env(api_key: str) -> bool:
    """Store the API key in the .env file."""
    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

scripts/call_api.py:51-79:

python
url = f"{settings.base_url}/api"
mcp_id = mcp_id or settings.mcp_id

api_key = get_api_key()
if not api_key:
    raise UpstreamError("API密钥未设置,请先调用 set_api_key()")

headers = {
    "XBY-APIKEY": api_key,
    "func": tool_name,
    "mcpid": mcp_id,
    "Content-Type": "application/json",
}

# data = {k: str(v) if v is not None else "" for k, v in params.items()}

t0 = time.time()
try:
    resp = self._session.post(
        url=url,
        headers=headers,
        data=json.dumps(params),
     
...[truncated 2862 chars]
Remediation
View remediation

Remediation Suggestions

  1. Make the production API endpoint immutable in normal operation, or validate it against an exact allowlist before attaching credentials. Require HTTPS and verify that the normalized hostname is exactly mcp.xiaobenyang.com.
  2. If custom endpoints are required for development, separate development credentials from production credentials and require an explicit trusted configuration mode. Never forward a production key to an arbitrary configured host.
  3. Store the API key in an operating-system keyring, managed secret store, or Agent-provided secret facility instead of a workspace file.
  4. If .env storage is unavoidable, create the file atomically with owner-only permissions such as 0600, verify existing file ownership and permissions before writing, and reject symlinks.
  5. Ensure .env is excluded from version control, packaging, logs, backups, support bundles, and shared archives. Provide a .env.example containing placeholders only.
  6. Avoid retaining the key in more locations than necessary. Do not copy it into the process environment unless required, and provide a supported mechanism to revoke or remove a stored key.
  7. Add automated tests confirming that credentials are never sent when the URL has an unapproved scheme, hostname, port, user-information component, or redirect destination.
  8. Disable cross-origin redirects for authenticated API requests, or strip the credential header before any redirect is followed.
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 (23)

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
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 32)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
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 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
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
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
93% confidence
Finding

This function explicitly persists the API key into .env, creating durable local storage of a secret for a skill whose stated purpose does not require credential persistence. In context, that makes the behavior more concerning because an educational admissions tool should not silently retain secrets on the user's filesystem, increasing the blast radius of any local compromise or accidental file exposure.

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 declares operational capabilities that imply access to environment variables, file read/write, and networked API calls, but it does not define any explicit tool scope or permission boundaries. In practice this increases the blast radius of the skill: it handles secrets (API keys), writes configuration, and can reach external services without a least-privilege declaration, making accidental secret exposure or unintended capability use more likely.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The skill is explicitly framed as a '全国高考志愿填报助手' and all instructions, parameters, and examples are fixed to Chinese-language Chinese-gaokao usage without offering any user language or locale choice. Under the stated policy, forcing a specific language or locale without opt-in is a natural-language policy violation unless the constraint is clearly documented and justified as region-specific.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
82% confidence
Finding

This code retrieves a credential via get_api_key() and sends it in the XBY-APIKEY request header during an outbound HTTP call. While the function names imply API usage, the file contains no confirmation prompt or explicit user-facing warning/comment that credentials and request parameters will be transmitted to an upstream service.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The code modifies local configuration state by rewriting .env with a credential, which exceeds the user-visible functionality of an admissions-query skill. That mismatch matters because users may not expect a read-only informational tool to alter local files and retain secrets, creating stealthy persistence of sensitive data.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill persists a sensitive API key into a local .env file even though the stated purpose is gaokao data lookup and recommendation. Storing credentials on disk expands exposure to other local processes, accidental commits, backups, or later exfiltration, and the code offers no clear necessity, protection, or minimization for this behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The API key is written to .env without any user-facing warning, confirmation, or indication that it will be stored persistently. This is dangerous because users may provide a secret for one session but unknowingly leave it recoverable on disk long after use.

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 range (requests>=2.31.0) rather than an exact version, which makes builds non-reproducible and can silently introduce vulnerable or incompatible releases later. In a security context, this is a real supply-chain hygiene issue because the deployed version cannot be reliably audited from the manifest alone.

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

requests has multiple known advisories, and because the manifest does not pin a specific version, it is impossible to verify from this file whether a safe or affected release will be installed. The risk is contextual rather than proof of active compromise, but it is still a real vulnerability-management gap.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

pydantic>=2.7.0 is unpinned, so future installs may resolve to different versions with different security properties. This weakens reproducibility and makes it harder to determine whether the environment is exposed to known issues.

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

pydantic has known advisories, but the unpinned requirement prevents determining whether the resolved version is vulnerable. This ambiguity is dangerous because a fresh install or rebuild could select an affected release without any code changes.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

Using pydantic-settings>=2.2.0 allows any newer release to be installed, including versions later found vulnerable or behaviorally incompatible. Even without proof of current exploitation, this is a genuine supply-chain risk because version selection is left open-ended.

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

pydantic-settings is associated with at least one advisory, and the open-ended version specifier means the actual installed release cannot be validated from the manifest. If this package is used to load secrets or configuration, the uncertainty around version safety becomes more relevant.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

python-dotenv>=1.0.1 is not pinned, so installations may pick up later versions with undisclosed regressions or known flaws. This creates avoidable uncertainty in the security posture of the skill's runtime environment.

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 manifest does not constrain installation to a verified safe release. If the skill uses .env file manipulation or loading in environments with attacker-controlled paths, an affected version could increase exposure.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The class docstring is written in Chinese, and other user-facing strings in this file are also Chinese-only, indicating an implicit language constraint. The file does not offer a language/locale choice or explain that the skill is intentionally region-specific, which can violate language/locale policy requirements.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The file's docstrings, comments, and user-visible print message are written only in Chinese, which imposes a specific language without any opt-in or alternative. Under the policy, locale or language constraints should be optional or clearly justified.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The settings initialization reads an API key from .env and from the XBY_APIKEY environment variable, which is sensitive credential access. The code contains no user-facing notice, logging, or warning that credential material will be loaded from these sources.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

This code file repeatedly sends user-supplied data such as province, score, school, major, and category to an external API via call_api, but the file provides no confirmation prompt, user-facing logging, or explicit warning about that transmission. Because these inputs can reflect a user's educational profile and preferences, the network transmission should be disclosed somewhere visible to the user.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.