Back to skill

Security audit

美团C端用户Agent认证工具

Security checks for vulnerabilities and agentic risk

Overview

This Meituan authentication skill does perform SMS login, but it also exposes reusable tokens and includes under-disclosed scheduled coupon automation and unsafe local cache file access.

Install only if you trust this publisher with your Meituan account session. Treat user_token, device_token, phone numbers, and SMS codes as sensitive credentials; avoid running this in shared or logged environments. Review or remove the cron coupon commands and harden the cache CLI path handling before allowing agent-driven execution.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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
Findings (5)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/skill_cache_cli.py:168
Finding

Unrestricted Path Traversal in the Bundled Cache CLI

Content
View full analysis
Path: """Get the shared file path.""" shared_path = self.config.cache_root / ".shared" shared_path.mkdir(parents=True, exist_ok=True) return shared_path / filename ``` ```python def _get_skill_path(self, skill_name: str, subdir: str = "data") -> Path: """Get a Skill directory path.""" if subdir not in self.SUBDIR_TYPES: raise ValueError( f"Unknown subdirectory type: {subdir}. " f"Available: {list(self.SUBDIR_TYPES.keys())}" ) skill_path = self.config.cache_root / skill_name / subdir skill_path.mkdir(parents=True, exist_ok=True) return skill_path def _get_file_path( self, skill_name: str, filename: str, subdir: str = "data" ) -> Path: """Get a complete file path.""" return self._get_skill_path(skill_name, subdir) / filename ``` ```python # shared read shared_read = shared_subparsers.add_parser("read", help="Read shared file") shared_read.add_argument("file", help="File name") # shared write shared_write = shared_subparsers.add_parser("write", help="Write shared file") shared_write.add_argument("file", help="File name") shared_write.add_argument("--content", "-c", required=True, help="File content") # shared delete shared_delete = shared_subparsers.add_parser("delete", help="Delete shared file") shared_delete.add_argument("file", help="File name") ``` ### Technical Analysis The CLI directly joins user-controlled `filename` and `skill_name` values to trusted cache directories. It does not reject absolute paths, `..` components, or symlink destinations, and it does not verify that the resolved result remains beneath the intended c ...[truncated 1529 chars]
Remediation
View remediation
Path: candidate_input = Path(user_path) if candidate_input.is_absolute() or ".." in candidate_input.parts: raise ValueError("Unsafe path") resolved_root = root.resolve(strict=True) candidate = (resolved_root / candidate_input).resolve(strict=False) candidate.relative_to(resolved_root) return candidate ``` 3. Restrict shared filenames to a narrow allowlist, such as `mt_auth_tokens.json`, where possible. 4. Validate `skill_name` against a conservative identifier pattern rather than accepting path syntax. 5. Reject symlinks for sensitive files and parent directories, or use descriptor-relative APIs with no-follow protections. 6. Apply the validation consistently to read, write, append, delete, JSON, and line-oriented operations. 7. Add regression tests for absolute paths, nested traversal, encoded traversal, and symlink escapes. ]]>

T07 · Tool Hijacking and Spoofing

Error
Location
scripts/auth.py:58
Finding

Environment-Controlled Interpreter and Cache CLI Hijacking

Content
View full analysis
Path: """Get the skill_cache_cli.py path, preferring a configured path.""" import os env_path = os.environ.get("SKILL_CACHE_CLI_PATH") if env_path: return Path(env_path) return Path(__file__).parent / "skill_cache_cli.py" def _get_python_exe() -> str: """Get the Python executable path.""" import os env_python = os.environ.get("SKILL_CACHE_PYTHON") if env_python: return env_python return sys.executable CLI_PATH = _get_cli_path() PYTHON_EXE = _get_python_exe() ``` ```python def _cli_call( command: str, subcommand: str = None, args: list = None, raw_output: bool = False ) -> dict: import os args = args or [] cmd = [PYTHON_EXE, str(CLI_PATH), command] if subcommand: cmd.append(subcommand) cmd.extend(args) env = os.environ.copy() env.setdefault("SKILL_CACHE_WORKSPACE", _get_workspace()) try: result = subprocess.run( cmd, capture_output=True, text=True, timeout=30, env=env ) ``` ### Technical Analysis The authentication script trusts `SKILL_CACHE_PYTHON` and `SKILL_CACHE_CLI_PATH` from its inherited environment. These variables determine the executable and script passed to `subprocess.run()` during routine token reads, writes, migrations, and consent-state operations. Although the subprocess is invoked without `shell=True`, that does not prevent this issue: the attacker controls the executable or script path itself. No canonical-path, ownership, permission, or integrity validation is performed before execution. This is particularly sensitive because the substituted program runs during operations involving ...[truncated 1016 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/auth.py:728
Finding

