Back to skill

Security audit

IP情报查询工具

Security checks for vulnerabilities and agentic risk

Overview

The skill is an IP lookup tool, but it stores an API key in a local plaintext .env file and contains mismatched/broken copied instructions that warrant review before installation.

Review before installing. Use only if you are comfortable giving the skill a Xiaobenyang API key, having that key stored in a local plaintext .env file, and sending queried IP data to the configured API endpoint. Prefer setting the key through a secure environment or secret store and avoid using this in shared workspaces until the stale instructions, broken tool definition, and credential-storage handling are fixed.

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

API Key Persisted in an Insecure Plaintext File

Content
View full analysis

Vulnerability Details

File Location: scripts/config.py:41-63
Vulnerability Type: Plaintext credential storage and unsafe secret-file handling
Risk Level: Medium

Vulnerable Code

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
    except Exception as e:
        print(f"Failed to save API key: {e}")
        return False

Technical Analysis

The function persists a user-provided API credential in a plaintext .env file relative to the current working directory. It does not create the file with an explicitly restrictive permission mode, correct permissions on an existing file, reject symbolic links, or perform an atomic replacement.

Consequently, the effective location and security properties of the credential depend on the process working directory, umask, preexisting file permissions, and filesystem state. If .env already has permissive permissions, Path.write_text() does not make it private. If an attacker with local write access can prepare .env as a symbolic link, the code follows that link when reading and writing.

The function also copies the credential into os.environ. Processes spawned after this assignment may inherit the API key even when they do not require access to it, ...[truncated 1604 chars]

Remediation
View remediation

Remediation Suggestions

  1. Prefer an operating-system credential manager or an application-provided secret store instead of plaintext project files.
  2. If file storage is unavoidable, use a dedicated per-user configuration directory rather than the current working directory.
  3. Create the secret file with exclusive creation and mode 0600, and verify that the destination is a regular file owned by the expected user.
  4. Reject symbolic links using platform-appropriate no-follow operations, such as O_NOFOLLOW where available.
  5. Write updates to a securely created temporary file in the same directory, set restrictive permissions, flush and synchronize it, and atomically replace the destination.
  6. Correct the permissions of an existing credential file before reading or updating it, or refuse to use files that are accessible by other users.
  7. Avoid assigning the key to os.environ unless downstream libraries strictly require it. Keep the secret in narrowly scoped application memory instead.
  8. Ensure .env is excluded from source control and document clearly that the key is stored locally and sent to https://mcp.xiaobenyang.com/api.
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 (25)

Tp2

High
Category
MCP Tool Poisoning
Confidence
85% confidence
Finding

Mixing characters from multiple Unicode scripts in a single identifier is a common technique to create visually ambiguous tool names.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The documented behavior does not match the declared IP-intelligence purpose: it includes local .env credential handling, persistent key storage, and residual references to an unrelated gaokao/school-query skill. This mismatch is dangerous because users and reviewers may grant trust or permissions for an IP lookup tool without realizing it also writes secrets locally and contains copy-paste remnants that suggest weak change control.

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

The code explicitly reads the .env file to extract a specific API key, bypassing normal settings abstraction and directly handling secrets in application logic. This increases secret exposure and makes credential handling less auditable, especially in a plugin/skill environment where local file access may be broader than expected.

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

Checking for and reading a local .env file as part of runtime initialization directly accesses a secret-bearing file in the working directory. In this context, that behavior contributes to insecure secret handling because credentials are expected to be present in a predictable plaintext location accessible to local users, tools, or accidental disclosure paths.

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

This function is explicitly designed to save an API key into a local .env file, creating plaintext on-disk secret persistence. In the context of an IP intelligence skill, that increases the chance of credential compromise through local file disclosure, repo inclusion, support bundles, backups, or other workspace consumers.

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

