Back to skill

Security audit

meituan-union-smart-recommendation-skill

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent Meituan shopping-guide purpose, but it asks for account access and makes persistent local/global changes with several under-disclosed security risks.

Review this skill before installing. It is not clearly malicious, but it can authenticate to Meituan, bind and store account-linked media codes, show promotional links, perform background update checks, and modify the global npm environment. Install only if you trust the publisher and are comfortable with those local persistence and dependency-install behaviors.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (4)

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:33
Finding

Mandatory Promotional Link Injection Hijacks Agent Responses

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/qrcode.sh:53
Finding

Unpinned Global NPM Package Installation During QR Generation

Content
View full analysis
/dev/null; then echo "[qrcode.sh] qrcode module is not installed; installing automatically..." >&2 if ! npm install -g qrcode 2>&1 >&2; then echo "QRCODE_SKIP" exit 0 fi NODE_GLOBAL_MODULES="$(npm root -g 2>/dev/null)" if ! NODE_PATH="$NODE_GLOBAL_MODULES" node -e "require('qrcode')" 2>/dev/null; then echo "QRCODE_SKIP" exit 0 fi fi ``` ### Technical Analysis The script installs `qrcode` by package name without an exact version or integrity hash. Consequently, the effective installed code is determined by the NPM registry at execution time rather than by the audited project. The `-g` option changes the user's global Node.js environment. NPM package lifecycle scripts may execute during installation with the privileges of the user running the Skill. This creates a mutable supply-chain execution path and exceeds the permissions required to render a QR code. The installation also occurs automatically during normal authentication instead of being disclosed as a separate dependency-management action requiring approval. ### Attack Path 1. The user begins an authentication flow that invokes `qrcode.sh`. 2. The script determines that the `qrcode` module is unavailable globally. 3. It runs `npm install -g qrcode`. 4. NPM resolves the current package and transitive dependency versions from the configured registry. 5. Package installation or lifecycle scripts execute with the invoking user's privileges. 6. A compromised package, dependency, registry, or NPM configuration can execute arbitrary code and modify the global Node.js installation. ### Impact Assessment ...[truncated 603 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/bind.py:334
Finding

User Token and Media Code Exposed Through Process Arguments

Content
View full analysis
``` The script accepts those values as ordinary process arguments: ```python p_bind = subparsers.add_parser("bind", help="Call the code-binding endpoint") p_bind.add_argument("--token", required=True, help="User token") p_bind.add_argument("--code-word", required=True, help="Media code") args = parser.parse_args() if args.command == "bind": cmd_bind(args.token, args.code_word) ``` ### Technical Analysis Command-line arguments are not a secure secret-transport mechanism. Depending on the operating system and execution environment, they may be visible through: - Process-listing utilities and process metadata. - `/proc` process command-line entries. - Shell history when run manually. - Agent tool-call records and orchestration telemetry. - Debuggers, monitoring agents, or crash reports. The code correctly avoids printing the full token in its own logs, but that protection does not prevent exposure before `bind.py` receives the values. Both the account token and media code remain visible in the process invocation. ### Attack Path 1. The user authenticates and the Agent obtains a valid user token. 2. The user supplies a media code. 3. The Agent constructs the documented `bind.py` command. 4. Both secrets become part of the child process argument vector. 5. A same-host observer, telemetry system, process monitor, or history mechanism records the invocation. 6. The observer recovers the token and code and may replay them against the binding service while they remain valid. ### Impact Assessment This does not independently provide ele ...[truncated 448 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/bind.py:39
Finding

Binding Response Bodies May Be Logged in Plaintext Under a Shared Temporary Path

