Back to skill

Security audit

clawauto-shop

Security checks for vulnerabilities and agentic risk

Overview

This skill is review-worthy because it can create real food orders, sends account credentials to configurable backends, and stores sensitive order links locally.

Install only if you trust the configured backend. Use HTTPS for any non-local backend, use a scoped or test API key where possible, keep --allow-final-submit off until the user explicitly confirms the purchase, and protect or delete outputs/openclaw_order_state because they may contain usable order links, pickup codes, and screenshots.

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

T09 · Insecure Skill Coding Practices

Error
Location
openclaw_skill.py:128
Finding

API credentials and personal identifiers may be transmitted over plaintext HTTP

Content
View full analysis

Vulnerability Details

File Location: openclaw_skill.py:128-132 (also affects requests at lines 145-159, 177-185, and 203-227); insecure configuration is documented at OPENCLAW_INSTALL_CHECKLIST.md:20-22
Vulnerability Type: Transmission of sensitive information over an unencrypted channel
Risk Level: High

Vulnerable Code

python
def get_products(identity: str, api_key: str, base_url: str, timeout: int = 10) -> dict:
    payload = {"username": identity, "phone": identity, "api_key": api_key}
    url = f"{base_url}/products"
    try:
        response = requests.post(url, json=payload, timeout=timeout)

The same credential-bearing request pattern is used for order status, order history, and order creation:

python
payload = {
    "username": identity,
    "phone": identity,
    "api_key": api_key,
    "order_id": int(order_id),
}
url = f"{base_url.rstrip('/')}/order/status"
response = requests.post(url, json=payload, timeout=timeout)

The installation checklist permits a remote plaintext HTTP endpoint:

env
KFC_PLATFORM_PHONE=your_platform_phone
KFC_PLATFORM_API_KEY=your_platform_api_key
KFC_PLATFORM_BASE_URL=http://your-backend-host:8888/api/openclaw

Technical Analysis

Sending an identity and API key to the ordering backend is necessary for the Skill's declared functionality. However, accepting and documenting non-loopback HTTP endpoints exceeds the minimum safe network privilege needed for that functionality.

resolve_base_url() and the request functions do not enforce HTTPS for remote endpoints. When an operator configures an http:// backend, requests.post() transmits the phone number or username and reusable API key without transport encryption. Request timeouts do not provide confidentiality or server authentication.

Placing the API key in the JSON body also increases the chance that it will be captured by application request logging, revers ...[truncated 1468 chars]

Remediation
View remediation

Remediation Suggestions

  1. Reject non-HTTPS URLs unless the destination is explicitly verified as loopback:
    python
    import ipaddress
    from urllib.parse import urlparse
    
    def validate_base_url(base_url: str) -> str:
        parsed = urlparse(base_url)
        host = parsed.hostname or ""
    
        is_loopback = host == "localhost"
        try:
            is_loopback = is_loopback or ipaddress.ip_address(host).is_loopback
        except ValueError:
            pass
    
        if parsed.scheme != "https" and not is_loopback:
            raise ValueError("Remote backend URLs must use HTTPS")
        return base_url.rstrip("/")
    
  2. Apply validation centrally in resolve_base_url() so every endpoint inherits the policy.
  3. Replace the remote HTTP example in OPENCLAW_INSTALL_CHECKLIST.md with an HTTPS URL. Clearly state that HTTP is allowed only for loopback development.
  4. Prefer a scoped, short-lived authorization token in the Authorization header rather than placing reusable secrets in request bodies.
  5. Configure the backend and reverse proxies to redact authorization data and request bodies from logs.
  6. Use separate read-only and order-creation scopes so compromise of a listing credential cannot authorize purchases.
  7. Ensure TLS certificate verification remains enabled and do not introduce a verify=False bypass.

T09 · Insecure Skill Coding Practices

Warning
Location
openclaw_skill.py:258
Finding

Sensitive order links, pickup data, and screenshots are stored without explicit access restrictions or retention controls