The skill declares no explicit tool scope or permission boundaries even though it is documented as using environment access, file read/write, and network capabilities. In an agent setting, missing least-privilege constraints can let the skill access or persist secrets more broadly than necessary, increasing the blast radius if the skill is misused or compromised.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The workflow example instructs the model to call a school-search function in an IP-intelligence skill, showing that the routing instructions are inconsistent with the claimed purpose. In agent systems, incorrect tool-routing guidance can cause unintended tool invocation, mishandling of user data, or execution of unrelated actions under the wrong trust context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This file contains natural-language strings and docstrings exclusively in Chinese, including user-facing error and status messages such as the API key error and API failure text. The skill does not offer a language choice or document that it is intentionally limited to a Chinese-speaking context, which violates the language/locale policy criteria.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The module implements local persistence of an API key into a plaintext .env file, which expands the secret's exposure surface beyond transient runtime use. In a skill context, storing credentials on disk without explicit disclosure, permissions hardening, or secure secret storage can lead to unintended leakage through backups, source packaging, workspace sharing, or local file reads by other components.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The code adds credential persistence capability that is not necessary for basic IP intelligence lookups, increasing risk without clear functional justification. Unnecessary secret storage is dangerous because it leaves recoverable credentials on disk and may surprise users who expect a query tool, not a credential-writing component.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The function persists the API key to a local .env file and updates the process environment without any user-facing warning, confirmation, or disclosure. Silent credential persistence is risky because users may unknowingly leave secrets in the project directory where they can be committed, archived, or accessed by other local processes and tools.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

文档将项目根目录写为 xiaobenyang_gaokao_skill/,这与当前“IP情报查询工具”的名称和功能明显不符。该类残留会让使用者误解技能实际实现来源与用途,属于文档意图和当前技能内容之间的明显矛盾。

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 (requests>=2.31.0), which allows future installs to resolve to different versions over time. This weakens build reproducibility and can unintentionally introduce vulnerable or breaking releases through the software supply chain.

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 published advisories, and because the manifest does not pin a specific version, it is impossible to verify whether deployed environments are using a fixed or affected release. In a network-facing IP intelligence tool, this matters more because HTTP client behavior may process attacker-controlled URLs, redirects, or credential sources depending on how the library is used elsewhere.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency is specified as pydantic>=2.7.0 without an upper bound or exact pin, so installs are not deterministic. This can result in unreviewed versions being pulled in later, increasing exposure to newly introduced vulnerabilities or incompatible behavior.

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

pydantic has known advisories, but the unpinned requirement prevents verification that installations will avoid affected versions. This is primarily a dependency hygiene issue, though it can become more relevant if the skill validates untrusted API input or configuration data extensively.

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 permits arbitrary newer versions to be installed in future environments. That creates a supply-chain and reproducibility risk because a later vulnerable release could be consumed without an intentional code change.

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

pydantic-settings has an advisory history, and the open-ended version specifier means consumers may install a vulnerable release without realizing it. If the application loads secrets or configuration from the filesystem, affected versions could increase risk depending on the surrounding code paths.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The python-dotenv dependency is not pinned to a specific release, so the resolved version may vary across installations. This increases the chance of silently ingesting vulnerable or behavior-changing versions, which is a common supply-chain hygiene issue.

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

python-dotenv has known advisories, and because only a minimum version is declared, the actual installed version cannot be verified for safety. This is relevant if the skill reads or writes .env files, where vulnerable versions could interact unsafely with filesystem links or environment management.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

Settings 类的文档字符串写的是“小笨羊高考Skill配置”,而当前技能清单名称和用途是“IP情报查询工具”。这不是简单的信息缺失,而是文档直接指向了另一个完全不同的技能领域,容易误导审计者和维护者对代码意图的理解。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The file uses Chinese-only natural-language descriptions in docstrings and comments, such as the class description and API-key persistence messages. Under the language/locale policy, this can be a violation when the skill imposes a specific language without opt-in or documented justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill exposes a Chinese-only function name and Chinese-language docstring text, which imposes a specific language/locale in the skill interface. There is no indication that users can choose another language or that the locale restriction is intentional and justified for a region-specific tool.

Content

No source excerpt is available for this finding.