Content
View full analysis
str: try: config_path = Path(__file__).parent / "config.json" with open(config_path, encoding="utf-8") as f: return json.load(f).get("aiScene", "") except Exception: return "" ``` ```python def write_bind_log(entry: dict): try: _BIND_LOG_FILE.parent.mkdir(parents=True, exist_ok=True) raw = json.dumps(entry, ensure_ascii=False) ai_scene = _load_ai_scene() encrypted = _xor_encrypt(raw, ai_scene) if ai_scene else raw with open(_BIND_LOG_FILE, "a", encoding="utf-8") as f: f.write(encrypted + "\n") except Exception: pass ``` ```python log_entry["response"] = { "http_status": resp.status_code, "body": resp.text[:500], } ``` ### Technical Analysis The binding client records the first 500 characters of every server response. The encryption branch is conditional on `aiScene` being present in `scripts/config.json`. The audited project contains no `config.json`, so `_load_ai_scene()` returns an empty string and the full log record is written as plaintext. The log is placed beneath a predictable system temporary directory. The code does not explicitly create the directory with `0700` permissions or the file with `0600` permissions. Effective access therefore depends on the process umask, pre-existing directory ownership, and platform behavior. The exact contents of the binding service's response are not fully specified. Successful responses include expiration and venue-link data, while error responses may contain additional service details. Logging arbitrary response bodies creates unnec ...[truncated 1337 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (23)

Vague Triggers

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill mandates activation for a very broad set of common consumer requests, including vague phrases like recommendations or everyday food/drug/shopping intents. Overly broad triggering can cause unnecessary collection and processing of user requests, force users into an auth/binding flow unrelated to their actual intent, and increase the chance that external links or background commands are invoked when not strictly needed. In this skill, that risk is amplified because activation can lead to local script execution, token handling, and external service interaction.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The skill description and all required user-facing scripts are written as mandatory Chinese responses, including exact phrases the user must provide such as “同意”. There is no indication that the user may choose another language or that the Chinese-only constraint is an explicitly documented regional requirement.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill includes diagnostic commands that read local auth and binding logs and then instruct the agent to surface findings back to the user. Even if intended for troubleshooting, this expands the skill from venue recommendation into local security-state inspection, increasing the chance that sensitive authentication metadata or behavioral traces are exposed in chat or to an untrusted user. The skill itself warns that logs may contain token-related fields, which confirms the sensitivity.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The section header and constraints describe version checking as a silent, non-blocking background step, yet the output rules explicitly tell the skill to append a visible update prompt with links when a new version exists. This is an active contradiction between the declared intent of the feature and its actual instructed behavior.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
74% confidence
Finding

The skill performs external network requests to GitHub for version checks, which constitutes outbound transmission beyond the core recommendation flow. Although the request appears limited to release metadata, it still discloses that the skill is installed and may reveal user environment characteristics via network metadata, especially because the logic uses reachability to infer whether the user is on an internal or external network. Hidden background transmission is more concerning because it occurs silently and is not clearly consented to in the user-facing flow.

Content

Scanner excerpt · SKILL.md (reported line 697)May include surrounding context.

md
请求 `https://skills.sankuai.com/api/v1/skills?id=59498`,有响应且返回版本信息 → 记为 `platform=friday`,提取远端版本号

2. **降级外网 GitHub**(内网不可达时,说明是外部用户):
   请求 `https://api.github.com/repos/Meituan-Union/Meituan-Union-Smart-Recommendation-Skill/releases/latest`,取 `.tag_name` 作为远端版本号 → 记为 `platform=github`

3. 两者均失败 → 静默跳过,不向用户输出任何内容

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The reset section instructs users to run state-clearing commands that delete authentication, device, and binding state without any explicit warning, confirmation step, or backup guidance. This can cause avoidable loss of local access state and service disruption, especially if users follow the procedure during troubleshooting without understanding that it is destructive.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The trigger examples include very broad, everyday phrases such as asking for food delivery or nearby dining, which can overlap with ordinary user conversation and cause unintended invocation of the skill. In this context, accidental activation is more concerning because the skill initiates account-binding and recommendation flows tied to a Meituan account and media-issued binding code, increasing the chance of confusing or unwanted account-linked actions.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/auth.py (reported line 190)May include surrounding context.