Content
View full analysis

Vulnerability Details

File Location: openclaw_skill.py:258-292; related artifact creation occurs in kfc_custom_product_flow.py:95-96, 154-155, 183, kfc_place_order_test_old.py:140-141, 200-201, 246-247, 323-324, 354, kfc_vip_choose_spec_flow.py:168-169, 227-228, 256, mcd_custom_product_flow.py:85-86, 150-151, 190, and mcd_place_order_test.py:127-128, 184-185, 199-200, 215-216, 250
Vulnerability Type: Insecure local storage of sensitive order artifacts
Risk Level: Medium

Vulnerable Code

The local state includes redemption URLs, order identifiers, idempotency keys, pickup results, and account-related order metadata:

python
payload = {
    "idempotency_key": idempotency_key,
    "order_id": order_id or (order_resp or {}).get("order_id") or 0,
    "url": url or (order_resp or {}).get("url") or "",
    "stage": stage,
    "flow_code": flow_code,
    "flow_result": flow_result,
    "updated_at": now,
}
if order_resp:
    payload["cost_yuan"] = order_resp.get("cost_yuan", order_resp.get("points_cost"))
    payload["balance_yuan"] = order_resp.get("balance_yuan", order_resp.get("points_balance"))
    payload["product_name"] = (order_resp.get("product") or {}).get("name")
if "created_at" not in payload:
    payload["created_at"] = now
path = state_dir / f"{_sanitize_idem_key(idempotency_key)}.json"
try:
    # Preserve created_at if the file already exists.
    if path.exists():
        try:
            existing = json.loads(path.read_text(encoding="utf-8"))
            payload["created_at"] = existing.get("created_at", now)
        except Exception:
            pass
    path.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8")
    return path
except OSError:
    return None

Browser-flow scripts also persist full-page screenshots and result JSON. For example:

python
shot1 = out_dir / f"kfc_cp_step1_pickup_{tag}.png"
await p
...[truncated 3186 chars]
Remediation
View remediation

Remediation Suggestions

  1. Create sensitive directories with owner-only permissions:
    python
    state_dir.mkdir(parents=True, exist_ok=True, mode=0o700)
    os.chmod(state_dir, 0o700)
    
  2. Create files atomically with mode 0600, rather than relying on Path.write_text() and the ambient umask:
    python
    flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
    fd = os.open(path, flags, 0o600)
    with os.fdopen(fd, "w", encoding="utf-8") as handle:
        json.dump(payload, handle, ensure_ascii=False, indent=2)
    
  3. Write to an owner-only temporary file and atomically rename it to avoid partially written state and symlink-related replacement risks.
  4. Store a redacted URL by default. Remove or encrypt query values such as cdkey and outId unless recovery strictly requires them.
  5. Make screenshots opt-in and warn that they may contain sensitive order information.
  6. Add configurable retention and automatically delete state, result files, and screenshots after a short period or once the order completes.
  7. Add and verify a .gitignore covering outputs/, openclaw_order_state/, .env, screenshots, and result JSON, while recognizing that ignore rules are not a substitute for filesystem permissions.
  8. Avoid printing complete sensitive URLs to shared logs. If the recovery protocol requires the URL on standard output, provide an explicit secure-output mode and redact it in ordinary diagnostic logging.
  9. Consider encrypting recovery state with a user-specific secret when artifacts must persist across sessions.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (32)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
- Can run with user-configured phone + api key.

## Required Runtime Config
Use either CLI args or environment variables. For OpenClaw usage, **.env is recommended**:

### Env-based config (dev / prod)

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

