Back to skill

Security audit

米游社工具

Security checks for vulnerabilities and agentic risk

Overview

This skill is a real MiHoYo account automation tool, but it handles reusable account credentials, proxy routing, account linking, and automated redemption in ways users should review carefully before installing.

Install only if you trust the operator and host environment with full MiHoYo session cookies. Avoid using the proxy feature unless the proxy provider is trusted, expect account cookies and phone/session data to be stored locally in plaintext, and be cautious with account linking and redemption commands because they can copy access or spend points without a strong confirmation flow.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (5)

T09 · Insecure Skill Coding Practices

Error
Location
plugin.py:885
Finding

Unrestricted Global Proxy Configuration Enables SSRF and Cross-User Authentication Traffic Hijacking

Content
View full analysis
str: """设置代理 API 地址""" import json from pathlib import Path config_file = Path(__file__).parent / "data" / "proxy_config.json" config = {} if config_file.exists(): try: with open(config_file, "r", encoding="utf-8") as f: config = json.load(f) except Exception: pass config["api_url"] = url config["last_fetch_time"] = 0 config["fetch_count_hour"] = 0 config["hour_start"] = 0 config_file.parent.mkdir(parents=True, exist_ok=True) with open(config_file, "w", encoding="utf-8") as f: json.dump(config, f, ensure_ascii=False, indent=2) ``` ```python # src/sms_login.py:54-94 def _get_proxy() -> str: config = _load_proxy_config() api_url = config.get("api_url", "") if not api_url: return "" now = time.time() max_per_hour = config.get("max_per_hour", 20) cooldown = config.get("cooldown_seconds", 30) last_fetch = config.get("last_fetch_time", 0) if now - last_fetch < cooldown: return "" hour_start = config.get("hour_start", 0) if now - hour_start > 3600: config["hour_start"] = now config["fetch_count_hour"] = 0 if config.get("fetch_count_hour", 0) >= max_per_hour: return "" try: import urllib.request req = urllib.request.Request(api_url, method="GET") with urllib.reques ...[truncated 2709 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/qr_login.py:113
Finding

QR Authentication Ticket Is Disclosed to an Unrelated Third-Party QR Service

Content
View full analysis
str: """将 URL 转为二维码图片 URL(使用 pwmqr.com API)""" import urllib.parse encoded = urllib.parse.quote(url, safe='') return f"https://www.pwmqr.com/qrcodeapi/?size={size}x{size}&data={encoded}" ``` ```python # plugin.py:403 qr_img_url = qrcode_to_image_url(qr_url) ``` ```python # plugin.py:521 qr_img_url = qrcode_to_image_url(qr_url) ``` The source of the sensitive URL includes a login ticket: ```python # src/qr_login.py:99-103 url = data["data"]["url"] from urllib.parse import urlparse, parse_qs ticket = parse_qs(urlparse(url).query).get("ticket", [None])[0] return True, url, ticket, device ``` ### Technical Analysis The complete MiHoYo QR-login URL is URL-encoded into the query string sent to `www.pwmqr.com`. The URL contains the QR login ticket used to poll and identify the authentication session. This external QR provider is unrelated to the official MiHoYo authentication endpoints and does not need access to the ticket. Messaging applications, link-preview services, browsers, or the user may request the generated image URL, causing the complete ticket-bearing login URL to be transmitted to and potentially logged by the third party. The transmission is not required for declared functionality because the project already includes support for local QR generation through the `qrcode` package. ### Attack Path 1. A user starts QR login. 2. MiHoYo returns a login URL containing a session ticket. 3. `qrcode_to_image_url()` embeds the entire URL into a third-party request query. 4. The Skill sends the generated Markdown image link to the user. 5. A browser, messaging client, or preview service requests the `pwmqr.com` URL. 6. The QR provi ...[truncated 750 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/store.py:32
Finding

Reusable Authentication Tokens and Phone Numbers Are Persisted in Plaintext

Content
View full analysis
bool: data = load_accounts() user_data = data.setdefault(user_id, {"accounts": []}) accounts = user_data["accounts"] for acc in accounts: if acc["uid"] == uid: acc["nickname"] = nickname acc["cookies"] = cookies acc["games"] = games save_accounts(data) return False accounts.append({ "uid": uid, "nickname": nickname, "cookies": cookies, "games": games, }) save_accounts(data) return True ``` ```python # plugin.py:337-343 save_sms_session(user_id, { "step": "await_captcha", "phone": phone, "action_type": result.get("action_type", "login"), "device_id": result.get("device_id"), "device_fp": result.get("device_fp"), }) ``` ```python # src/store.py:207-213 def save_sms_session(user_id: str, session: dict): """保存短信登录会话""" _ensure_dir() sessions = _load_sms_sessions() session["created_at"] = session.get("created_at", time.time()) sessions[user_id] = session with open(SMS_SESSIONS_FILE, "w", encoding="utf-8") as f: json.dump(sessions, f, ensure_ascii=False, indent=2) ``` ### Technical Analysis The account store writes the complete cookie dictionary to `data/accounts.json`. That dictionary can include reusable credentials such as `stoken`, `stoken_v2`, `cookie_token`, `ltoken`, and related account identifiers. SMS l ...[truncated 1565 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
channel.py:25
Finding

