Back to skill

Security audit

migu-trip-agent

Security checks for vulnerabilities and agentic risk

Overview

This travel-planning skill mostly does what it says, but it uses a copied login token and recommended raw traffic logging that can expose account-linked travel data.

Install only if you are comfortable giving this skill local access to a Migu Travel login JWT and sending itinerary details to gulangyu.migudm.cn. Do not paste the token into chat, avoid using --log-file for normal runs, delete any ws-openclaw.jsonl-style logs, and treat the token/session files as sensitive credentials.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/plan_multi_ws_client.mjs:960
Finding

Raw WebSocket Traffic Logging Exposes Authenticated Personal Data

Content
View full analysis

Vulnerability Details

File Location: scripts/plan_multi_ws_client.mjs:960-968
Vulnerability Type: Sensitive information exposure through persistent raw traffic logging
Risk Level: Medium

Complete Code Snippet

js
function logTraffic(args, direction, raw, extra = {}) {
  if (!args?.logFile) return;
  const line = JSON.stringify({
    ts: new Date().toISOString(),
    direction,
    raw,
    ...extra,
  });
  appendFileSync(args.logFile, `${line}\n`, "utf8");
}

The logger is reached for inbound WebSocket frames at scripts/plan_multi_ws_client.mjs:1214-1216:

js
_onMessage(raw) {
  logTraffic(this.args, "recv", raw.toString());
  const frame = parseFrame(raw);

The documented recommended command enables this behavior at SKILL.md:641-648:

bash
--bearer \
--trip-plan-direct \
--plan-form-file "$HOME/.openclaw/workspace/plan_form.json" \
--session-file "$HOME/.openclaw/workspace/plan_multi_session.txt" \
--fallback-trip-plan \
--json \
--log-file "./ws-openclaw.jsonl"

A resulting log was included in the project. At ws-openclaw.jsonl:2, an authenticated server frame contains a full phone-number-like userId:

json
{"ts":"2026-09-30T10:05:37.336Z","direction":"recv","raw":"{\"content\":{\"connectionId\":\"17858366-9696-4df1-9c39-fa6d03ccd557\",\"msg\":\"欢迎使用多模态AI服务\",\"time\":\"2026-09-30 18:05:36.198\",\"userId\":\"15881010233\"},\"content_type\":\"json\",\"status\":\"stop\",\"task_status\":\"\",\"category\":\"system_notify\"}"}

Technical Analysis

When --log-file is supplied, logTraffic() serializes and appends complete WebSocket frames without an allowlist or redaction pass. The output includes authenticated service responses, user questions, session identifiers, travel dates, passenger composition, and itinerary details.

This is not merely a theoretical risk: ws-openclaw.jsonl is already distributed with the project an ...[truncated 1939 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove ws-openclaw.jsonl from the distributed package and repository history. Treat the disclosed identifier and travel data according to the project’s incident-response and privacy procedures.
  2. Remove --log-file from the recommended production command. Raw traffic logging should be an explicitly enabled diagnostic feature with a prominent privacy warning.
  3. Replace raw-frame logging with structured, allowlisted telemetry. Record only non-sensitive fields such as timestamps, frame category, status, task state, payload size, and generic error codes.
  4. Apply redaction before serialization. At minimum, remove or mask:
    • Phone numbers and user IDs
    • Session, task, and connection identifiers
    • Authorization values and JWT-shaped strings
    • User questions and recommendation content
    • Travel dates, destinations, passenger composition, and itinerary details
  5. Create diagnostic files with owner-only permissions, such as mode 0600 on supported platforms, rather than relying on the process umask.
  6. Add generated traffic logs to .gitignore and packaging exclusions, for example ws-*.jsonl and other configured log destinations.
  7. Implement retention controls, such as automatic deletion after a short interval or a documented cleanup command.
  8. Add tests that pass representative frames containing identifiers, JWTs, session IDs, and itinerary details through the logger and verify that none appear in the resulting file.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (20)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
6. 用户确认需要路书后,执行 `scripts/get_roadbook.mjs` 生成路书。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
6. 用户确认需要路书后,执行 `scripts/get_roadbook.mjs` 生成路书。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
6. 用户确认需要路书后,执行 `scripts/get_roadbook.mjs` 生成路书。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
6. 用户确认需要路书后,执行 `scripts/get_roadbook.mjs` 生成路书。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
6. 用户确认需要路书后,执行 `scripts/get_roadbook.mjs` 生成路书。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/plan_multi_ws_client.mjs --check-token --probe-auth --token-diagnostics

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/plan_multi_ws_client.mjs --check-token --probe-auth --token-diagnostics

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill clearly performs network access and reads local credential material, but it does not declare any explicit tool scope or allowed-tools boundary. That creates a least-privilege failure: the runtime may permit broader capabilities than reviewers and users can easily verify, increasing the risk of unintended external requests or credential-adjacent actions.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger phrases are broad enough to match ordinary travel conversation, which can cause the skill to auto-activate in contexts where the user did not intend external network use. In this skill, unintended activation is more sensitive because it may lead to third-party requests using the user's locally configured authentication token.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This JSON example includes a natural-language comment and values entirely in Chinese, which can impose a specific language on users without any visible opt-in or justification. The policy requires flagging language or locale constraints when the skill forces a specific language without user choice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The document is entirely prescriptive in Chinese and uses mandatory language such as '必须' for the required output format, but it does not indicate that the language is optional or user-selected. This can violate a language/locale policy when the skill forces a specific language presentation without user opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This file includes natural-language comments and output strings exclusively in Chinese, including the success and hint messages shown to users. The skill does not offer any language or locale choice, and there is no indication that the skill is intentionally limited to a Chinese-speaking or region-specific context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script supports --log-file and writes raw WebSocket send/receive/error/close events to disk via logTraffic. Because the WebSocket URL is constructed with token in the query string and outbound payloads/inbound frames may include session identifiers or itinerary data, raw logging can persist authentication material and sensitive session content to local files where other local users, backups, or support bundles may later expose it.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README instructs the user to manually extract an authenticated JWT from browser developer tools and save it locally, which contradicts the skill's stated security model that it relies on locally configured credentials without asking the user for a token. Manual token harvesting increases the chance of credential mishandling, accidental sharing, reuse beyond intended scope, and insecure storage of a bearer token that grants account access.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The instructions tell users to copy a live login JWT and store it in a file, but they do not clearly emphasize that this token is a sensitive secret equivalent to account access and must never be shared or exposed. In the context of a travel-planning skill using third-party authenticated APIs, this omission makes credential leakage more likely through screenshots, chat paste, backups, or weak local storage practices.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The "何时使用" section combines clear user intents with an internal condition about plan_multi fallback behavior, which is not a user-visible trigger. This blurs the boundary between when the skill should activate from user requests versus when it should be used for backend exception handling.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code emits user-visible error text in Chinese, and later also prints Chinese status labels, without offering a language/locale option. That creates a natural-language policy concern because it forces a specific language on users without opt-in or documented justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The normal command output uses Chinese-only labels for roadbook name and image URL. Forcing a single language in user-facing output can violate language/locale policy when no opt-in or explicit regional scope is provided.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

persistSessionId writes the session_id to a file path supplied by the user, which is a file write involving conversation/session state. The operation has no nearby disclosure about what is being stored or its sensitivity, aside from a minimal verbose log after the write.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

This JSONL log contains natural-language system content in Chinese ("欢迎使用多模态AI服务"). For SQP-3, locale or language constraints should not be forced unless the skill offers user choice or clearly documents a justified region-specific limitation; no such opt-in or justification is visible in this file.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.