Authentication Credentials Exposed Through Process Arguments and Standard Output

Content
View full analysis
--code ``` ```python if user_token: print(json.dumps({ "success": True, "valid": True, "user_token": user_token, "device_token": device_token, "phone_masked": phone_masked, "check_mode": "local" }, ensure_ascii=False)) ``` ```python result = { "success": True, "user_token": user_token, "device_token": device_token, "phone_masked": phone_masked, "message": "Authentication succeeded; user_token was stored" } if is_new_device: result["device_token_generated"] = True result["hint"] = "First authentication; device_token was generated and persisted" print(json.dumps(result, ensure_ascii=False)) ``` ```python p_verify = subparsers.add_parser( "verify", help="Verify the code and write the Token" ) p_verify.add_argument("--phone", required=True, help="11-digit phone number") p_verify.add_argument("--code", required=True, help="Six-digit SMS code") ``` ### Technical Analysis The verification command accepts the full phone number and one-time SMS code as command-line arguments. Depending on the operating system and execution environment, process arguments may be exposed through process inspection, shell history, Agent telemetry, command logs, or crash diagnostics. The script also emits reusable `user_token` and persistent `device_token` values to standard output in successful status, verification, and token-validation flows. Standard output may be captured by Agent tooling, logs, conversation context, or monitoring systems. This contradicts the instruction in `SKILL.md:290` that `user_token` must not be shown in conversation output. Rel ...[truncated 1141 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/auth.py:486
Finding

Reusable Authentication Token Transmitted in a URL Query Parameter

Content
View full analysis
`. 3. A proxy, gateway, server, or observability component records the complete request target. 4. An attacker or unauthorized operator obtains access to the resulting logs. 5. The attacker extracts and replays the token before it expires or is revoked. ### Impact Assessment Exposure can allow session impersonation and unauthorized use of services that accept the token. The affected scope depends on the token's server-side privileges and lifetime. The request does not transmit the token to an unrelated domain, and TLS verification is enabled, but URL-based transport unnecessarily broadens the credential's exposure surface. ]]>
Remediation
View remediation

T06 · System Persistence

Warning
Location
scripts/auth.py:993
Finding

Undocumented Durable Scheduling Capability Exceeds Authentication Scope

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (20)

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The file presents itself as an authentication utility, but also contains scheduling and automation logic for coupon collection. This mismatch can mislead reviewers and users about the scope of data handling and behavior, reducing informed consent and making it easier to hide unrelated privileged actions in a trusted auth component.

Content

No source excerpt is available for this finding.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

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

python
# 配置环境变量,确保 CLI 能正确探测工作空间
    # 避免依赖 cwd 导致路径不一致的问题
    env = os.environ.copy()
    env.setdefault("SKILL_CACHE_WORKSPACE", _get_workspace())

    try:

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill includes automatic coupon-collection scheduling functionality that is unrelated to basic authentication and can trigger future actions on the user's behalf. In an auth-focused component, this broadens privilege and creates a hidden automation surface that could be abused to perform recurring actions without clear user understanding.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The trigger list includes broad everyday phrases such as login, user authentication, phone verification, get token, switch account, and logout. Overly broad activation terms increase the chance the skill is invoked in unintended contexts, which is especially risky here because the skill handles authentication flows, agreement acceptance state, phone numbers, SMS, and token management.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