python
"""
    cli_cleared = False
    try:
        result = subprocess.run(
            ["pt-passport", "logout", "--client_id", CLIENT_ID],
            capture_output=True, text=True, timeout=10,
        )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/auth.py (reported line 230)May include surrounding context.

python
# 同时清除 pt-passport CLI 缓存
    try:
        subprocess.run(
            ["pt-passport", "logout", "--client_id", CLIENT_ID],
            capture_output=True, text=True, timeout=10,
        )

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This code file contains natural-language documentation and CLI help/messages entirely in Chinese, describing the tool's purpose and usage without any indication that language selection is optional. The policy explicitly requires flagging language or locale constraints when the skill forces a specific language without user opt-in.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script reads device token material from the user's auth token store in order to derive a decryption key for authentication logs, but it provides no warning, consent prompt, or disclosure that sensitive credential material is being accessed. In a diagnostic tool this may be expected behavior, but silently accessing authentication secrets increases the risk of inadvertent exposure, misuse in shared environments, and operator misunderstanding about what the tool touches.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script decrypts authentication logs and prints the plaintext directly to stdout, including any embedded tokens, login details, or authorization data, without an explicit warning or redaction step. This is dangerous because stdout is often captured by terminals, shell history workflows, CI logs, remote sessions, screen recordings, or support transcripts, turning a local diagnostic action into a broader credential exposure event.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This code accesses a device token from a user auth file and uses it to decrypt binding logs, then later prints the decrypted contents to stdout. Although the script's purpose is diagnostic, there is no explicit warning that running it may reveal sensitive account or operational data in the terminal.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This script automatically sources a user-controlled nvm initialization file and performs a global npm installation from a local tarball without any warning, prompt, or trust verification. In an agent skill context, that behavior can silently modify the host environment, execute install-time package scripts as the current user, and persist changes beyond the skill run, which makes unintended or malicious package execution more dangerous.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script presents itself as a QR generator but also performs a global npm installation of the qrcode package if missing. That hidden side effect expands its privileges and changes the host environment, creating supply-chain and integrity risk that is not justified by a simple rendering helper.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

Auto-installing a global npm package gives the script the ability to modify the system and pull executable code from the package ecosystem at runtime. If the package, its dependencies, registry path, or network environment are compromised, this can lead to arbitrary code execution during installation or later use.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script installs a global package automatically without explicit consent, warning, or an opt-in flag. In an agent or automation context, this is dangerous because it can silently alter shared environments and trigger execution of untrusted install scripts.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The skill documentation forces a single language presentation for all instructions and troubleshooting guidance. Under the stated policy, a language constraint should either be optional for the user or explicitly documented as a justified region-specific requirement.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
75% confidence
Finding

The entire skill terms document is presented only in Chinese and does not offer an opt-in language or locale choice. Under the policy, forcing a specific language without user choice can be a natural-language policy violation unless the locale restriction is clearly documented and justified.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The module stores a persistent device_token in a user-controlled path selected by the XIAOMEI_AUTH_FILE environment variable and also writes authentication activity to a temp-directory log protected only by reversible XOR obfuscation derived from ai_scene and optionally the device_token. This expands the local attack surface around authentication state, can leak tracking or auth-related metadata to other local actors depending on filesystem permissions, and creates security assumptions inconsistent with the docstring's implication that token handling is delegated to pt-passport.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The docstring and all CLI output strings are written in Chinese, which imposes a fixed language on users. The file does not provide an opt-in language selection or explain that the tool is intentionally limited to a Chinese-speaking environment.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The script contains natural-language comments and stderr output in Chinese, including the installation notice, without offering any language choice or documenting a locale-specific scope. This can violate a language/locale policy when skills are expected to be language-neutral or user-selectable.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The stderr message announcing automatic installation is written only in Chinese, which imposes a specific language on users without opt-in. For shared skills, user-facing operational messages should either match documented locale scope or support user choice.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.secret_argv_exposure

Instructions pass high-value credentials through process argv.

Critical
Code
suspicious.secret_argv_exposure
Location
references/DOCTOR.md:97

Instructions pass high-value credentials through process argv.

Critical
Code
suspicious.secret_argv_exposure
Location
SKILL.md:207