Back to skill

Security audit

骰子滚动服务

Security checks for vulnerabilities and agentic risk

Overview

This dice-rolling skill asks for and stores a third-party API key and sends requests to a remote service, with leftover unrelated exam-service code, so it needs review before installation.

Install only if you are comfortable giving this publisher an XBY API key, having that key saved in a local .env file, and sending dice requests to xiaobenyang.com. A normal dice roller should be able to work locally, so prefer a version that removes API-key storage, removes gaokao/exam-service leftovers, and limits the code to a fixed dice function.

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)

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill advertises a simple dice-rolling function but exposes undeclared capabilities to read environment data, read/write local files, and make network requests. Those capabilities materially expand the trust boundary and can enable secret collection and persistence behavior that users would not expect from a local dice utility.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This is a strong description-behavior mismatch: a dice roller should not need a third-party API, local secret storage, or generic API calling infrastructure. Such mismatch is dangerous because it can mislead users into granting secrets and permissions under a benign pretext, increasing the chance of data exfiltration or abuse.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
The document shifts from a simple dice service to a workflow centered on obtaining an API key and routing requests to external APIs. In context, this makes the skill more dangerous because the stated task is trivial to implement locally, so requesting credentials and remote access is disproportionate and suspicious.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
References to search_schools/gaokao behavior inside a dice-rolling skill indicate copy-paste residue or hidden scope beyond the declared function. This inconsistency suggests the skill may invoke unrelated tooling or services, which undermines trust and can mask unintended data handling or off-purpose actions.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
Collecting and persisting an API key for a dice roller is unnecessary on its face and increases the risk of secret exposure, especially when stored in a local .env file. The mismatch between low-risk functionality and sensitive credential handling makes this more concerning than it would be in a genuinely API-dependent skill.

Intent-Code Divergence

Medium
Confidence
93% confidence
Finding
The statement that 'code only calls APIs' conflicts with the declared dice-service purpose and implies the skill is primarily a remote API wrapper rather than a local dice utility. That discrepancy expands the operational risk because user inputs may be transmitted externally despite the benign framing of the skill.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The file implements a generic upstream MCP invocation wrapper that accepts arbitrary `tool_name`, `mcp_id`, and `params`, rather than enforcing a dice-only interface. In a skill advertised as simple dice rolling, this expands the effective capability to remote tool execution, enabling misuse, hidden data egress, or invocation of unintended upstream actions if higher-level inputs are attacker-controlled.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
The request headers directly embed caller-supplied `func` and `mcpid`, allowing this component to invoke arbitrary upstream MCP tools over the network. Because the stated purpose is dice rolling, this mismatch in capability makes the skill more dangerous: any prompt or wrapper bug that passes untrusted values can turn a benign game utility into a general remote action proxy.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The file claims to belong to a dice-rolling service, but this code persists and manages an unrelated '高考' service API credential in .env and process environment state. That mismatch is a strong indicator of repurposed or hidden functionality, and it creates a path for credential collection and long-term storage that is unnecessary for a dice tool.

Intent-Code Divergence

High
Confidence
97% confidence
Finding
The class docstring identifies this as configuration for a different product ('小笨羊高考Skill'), directly conflicting with the declared dice-rolling purpose. In security review, this kind of identity mismatch is a red flag for hidden capability, code reuse without review, or intentional concealment of the module's true purpose.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The code explicitly reads .env and environment variables to extract an API key, which is not required for a simple dice-rolling tool. In this context, secret-loading behavior is suspicious because it broadens access to credentials and may enable exfiltration or unauthorized upstream API use.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The function writes the supplied API key into .env with no user-facing consent flow, warning, or secure-storage handling. Persisting secrets in plaintext project files increases the risk of accidental disclosure through source control, backups, logs, or other local access.

Credential Access

High
Category
Privilege Escalation
Content
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")
Confidence
96% confidence
Finding
This code manually opens .env and searches specifically for XBY_APIKEY, which goes beyond ordinary configuration loading and targets a credential for an unrelated service. In the context of a dice skill, that constitutes unnecessary credential access and strongly suggests hidden or repurposed functionality.

Credential Access

High
Category
Privilege Escalation
Content
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():
Confidence
96% confidence
Finding
The existence check is part of a manual workflow to read credentials from a local secret file for an unrelated API. In this skill context, it contributes to unauthorized credential access because the file's declared purpose does not justify inspecting .env for such secrets.

Credential Access

High
Category
Privilege Escalation
Content
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
Confidence
97% confidence
Finding
Reading XBY_APIKEY from the environment and assigning it into application state accesses a sensitive credential unrelated to the advertised dice-rolling use case. This expands secret exposure in memory and may facilitate downstream misuse of the credential.

Credential Access

High
Category
Privilege Escalation
Content
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()
Confidence
95% confidence
Finding
This function is explicitly designed to save an API key into .env, enabling plaintext local storage of a sensitive secret. Even absent exfiltration, this is insecure secret handling and is especially unjustified for a dice utility.

Credential Access

High
Category
Privilege Escalation
Content
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()
Confidence
95% confidence
Finding
The setter function normalizes and persists the API key, making secret storage a supported runtime feature of the skill. Supporting credential management in a module whose declared purpose is unrelated increases the risk of misuse and accidental exposure.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
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 pull in different packages over time. This increases supply-chain risk and can unexpectedly introduce vulnerable or incompatible versions, especially in environments without a lockfile.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
Confidence
95% confidence
Finding
Using `pydantic>=2.7.0` allows future unreviewed versions to be installed, which weakens reproducibility and can introduce security regressions or breaking behavior. While not immediately exploitable by itself, it is a real supply-chain hygiene issue.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
Confidence
95% confidence
Finding
The package `pydantic-settings>=2.2.0` is unpinned, so deployments may resolve to different versions over time. That makes security posture and runtime behavior unpredictable and increases supply-chain exposure.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
Confidence
96% confidence
Finding
`python-dotenv>=1.0.1` permits automatic installation of future versions without review, reducing build determinism and increasing the chance of pulling a compromised or vulnerable release. This is a genuine dependency-management weakness even if exploitation is indirect.

Known Vulnerable Dependency: requests==2.31.0 — 3 advisory(ies): 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); CVE-2026-25645 (Requests has Insecure Temp File Reuse in its extract_zipped_paths() utility func)

Low
Category
Supply Chain
Confidence
91% confidence
Finding
The requirement allows `requests` 2.31.0, a version with published advisories, and an environment resolving to that version would inherit those issues. In this dice-rolling skill, risk depends on whether the code actually uses affected `requests` features, but including a known-vulnerable version in the allowed range is still a real supply-chain exposure.

Known Vulnerable Dependency: python-dotenv==1.0.1 — 1 advisory(ies): CVE-2026-28684 (python-dotenv: Symlink following in set_key allows arbitrary file overwrite via )

Low
Category
Supply Chain
Confidence
88% confidence
Finding
The dependency range permits `python-dotenv` 1.0.1, which has a published advisory involving symlink following in `set_key`; if the skill or its tooling invokes that functionality on attacker-influenced paths, it could lead to arbitrary file overwrite. The dice service context makes this less dangerous than a file-management tool, but the vulnerable version is still unnecessarily exposed.

Static analysis

No suspicious patterns detected.