This script is presented as a 'flow tester' but its default behavior can progress through the real KFC ordering flow and submit a live order unless the operator explicitly passes --no-submit. In an agent/skill context, that mismatch between description and behavior is dangerous because it can trigger unintended real-world transactions, purchases, or operational actions during testing or routine execution.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script proceeds from page navigation to clicking '下单' and then a final confirmation button, which can place a real order unless the operator explicitly remembers to pass --no-submit. In an automation/agent context, that creates a dangerous side effect: a supplied URL and store code are enough to trigger a purchase flow without an in-band user confirmation, preview, or explicit acknowledgment of cost/commitment.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The checklist instructs operators to configure real platform credentials and a live backend endpoint but does not warn that these secrets enable access to production ordering functions. In the context of a food-ordering automation skill, this increases the chance of accidental use of real accounts, unintended transactions, and credential mishandling during setup or testing.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The real-order validation section provides runnable commands that drive browser automation through live KFC and McD ordering flows, yet it does not clearly warn that these actions may interact with real stores, consume points, reserve inventory, or place orders if safeguards fail. Because the skill is specifically designed for transaction automation, the missing warning materially raises the risk of accidental real-world impact during testing.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The user-facing instructions at this line are written as a mandatory directive in Chinese, and the document continues to present operational guidance in Chinese without indicating multilingual support or giving the user a language preference option. This creates a locale/language policy concern because the skill appears to require a specific language by default rather than offering user choice.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill explicitly instructs the caller/model to scrape OPENCLAW_FINAL_LINK: from stdout and display it directly in chat during disconnect or recovery scenarios. Because the link represents an active order URL and the local state also stores order identifiers and pickup details, surfacing it without re-authentication or redaction can expose sensitive transactional data to the wrong user or any component with log/chat access.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This script automates a real purchase flow by clicking the final submission controls ('确认提交' and popup '确认') using a user-supplied URL, and it proceeds by default unless --no-submit is explicitly set. That creates a genuine safety/security risk because running the skill can trigger an irreversible real-world transaction without an additional runtime confirmation, clear warning, or dry-run default.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code clicks the final confirmation and waits for order completion without any explicit user-facing warning or secondary confirmation before the irreversible action. In an automation skill, this increases the risk of accidental purchases because callers may believe they are only validating UI flow while the script actually commits a transaction.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script hardcodes locale="zh-CN", which imposes a specific language/locale behavior on all runs. The file does not indicate that this is optional, user-selected, or required for a region-specific compliance reason.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script captures screenshots and later writes a JSON result file containing order details such as pickup code, order number, URL, and page state to disk. These artifacts can expose sensitive transactional information to other local users, logs, backup systems, or downstream tooling, especially because there is no minimization, retention control, or user consent around storing them.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This script can place a real McDonald's order by clicking the final confirmation button automatically unless the caller explicitly supplies --no-submit. That creates a risky default for a purchasing workflow, because an agent or automation framework could trigger financial or real-world actions without an informed, user-facing confirmation step at execution time.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script hard-codes locale="zh-CN" and a precise Shanghai geolocation into the browser context, which overrides user/environment settings and can misrepresent the operator's location to the target service. In an order-flow automation context, this can bypass region-specific behavior, produce misleading test results, or trigger actions under a falsified location context without explicit user awareness or consent.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

This code transmits identity data and the API key to a configurable backend URL, which may be attacker-controlled if set via CLI or environment. In this skill's context, the transmitted data is sensitive account material, and the default development endpoint is plain HTTP, creating a real risk of credential exposure to local-network interception or misconfiguration.

Content

Scanner excerpt · openclaw_skill.py (reported line 132)May include surrounding context.

python
payload = {"username": identity, "phone": identity, "api_key": api_key}
    url = f"{base_url}/products"
    try:
        response = requests.post(url, json=payload, timeout=timeout)
        response.encoding = "utf-8"
        response.raise_for_status()
    except requests.RequestException as exc:

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

The order-status request sends identity, API key, and order ID to a user-configurable endpoint, exposing both authentication material and order metadata. Because this function may query and refresh live order status, directing it to an untrusted or insecure server could leak credentials and enable account/order reconnaissance.

Content

Scanner excerpt · openclaw_skill.py (reported line 159)May include surrounding context.