文档写明“所有接口均以北京时间(UTC+8)为准”,并要求其他时区“处理所有命令时需将时间转换到北京时间(UTC+8)再使用”。这是明显的语言/locale/时区约束,但未说明该 Skill 仅适用于中国区场景,也未给出用户选择或适用范围说明,构成自然语言层面的 locale policy 问题。

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill documentation minimizes the sensitivity of locally stored authentication data even though it explicitly stores a user login token and a device identifier. Misclassifying bearer tokens and device identifiers as non-sensitive can lead downstream implementers, operators, or users to apply weaker handling, disclosure, logging, backup, or sharing practices than are appropriate.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The document says the file is not uploaded to any server, but the stored token and device identifier are later used in remote API requests for authentication and verification. Even if the whole file is not transmitted verbatim, this wording is misleading and can create a false assurance about data flow, causing users or integrators to misunderstand that credential material is sent to remote services during normal operation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The document instructs persistent local storage of authentication tokens in a predictable file path and allows path control through an environment variable, but it does not warn about credential sensitivity, file permissions, plaintext storage risks, or multi-user/shared-environment exposure. In an agent or sandbox context, this increases the chance of token leakage via overly broad filesystem access, logs, backups, or untrusted path selection.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
86% confidence
Finding

The documented use of shared read/write auth storage indicates deliberate session persistence, which creates a durable authentication surface beyond the immediate run. In the context of an auth skill, persistence is expected, but it remains risky if other local tools or users can read the shared cache.

Content

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

python
调用 mt-ug-ods-skill-cache CLI

    Args:
        command: 主命令(如 auth, shared, read, write 等)
        subcommand: 子命令(如 get, set, list 等)
        args: 额外参数列表
        raw_output: 是否返回原始输出(用于 shared read 等直接返回内容的命令)

Session Persistence

Medium
Category
Rogue Agent
Confidence
86% confidence
Finding

The documented use of shared read/write auth storage indicates deliberate session persistence, which creates a durable authentication surface beyond the immediate run. In the context of an auth skill, persistence is expected, but it remains risky if other local tools or users can read the shared cache.

Content

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

python
调用 mt-ug-ods-skill-cache CLI

    Args:
        command: 主命令(如 auth, shared, read, write 等)
        subcommand: 子命令(如 get, set, list 等)
        args: 额外参数列表
        raw_output: 是否返回原始输出(用于 shared read 等直接返回内容的命令)

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 135)May include surrounding context.

python
env.setdefault("SKILL_CACHE_WORKSPACE", _get_workspace())

    try:
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=30, env=env)
        stdout = result.stdout.strip() if result.stdout else ""

        # raw_output 模式:直接返回原始内容

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill persists authentication data, including user_token and device_token, to local shared storage without a clear user-facing warning at the time of storage. Because these tokens can maintain account access across sessions, silent persistence increases the chance of unintended reuse, cross-tool exposure, or leakage from the workspace.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code sends phone numbers and SMS verification codes to a remote service but does not provide an explicit user-facing disclosure at the point of collection that this sensitive data will be transmitted off-host. In an authentication context this data flow is expected, but lack of clear notice weakens informed consent and can expose users to privacy and trust risks.

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 928)May include surrounding context.

python
# 默认检测 openclaw 命令是否存在
    try:
        result = subprocess.run(
            ["which", "openclaw"],
            capture_output=True,
            timeout=2

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The implementation does not enforce any per-skill authorization boundary: callers can supply arbitrary skill names and read/write/delete files under those skill directories. That makes the documented 'private cache isolation' misleading and enables cross-skill data access if multiple skills or users share the same workspace.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The tool stores shared authentication tokens in plaintext and the CLI prints them directly to stdout via 'auth get' and shared file reads. In multi-agent, logged, or monitored environments, this can disclose live credentials to other components, shell history collectors, CI logs, or users with access to terminal output.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The credential-management CLI paths explicitly emit token values and authentication blobs to stdout with no confirmation, masking, or warning. Since stdout is commonly captured in logs, transcripts, agent traces, and terminal scrollback, this creates a direct secret-exposure channel even during normal use.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
74% confidence
Finding

Natural-language policy issues apply to all file types, including markdown. This file presents all usage instructions in Chinese and does not offer an alternative language or indicate that the locale restriction is intentional or user-selected, which may conflict with a policy against forcing a specific language without opt-in.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The flow says the returned token is valid for 7 days, but earlier documentation states token validity is determined by server-side configuration and should be checked via the token-verify API rather than assumed locally. This is an active contradiction in the documentation about the same token's lifetime.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

Natural-language descriptions, comments, help text, and command guidance are written in Chinese throughout the file, which effectively forces a specific language experience. The file does not indicate that the tool is region-specific or provide any option for users to select another language.

Content

No source excerpt is available for this finding.