Back to skill

Security audit

eleme-food-recommend

Security checks for vulnerabilities and agentic risk

Overview

This Ele.me food recommendation skill has a coherent purpose, but it needs Review because it handles a live account cookie and precise location data in unsafe ways.

Review carefully before installing. Only use it if you are comfortable giving the skill an active Ele.me browser cookie and precise location data. Prefer not to run it on shared machines, avoid pasting real cookies into shell commands, clear or rotate the cookie after testing, and do not use it on untrusted networks unless TLS verification and secret handling are fixed.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/eleme_api.py:14
Finding
TLS Certificate and Hostname Verification Disabled<![CDATA[ ## Vulnerability Details **File Location**: `scripts/eleme_api.py:14-18`, with the insecure context used at `scripts/eleme_api.py:61-62` and `scripts/eleme_api.py:93-94` **Vulnerability Type**: Improper certificate validation **Risk Level**: High ### Vulnerable Code ```python def create_ssl_context(): """创建SSL上下文""" ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE return ctx ``` The resulting context is used for requests containing the authentication cookie: ```python ctx = create_ssl_context() with urllib.request.urlopen(req, timeout=10, context=ctx) as response: data = json.loads(response.read()) return data ``` ### Technical Analysis The custom SSL context explicitly disables both certificate-chain validation and hostname verification. Although the requests use HTTPS, the client does not authenticate that the remote endpoint is genuinely `www.ele.me`. Both `get_nearby_restaurants()` and `get_restaurant_foods()` attach the user's Ele.me cookie to requests made through this context. The nearby-restaurant request also includes the user's latitude and longitude in the URL. Consequently, an attacker capable of intercepting network traffic can present an arbitrary certificate without causing the connection to fail. ### Attack Path 1. The user invokes the `recommend` command while connected through an attacker-controlled or compromised network. 2. The attacker intercepts DNS or network traffic intended for `www.ele.me`. 3. The attacker presents an untrusted certificate for an impersonated endpoint. 4. Because certificate and hostname verification are disabled, the client accepts the endpoint. 5. The client sends the Ele.me session cookie and, for the restaurant request, the user's coordinates to the attacker. 6. The attacker may replay the cookie against Ele.me within the permissions and lifetime of that session. 7. The attacker may also return manipulated API responses, caus ...[truncated 601 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove the custom context and allow `urllib.request.urlopen()` to use the platform's verified default TLS configuration: ```python with urllib.request.urlopen(req, timeout=10) as response: data = json.loads(response.read()) ``` - Alternatively, use an explicitly verified context without modifying its security properties: ```python ctx = ssl.create_default_context() with urllib.request.urlopen(req, timeout=10, context=ctx) as response: data = json.loads(response.read()) ``` - Never set `check_hostname` to `False` or `verify_mode` to `ssl.CERT_NONE` for authenticated requests. - Fail closed when certificate validation fails. Do not retry over an unverified connection. - Avoid returning raw transport exception details to users or logs if those details may expose sensitive request information. - Invalidate and replace cookies that may previously have been transmitted over untrusted networks while this implementation was in use. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/config_manager.py:35
Finding
Authentication Cookie and Location Stored in a Plaintext Configuration File Without Enforced Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/config_manager.py:10-11` and `scripts/config_manager.py:35-39` **Vulnerability Type**: Insecure storage of sensitive information **Risk Level**: High ### Vulnerable Code ```python CONFIG_DIR = Path.home() / ".openclaw" / "skills" / "eleme-food-recommend" CONFIG_FILE = CONFIG_DIR / "config.json" ``` ```python def save_config(config): """保存配置""" CONFIG_DIR.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) ``` The object written to this file includes the authentication cookie and location: ```python DEFAULT_CONFIG = { "cookie": "", "breakfast": "07:30", "lunch": "11:30", "dinner": "18:30", "flavor": "清淡", "recommend_count": 3, "location": { "latitude": "", "longitude": "", "address": "" } } ``` ### Technical Analysis The Skill persists the Ele.me authentication cookie, coordinates, and address as unencrypted JSON. It does not enforce a restrictive directory mode such as `0700` or a file mode such as `0600`. Actual access therefore depends on the process umask and the permissions of the existing parent directories and file. The implementation also does not validate whether the destination is an existing symbolic link or whether an existing configuration file has unsafe permissions. On a multi-user or otherwise compromised system, a local actor with sufficient path access may be able to read the stored session credential and location information. ### Attack Path 1. A user runs `set-config`, causing `save_config()` to create or update `~/.openclaw/skills/eleme-food-recommend/config.json`. 2. The cookie, coordinates, and address are serialized into the file as plaintext. 3. If the host umask, parent-directory permissions, existing file permissions, backups, or local process boundaries permit access, another local user or process reads t ...[truncated 911 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Prefer an operating-system credential manager or secret-storage service for the authentication cookie. Keep non-secret preferences separate from credentials. - If file storage is unavoidable, enforce restrictive permissions: - Create the configuration directory with mode `0700`. - Create the credential file atomically with mode `0600`. - Verify and repair permissions on existing files. - Reject symbolic links and unexpected non-regular files. - Use atomic replacement to prevent partial writes and reduce race conditions. - Example hardening pattern: ```python CONFIG_DIR.mkdir(parents=True, exist_ok=True, mode=0o700) os.chmod(CONFIG_DIR, 0o700) flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC if hasattr(os, "O_NOFOLLOW"): flags |= os.O_NOFOLLOW fd = os.open(CONFIG_FILE, flags, 0o600) try: with os.fdopen(fd, "w", encoding="utf-8") as f: json.dump(config, f, ensure_ascii=False, indent=2) finally: os.chmod(CONFIG_FILE, 0o600) ``` - For robust atomic updates, write to a securely created file in the same directory, set mode `0600`, flush and synchronize it, and then replace the destination. - Document the sensitivity and retention period of the cookie and location data. - Provide a command that deletes stored credentials and location information. - Rotate or invalidate any cookie believed to have been exposed. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
main.py:48
Finding
Full Authentication Cookie Exposed Through Command Output and Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `main.py:48-52` and duplicate implementation at `scripts/main.py:46-50`; command-line secret input is defined at `main.py:101` and `scripts/main.py:99` **Vulnerability Type**: Sensitive information exposure through output and process arguments **Risk Level**: High ### Vulnerable Code The configuration update response prints the complete configuration returned by `get_config()`, including the full cookie: ```python update_config(**config) print(json.dumps({ "message": "配置已更新", "config": get_config() }, ensure_ascii=False, indent=2)) ``` The same behavior is duplicated in `scripts/main.py`: ```python update_config(**config) print(json.dumps({ "message": "配置已更新", "config": get_config() }, ensure_ascii=False, indent=2)) ``` The cookie is accepted directly as a command-line argument: ```python set_parser.add_argument('--cookie', help='饿了么Cookie') ``` The documented invocation encourages this usage: ```bash python scripts/main.py set-config --cookie "your_eleme_cookie" ``` ### Technical Analysis The `show-config` command attempts to redact the cookie, but `set-config` immediately reloads and prints the complete persisted configuration without redaction. The session credential can consequently enter terminal output, CI logs, agent transcripts, shell captures, or monitoring systems. Passing the cookie through `--cookie` also places it in shell history and may expose it through process inspection while the command is running. Quoting the value does not prevent either form of exposure. Because there are two entry points with duplicated logic, fixing only one file would leave the other vulnerable. ### Attack Path 1. The user follows the documented instructions and supplies the Ele.me cookie through `--cookie`. 2. The shell may persist the complete command in its history. 3. While the process is active, another sufficiently privileged local process may inspect its command-line arguments. ...[truncated 857 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Never include the cookie in command responses. Use one centralized sanitization function for every configuration output path: ```python def redact_config(config): safe = dict(config) if safe.get("cookie"): safe["cookie"] = "[REDACTED]" return safe updated = update_config(**config) print(json.dumps({ "message": "Configuration updated", "config": redact_config(updated) }, ensure_ascii=False, indent=2)) ``` - Apply the correction to both `main.py` and `scripts/main.py`, or remove the duplicate entry point to prevent security fixes from diverging. - Do not accept session credentials as ordinary command-line arguments. Prefer: - A hidden interactive prompt using `getpass.getpass()`. - An operating-system credential manager. - A protected file descriptor or secret-injection mechanism that does not expose the value in process arguments. - Avoid environment variables for long-lived secrets where the runtime or diagnostic tooling may expose them. - Update `README.md` and `SKILL.md` so examples do not place real cookies directly on command lines. - Ensure logs and exception reports redact `Cookie` headers and configuration values. - Remove affected shell-history entries and captured logs where practical, then invalidate and replace any cookie that was exposed. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (15)

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The README explicitly instructs users to extract a live browser Cookie from developer tools and pass it to the skill, but it does not warn that this Cookie is an authentication credential that can grant account access if exposed. In this skill context, the risk is elevated because the Cookie is required for functionality and may be stored, logged, or mishandled by the tool, enabling account takeover or abuse of the user's food-delivery account.

Lp3

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding
The skill advertises operational behavior that likely requires file access, configuration storage, and network access, but it declares no explicit tool scope or permissions. This creates unnecessary ambiguity about what the skill is allowed to do and can enable overbroad execution in hosts that rely on manifest metadata for trust and sandboxing decisions.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The documentation instructs users to pass an Eleme cookie directly on the command line without any warning about credential sensitivity, storage, shell history exposure, or account misuse risk. Cookies are authentication secrets, and exposing them this way can lead to account takeover, unauthorized orders, privacy leakage, or reuse by other local users and logs.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The module docstring and CLI help text present the skill exclusively in Chinese, which effectively forces a specific language for users. The file does not offer any language/locale choice or explain that the skill is intentionally limited to a Chinese-speaking or region-specific audience.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The module persists sensitive user data, including a session cookie and precise location details, to a plain JSON file under the user's home directory without any warning, consent flow, or access-control hardening. In the context of a food-ordering skill, the cookie may enable account/session abuse and the location data exposes sensitive personal information if another local process or user can read the file.

Intent-Code Divergence

Medium
Confidence
99% confidence
Finding
The SSL helper explicitly disables both certificate validation and hostname verification, so every HTTPS request in this module is vulnerable to man-in-the-middle interception. In this skill, those requests carry an Ele.me authentication cookie and precise location data, which makes the weakness materially more dangerous than a generic transport issue because an attacker could steal the session or tamper with restaurant/menu responses.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
This code sends latitude, longitude, and the user's Ele.me cookie to remote Ele.me API endpoints, which is a privacy-sensitive network operation. Although comments and docstrings describe functionality, they do not warn the user that precise location and account-linked authentication data will be transmitted.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
This function performs an authenticated HTTP request by attaching the configured cookie to the request headers. The code lacks a user-facing disclosure that account-linked credentials are being sent to a third-party service as part of menu retrieval.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The module docstring and user-facing descriptions are written entirely in Chinese, which imposes a specific language on users without any visible opt-in or alternative. The stated policy flags language or locale restrictions unless the skill offers a choice or clearly documents a justified regional constraint.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The code checks for and relies on a configured Eleme cookie, which is an authentication credential, but there is no user-facing warning here that the skill will use stored account credentials to access an external service. Silent use of a session cookie increases the risk of unauthorized account actions, accidental credential misuse, or exposure through poor storage/logging practices elsewhere in the skill.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The function sends precise latitude and longitude to a network API to retrieve nearby restaurants, but this file provides no user-facing notice or consent flow about sharing location data. Precise geolocation is sensitive personal data, and silent transmission can expose the user's home/work area or routine if the API, logs, or downstream services are compromised or misused.

Natural-Language Policy Violations

Low
Confidence
78% confidence
Finding
The skill content, commands, and guidance are presented only in Chinese, which can amount to a language/locale constraint without an explicit opt-in or justification. There is no statement that the skill is intended only for Chinese-speaking users or for a China-specific use case.

Natural-Language Policy Violations

Low
Confidence
89% confidence
Finding
The module docstring is written only in Chinese, with no indication that language is selectable or that the skill is intentionally limited to a Chinese-speaking audience. This can violate language/locale policy when a skill imposes a language without user opt-in or documented justification.

Natural-Language Policy Violations

Low
Confidence
82% confidence
Finding
The module docstring and user-visible error messages are presented only in Chinese, which can impose a language constraint without offering opt-in or alternative locale handling. Under the stated policy, forcing a specific language without user choice can be a natural-language policy concern.

Natural-Language Policy Violations

Low
Confidence
78% confidence
Finding
The module docstring is entirely in Chinese and does not indicate that language is configurable or user-selected. This can constitute a language-policy issue when a skill implicitly forces a specific language without offering choice or documenting a justified locale constraint.

Static analysis

No suspicious patterns detected.