Error Logging Can Persist Cookie Tokens, Phone Numbers, and Verification Codes

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
src/store.py:255
Finding

Weak and Reusable Link Codes Can Grant Unauthorized Access to Stored Accounts

Content
View full analysis
str: """ 生成用户识别码(6位字母数字) 用于跨平台账号绑定 """ import random import string _ensure_dir() codes = _load_link_codes() code = ''.join(random.choices(string.ascii_uppercase + string.digits, k=6)) codes[code] = { "user_id": user_id, "created_at": time.time(), } with open(LINK_CODES_FILE, "w", encoding="utf-8") as f: json.dump(codes, f, ensure_ascii=False, indent=2) return code ``` ```python # src/store.py:282-301 def verify_link_code(code: str) -> Optional[str]: codes = _load_link_codes() code_data = codes.get(code.upper()) if not code_data: return None if time.time() - code_data.get("created_at", 0) > 600: codes.pop(code.upper(), None) _save_link_codes(codes) return None return code_data.get("user_id") ``` ```python # src/store.py:443-483 def merge_user_accounts(source_user_id: str, target_user_id: str) -> bool: data = load_accounts() source_accounts = data.get(source_user_id, {}).get("accounts", []) target_accounts = data.get(target_user_id, {}).get("accounts", []) if not source_accounts: return False for src_acc in source_accounts: src_uid = src_acc["uid"] merged = False for tgt_acc in target_accounts: if tgt_acc["uid"] == src_uid: merged_cookies = {**tgt_acc.get("cookies", {}), **src_acc.get("cookies", {})} merged_games = src_acc.get("games", []) or tgt_acc.get("games", []) tgt_acc["cookies"] = merged_cookies tgt_acc["games"] = merged_games tgt_acc["nickname"] = ...[truncated 3101 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (43)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The public description understates several sensitive capabilities, including scheduled redemption, proxy configuration, cross-platform account linking, and cron-driven bulk actions across bound users. When a skill manages accounts, tokens, and automated redemption, incomplete disclosure materially increases the risk of users or platform operators authorizing behavior they did not expect.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The public description understates several sensitive capabilities, including scheduled redemption, proxy configuration, cross-platform account linking, and cron-driven bulk actions across bound users. When a skill manages accounts, tokens, and automated redemption, incomplete disclosure materially increases the risk of users or platform operators authorizing behavior they did not expect.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

cmd_set_proxy accepts an arbitrary user-supplied URL and persists it as proxy configuration without validation, authorization, or trust restrictions. In a plugin handling SMS login, QR login, and cookies, this can enable traffic interception, request manipulation, credential exposure, or redirection through attacker-controlled services.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The exchange flow performs a purchase-like redemption using user authentication and may include a saved address ID, but there is no in-file confirmation, spending limit, or second-factor style safeguard. In a skill context with access to cookies and address data, this could silently consume a user's points and cause unwanted physical-item fulfillment or digital redemption.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

This code transmits the login URL and ticket to a third-party QR service without any user-facing disclosure in the module. Because the QR encodes a login authorization flow, sharing it externally creates an avoidable credential exposure path and increases the chance of account takeover if the URL is intercepted or retained.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
90% confidence
Finding

The module programmatically exchanges a scanned login result for a full cookie set, including stoken, cookie_token, and ltoken, which are highly sensitive session credentials. In the context of a login/binding plugin this behavior is functionally expected, but without explicit user warning, consent, and secure downstream storage/handling, it materially increases the risk of credential misuse or theft elsewhere in the skill.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code exchanges stoken for broader session cookies and places sensitive session material directly into request headers and cookie strings. While sending tokens to the legitimate service is functionally necessary, in this skill it becomes dangerous because the same module supports dynamic proxying, meaning these high-value tokens may be exposed to intermediary infrastructure and silently expanded into more privileged cookies.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code dynamically fetches proxy endpoints from a local configuration/API and then routes SMS-login traffic and token-related requests through those proxies. That traffic includes encrypted phone numbers, SMS login requests, cookies, and session tokens; a proxy operator can observe metadata, headers, cookies, and potentially modify or replay requests, creating a real credential/session interception risk without any user disclosure or trust boundary validation.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

