Back to skill

Security audit

国际象棋FEN验证可视化服务

Security checks for vulnerabilities and agentic risk

Overview

This skill is presented as a chess FEN visualizer, but it requires and persists an unrelated API key and sends requests to a configurable remote MCP service.

Review before installing. This skill asks users for an XBY API key, stores it in the project .env file, and sends FEN input plus that key to a remote service. Install only if you trust the XiaoBenYang service and the publisher, are comfortable with local plaintext credential storage, and can control the working directory and environment variables used to run it.

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 (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/call_api.py:54
Finding

API Credential Disclosure Through a Configurable Upstream Endpoint

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/config.py:43
Finding

Plaintext API Key Persistence Without Explicit File-Security Controls

Content
View full analysis
bool: """Persist the API key to 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 API key is written in plaintext to a relative `.env` path using `Path.write_text`. The implementation does not explicitly create or enforce restrictive permissions such as mode `0600`, does not verify that the target is a regular file owned by the current user, and does not reject symbolic links. For a newly created file, effective permissions depend on the process umask. In a permissive or shared environment, another local account or process may be able to read the key. Because the path is relative to the current working directory, execution from an unexpected or attacker-influenced directory can also place the credential somewhere unintended. The check and subsequent write are not performed atomically. If an attacker can modify the working directory, a prepared `.env` symbolic link can cause the code to follow that link and write API-key content to another file writable by the victim process. Exploitation therefo ...[truncated 1560 chars]
Remediation
View remediation
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)

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

The skill claims to visualize chess positions but documents reading/writing .env, persisting XBY_APIKEY, and configuring unrelated remote service parameters. This creates unnecessary credential handling and persistent state for a task that should be self-contained, increasing the risk of secret collection, accidental leakage, and misuse of the host environment.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill claims to visualize chess positions but documents reading/writing .env, persisting XBY_APIKEY, and configuring unrelated remote service parameters. This creates unnecessary credential handling and persistent state for a task that should be self-contained, increasing the risk of secret collection, accidental leakage, and misuse of the host environment.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The SKILL.md explicitly requires collecting an API key and using an external API even though FEN validation/visualization does not need either. In context this is a strong red flag for credential harvesting or disguised remote-service invocation, made more dangerous because the instructions tell the agent to ask the user for the secret and persist it.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

该文件实现的并不是受限于FEN校验/棋盘可视化的专用逻辑,而是一个可向外部“小笨羊MCP API”发送任意工具名、任意参数和可选mcp_id的通用代理调用器。对于一个宣称仅提供国际象棋FEN验证可视化的技能,这种通用外呼能力明显超出最小权限范围,可被上层代码复用为任意外部工具调用与数据转发通道,扩大数据外泄、越权功能调用和隐蔽能力漂移的风险。

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 materially inconsistent with the declared chess FEN validation/visualization purpose and instead implements configuration for an unrelated Gaokao service plus API-key handling. In an agent skill, this kind of scope mismatch is dangerous because it can mask hidden data flows, unexpected remote dependencies, or credential collection behavior that users would not reasonably expect from a local chess utility.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The docstring explicitly identifies the code as configuration for a different Gaokao skill, directly contradicting the manifest's chess-service description. In a security review, this mismatch is a strong indicator of repurposed or deceptive code, making any credential or network behavior significantly more suspicious.

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

The code forcibly reads the .env file and extracts a specific API key outside the normal settings abstraction, adding bespoke secret-access logic unrelated to the stated chess purpose. In context, this increases suspicion because the skill is expected to validate FEN locally, not inspect and harvest credentials from local configuration files.

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

Opening and reading .env directly is a form of local secret access, and in this skill context it is unnecessary for a chess FEN utility. Because the file's functionality is mismatched with the manifest, this direct file access is more dangerous than it would be in a legitimately networked service.

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

The environment variable override continues the secret-access pattern by pulling XBY_APIKEY into runtime state for an unrelated skill. On its own this is standard practice, but within a purported local chess tool that already shows deceptive scope mismatch, this contributes to unjustified credential handling and raises the risk of 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

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

Persisting API credentials to .env and copying them into the process environment creates long-lived secret exposure unrelated to the chess use case. If the working directory, logs, backups, or repository contents are exposed, the stored key can be recovered and abused to access the associated external service.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
94% confidence
Finding

This function is expressly designed to persist an API key into .env, turning transient secret input into durable local storage. In the context of a chess skill with no clear need for credentials, this behavior creates unnecessary secret exposure and is consistent with collecting or retaining credentials beyond user expectations.

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

The skill declares no explicit tool scope or permissions while its documented/project capabilities include environment access, file read/write, and outbound network usage. In an agent setting this broad, undeclared capability boundary increases the chance of unintended secret access, persistent modification, or exfiltration because reviewers and users cannot accurately understand what the skill may do.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The entire skill description and operating instructions are written only in Chinese, and the workflow provides no opt-in or alternative language behavior for users. Under the language/locale policy, a skill should not force a specific language unless it offers a choice or clearly documents a justified regional constraint.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The workflow references unrelated tooling such as search_schools, indicating the skill may be repurposed from another domain without proper review. This kind of cross-domain copy/paste error undermines trust in the skill's behavior and can cause the agent to invoke unintended functions or send user data to the wrong backend.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The project structure and return-value handling describe a generic API-backed skill (call_api.py, config management, raw remote JSON) instead of a local chess renderer. This discrepancy suggests the skill may expose more capabilities than advertised and encourages direct presentation of remote raw data, which can leak sensitive content or propagate untrusted output into the agent conversation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

代码会把调用参数通过HTTP发送到外部服务,并同时在请求头中附带API密钥,但从该实现看不到任何用户侧提示、确认或最小化发送机制。若上层把用户输入、上下文或敏感内容放入params,此技能会在不透明的情况下将数据出站到第三方服务,造成隐私泄露和凭证使用边界不清的问题。

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The presence of base_url, mcp_id, and api_key fields introduces remote-service and credential dependencies that are not justified by the advertised local chess functionality. This expands the attack surface by enabling outbound connections and secret handling where users would expect simple local processing only.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The function silently writes the supplied API key into a local .env file without any user-facing confirmation, warning, or disclosure. This can cause users or operators to unknowingly leave credentials on disk where they may later be committed, exfiltrated, or read by other local processes.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

The dependency declaration uses a lower-bound constraint only (requests>=2.31.0), which permits installation of many different future versions and prevents reproducible builds. This increases supply-chain risk because a later vulnerable or incompatible release could be resolved without review, and the separate advisory signal for requests makes that uncertainty more relevant.

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

The manifest does not pin requests, and the package has multiple known advisories across versions, so it is impossible to verify from this file whether the deployed version is affected. In a network-capable MCP service, unresolved requests version ambiguity raises risk because HTTP client flaws can affect confidentiality or request handling if this library is used.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

pydantic>=2.7.0 is unpinned, so deployments may resolve to different versions over time, including versions with known defects or security issues. In an MCP service that validates user-provided input, dependency behavior matters directly, so non-reproducible resolution is a genuine supply-chain weakness.

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

pydantic has known advisories in some releases, but the unpinned requirement prevents determining whether the installed version is safe. Given this service's stated role in validating FEN input, a vulnerable validation library could be more relevant than in a passive utility because attacker-controlled input is expected.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

pydantic-settings>=2.2.0 allows arbitrary newer versions to be installed, making the build non-deterministic and complicating assurance that a safe version is used. Because settings libraries often load environment and secrets-related data, version uncertainty can expose the service to configuration-handling flaws.

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