python
}
    url = f"{base_url.rstrip('/')}/order/status"
    try:
        response = requests.post(url, json=payload, timeout=timeout)
        response.encoding = "utf-8"
    except requests.RequestException as exc:
        raise RuntimeError(f"request failed: {exc}") from exc

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

Listing server orders sends identity and API key to the configured backend, which exposes account-level order history if intercepted or sent to an attacker-controlled URL. In a commerce-related skill, that data is sensitive and the ability to enumerate orders materially increases privacy and fraud risk.

Content

Scanner excerpt · openclaw_skill.py (reported line 185)May include surrounding context.

python
payload = {"username": identity, "phone": identity, "api_key": api_key}
    url = f"{base_url.rstrip('/')}/orders"
    try:
        response = requests.post(url, json=payload, timeout=timeout)
        response.encoding = "utf-8"
    except requests.RequestException as exc:
        raise RuntimeError(f"request failed: {exc}") from exc

External Transmission

Medium
Category
Data Exfiltration
Confidence
93% confidence
Finding

The order-placement request transmits identity, API key, product selection, pricing, and idempotency data to a configurable remote endpoint. In this skill context, that is especially sensitive because it can authorize real purchases; using a non-validated endpoint or insecure transport could leak credentials and transaction details or facilitate fraudulent order actions.

Content

Scanner excerpt · openclaw_skill.py (reported line 227)May include surrounding context.

python
payload["supplier_goods_id"] = supplier_goods_id
    url = f"{base_url}/order"
    try:
        response = requests.post(url, json=payload, timeout=timeout)
        response.encoding = "utf-8"
        response.raise_for_status()
    except requests.RequestException as exc:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill persistently stores order URLs, order IDs, timestamps, product metadata, and related flow results in local JSON files without access controls, encryption, or clear user consent. Because these order links appear to enable continued order access or fulfillment, any other local user, malware, backup service, or log collector that can read the directory may obtain sensitive purchase data and potentially active ordering links.

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 · openclaw_skill.py (reported line 405)May include surrounding context.

python
if args.no_final_submit or not args.allow_final_submit:
        cmd.append("--no-submit")

    proc = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8", errors="replace")
    result_file = extract_result_file(proc.stdout)
    if result_file is None:
        if proc.returncode != 0:

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 · openclaw_skill.py (reported line 445)May include surrounding context.

python
if args.no_final_submit or not args.allow_final_submit:
        cmd.append("--no-submit")

    proc = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8", errors="replace")
    result_file = extract_result_file(proc.stdout)
    if result_file is None:
        if proc.returncode != 0:

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 · openclaw_skill.py (reported line 493)May include surrounding context.

python
if args.no_final_submit or not args.allow_final_submit:
        cmd.append("--no-submit")

    proc = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8", errors="replace")
    result_file = extract_result_file(proc.stdout)
    if result_file is None:
        if proc.returncode != 0:

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 · openclaw_skill.py (reported line 533)May include surrounding context.

python
if args.no_final_submit or not args.allow_final_submit:
        cmd.append("--no-submit")

    proc = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8", errors="replace")
    result_file = extract_result_file(proc.stdout)
    if result_file is None:
        if proc.returncode != 0:

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 · openclaw_skill.py (reported line 571)May include surrounding context.

python
if args.no_final_submit or not args.allow_final_submit:
        cmd.append("--no-submit")

    proc = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8", errors="replace")
    result_file = extract_result_file(proc.stdout)
    if result_file is None:
        if proc.returncode != 0:

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The code hard-codes locale="zh-CN" when creating the browser context. Under the policy, forcing a specific language or locale without opt-in is a natural-language policy concern unless the constraint is explicitly justified or user-selectable.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

The browser context is created with locale='zh-CN', which enforces a specific language/locale setting. The file does not offer a user choice or explain why the locale must be fixed, so this is a natural-language policy concern under the locale-choice rule.

Content

No source excerpt is available for this finding.