save_accounts persists account records, including cookies, in plaintext JSON on disk. In this plugin, cookies include sensitive tokens like stoken, cookie_token, and account identifiers, so disclosure of the file to another local user, backup system, or compromised process can lead to replay and account compromise.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

merge_user_accounts copies cookies, nicknames, and game data from one user ID to another, effectively sharing authenticated account access. Without an explicit, enforced confirmation and strong ownership verification, any weakness in the surrounding link-code flow can turn this into cross-user credential transfer and unauthorized account access.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

This duplicate implementation repeats the same sensitive cross-user merge behavior, increasing the chance of inconsistent fixes and leaving multiple code paths that can transfer authentication cookies between users. Duplication amplifies the risk because one copy may be patched while another remains exploitable.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The README explicitly advertises cross-platform sharing of 米游社 account data and local storage of account-related files, but does not clearly warn users what sensitive data is stored, who can access it, how long it is retained, or the risks of linking Telegram and QQ identities. In an account-automation skill handling login methods, cookies, and tokens, missing privacy and sensitive-data handling disclosure increases the chance of inadvertent credential exposure or unauthorized account linking.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README instructs users to configure a mobile proxy/IP pool specifically to bypass SMS frequency limits, but provides no warning that this routes sensitive login traffic through third-party infrastructure and may violate provider controls. Because SMS login involves phone numbers, session state, and authentication flows, using untrusted proxies can expose credentials or enable abuse while normalizing evasion of platform protections.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill instructs the agent to execute local Python code that handles login flows, cookies, storage, logs, and network calls, yet the manifest declares no explicit tool scope or permissions. This creates a trust gap: users and orchestrators cannot clearly see that the skill can read/write files and contact external services, which is especially risky for an account-management plugin handling credentials and tokens.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill can perform account-affecting actions such as sign-ins, forum tasks, goods redemption, scheduled抢购, account linking, and proxy changes, but the description does not adequately warn users about side effects or the possibility of automated recurring actions. This is dangerous because users may trigger purchases/redemptions, alter account state, or enable persistent automation without informed consent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill explicitly supports SMS login, QR login, and direct Cookie submission, including stoken completion, but does not warn users that these are highly sensitive authentication artifacts that can enable full account access. In a chat-driven plugin, normalizing the practice of pasting cookies or handling tokens without strong warnings can lead to credential theft, accidental disclosure in logs, or unsafe retention.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This logger records raw user commands and full error output in plain-language logs, which can directly leak secrets supplied by users. Given the skill handles account binding, login, cookies, and stoken workflows, the danger is elevated because the logged data may include reusable authentication artifacts.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code writes user identifiers, raw command content, and full error text to disk in plaintext. In this skill's context, commands may contain highly sensitive Mihoyo account data such as login details, cookies, or stoken-related material, so log files can become a secondary secret store and enable account compromise if accessed.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

Capturing the full command plus traceback can reveal sensitive user content and internal state in one place, making logs especially valuable to an attacker or insider. In an account-management plugin, this can expose cookies, tokens, phone-related login data, and stack traces that aid further exploitation or lateral movement.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The runtime error logger stores the full traceback together with the full user command, which can expose both sensitive user input and internal implementation details. Because this plugin supports SMS login, cookie login, and stoken completion, exceptions may capture credentials, tokens, session cookies, or debugging data that materially increase compromise risk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Natural-language instructions, commands, prompts, and help text are written in Chinese only, and the command interface expects Chinese trigger phrases for most functionality. There is no indication that users can opt into another language or locale, which may violate a language-choice policy.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The cross-platform account-linking feature allows sharing bound account data between different user IDs, but this capability is not disclosed in the manifest description. In a skill that stores cookies and account bindings, hidden data-sharing paths increase the chance of unauthorized account access or accidental cross-user data exposure.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill exposes proxy configuration commands that are not described in the manifest, creating hidden operational capability beyond the stated Mihoyo-helper scope. Undisclosed network-routing controls can redirect subsequent requests through attacker-controlled infrastructure, which is particularly sensitive in a plugin that handles login cookies and account sessions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

Scheduled exchange reservations are written to local disk without telling users that their reservation metadata will be stored persistently. While the stored fields are not the most sensitive secrets in the system, undisclosed persistence weakens user consent and can expose behavior/history if the host is shared or compromised.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The proxy-setting command persists a user-provided URL to disk but does not clearly warn that this changes future behavior system-wide and survives restarts. Silent persistent configuration is risky here because it alters how sensitive authenticated traffic is routed and may be difficult for users to notice or undo.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.