Back to skill

Security audit

Travel Frog 旅行青蛙

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent travel-frog experience, but it needs Review because it combines autonomous messaging, persistent memory, image-generation calls, and shell-based file writes with weak guardrails.

Install only if you are comfortable with an autonomous character sending channel messages, generating images through external providers, and keeping persistent diaries and memory. Avoid exposing user-controlled text or paths to shell commands, do not use arbitrary --state-dir values, and treat reset as destructive until confirmation and path containment are added.

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

Warning
Location
templates/AGENTS.md:73
Finding
Shell Command Injection Risk in Mandated Diary Append Operations## Vulnerability Details **File Location**: `templates/AGENTS.md:73` and `templates/HEARTBEAT.md:144` **Vulnerability Type**: Shell command injection through unsafe construction of diary append commands **Risk Level**: Medium ### Vulnerable Code Both templates mandate diary appends through the following operative shell command: ```bash echo [diary content] >> [diary file] ``` The instructions specifically require use of the `exec` tool with `echo >> file` rather than a structured file-writing operation. ### Technical Analysis Diary entries can contain content derived from user conversations, recommendations, place names, travel descriptions, and other externally influenced text. Placing such text directly into an `echo` command creates a shell interpretation boundary. If the Agent constructs the command without rigorous shell escaping, characters such as command substitutions, quotes, semicolons, pipes, or redirection operators can alter the intended command. For example, attacker-controlled text containing a command substitution could be executed by the shell instead of being written literally to the diary. This is an insecure instruction pattern even though the template does not contain a malicious payload itself. It directs downstream Agents to use a shell for a task that does not require shell interpretation. ### Attack Path 1. An attacker supplies text likely to be incorporated into a diary entry, such as a recommendation, location, or conversational statement. 2. The supplied text contains shell metacharacters or command-substitution syntax. 3. Following the template, the Agent embeds the text into an `exec` command using `echo ... >> memory/YYYY-MM-DD.md`. 4. If quoting is absent or incomplete, the shell interprets part of the diary content as syntax. 5. The injected command executes with the same operating-system privileges and filesystem access as the Agent runtime. Exploitation depends on the downstrea ...[truncated 666 chars]
Remediation
## Remediation Suggestions - Replace the mandated `exec` and `echo` workflow with a structured append-file tool that does not invoke a shell. - Alternatively, add a small Python helper that accepts diary content as data and opens the target file in append mode: ```python with open(diary_path, "a", encoding="utf-8") as diary: diary.write(content + "\n") ``` - Validate that the diary path resolves beneath the intended memory directory. - If shell execution is unavoidable, pass content through a non-shell argument channel and use a fixed command with robust positional-argument handling. Do not concatenate content into a shell command. - Apply the same correction to `templates/HEARTBEAT.md:144`. - Add adversarial tests using quotes, command substitutions, semicolons, newlines, pipes, and redirection characters to confirm that all content is stored literally.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/frog_engine.py:91
Finding
Unrestricted State Directory Permits Arbitrary Fixed-Name File Overwrite or Deletion## Vulnerability Details **File Location**: `scripts/frog_engine.py:91-96`, with destructive operations at `scripts/frog_engine.py:615-622` **Vulnerability Type**: Insufficient path validation for filesystem write and deletion operations **Risk Level**: Medium ### Vulnerable Code ```python def init_paths(state_dir=None): """Initialize paths, prioritizing argument, environment variable, then default.""" global STATE_DIR, STATE_FILE, COLLECTIONS_FILE, POSTCARDS_DIR STATE_DIR = state_dir or os.environ.get("FROG_STATE_DIR") or _DEFAULT_STATE_DIR STATE_FILE = os.path.join(STATE_DIR, "state.json") COLLECTIONS_FILE = os.path.join(STATE_DIR, "collections.json") POSTCARDS_DIR = os.path.join(STATE_DIR, "postcards") ``` The reset operation subsequently removes files derived from that unrestricted directory: ```python def cmd_reset(state): if os.path.exists(STATE_FILE): os.remove(STATE_FILE) if os.path.exists(COLLECTIONS_FILE): os.remove(COLLECTIONS_FILE) print(json.dumps({"success": True}, ensure_ascii=False)) ``` Other state-mutating commands write JSON data to the same derived paths: ```python with open(STATE_FILE, "w", encoding="utf-8") as f: json.dump(state, f, ensure_ascii=False, indent=2) ``` ### Technical Analysis The `--state-dir` command-line argument and `FROG_STATE_DIR` environment variable are accepted without canonicalization, ownership checks, symlink checks, or enforcement of an allowed storage root. Consequently, the caller can select any directory accessible to the Agent process. State-mutating commands can overwrite files named `state.json` or `collections.json` in that directory, while the `reset` command can delete them. A symlinked selected directory can also redirect operations outside the expected data area. The filenames are fixed, so this is not unrestricted arbitrary-filename deletion. Nevertheless, it crosses the Skill's ...[truncated 1468 chars]
Remediation
## Remediation Suggestions - Resolve the requested directory to a canonical absolute path before use. - Enforce that production state remains beneath a dedicated application-owned root. - If custom test directories are necessary, restrict them to a designated temporary-test root and enable the feature only in an explicit test mode. - Reject selected directories and target files that are symbolic links. - Verify directory ownership and permissions before reading, writing, or deleting data. - Use safe containment checks based on resolved paths rather than string-prefix comparisons. - Before `reset`, confirm that the resolved target directory is the expected application data directory. - Consider requiring an explicit confirmation flag for destructive reset operations. - Write state atomically through a temporary file in the validated directory followed by `os.replace`. - Add tests covering absolute paths, parent traversal, symlinked directories, environment-variable overrides, and reset attempts outside the permitted root.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (21)

External Model or Provider Selection

High
Category
Excessive Agency
Content
### OpenAI (优先)
```bash
python3 skills/openai-image-gen/scripts/gen.py \
  --prompt "<prompt>" --model gpt-image-1.5 --size 1024x1024 --count 1 \
  --filename "trip_<NNN>_<phase>.png" --out-dir ~/.openclaw/media
```
Confidence
90% confidence
Finding
Skill selects an external model or provider that may use a different account or billing plan than the operator expects. Undisclosed model switches can cause unexpected cost or quota consumption.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill invokes a Python engine and documents persistent state files, but it declares no explicit tool scope or permissions boundaries. That mismatch can cause the host agent to grant broader file/environment access than users expect, increasing the chance of unintended reads, writes, or state manipulation.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
The natural-language instructions and command descriptions are written entirely in Chinese, which effectively forces a specific language for users. The file does not offer an opt-in language choice or explain that the skill is intended only for a Chinese-language audience.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The documented reset command wipes all data, but the skill text does not include an explicit warning about irreversible data loss or any confirmation requirement. In an autonomous or loosely supervised agent flow, this makes accidental destructive invocation more likely and could erase user history, collections, and state.

Tainted flow: 'STATE_FILE' from os.environ.get (line 94, credential/environment) → open (file write)

Medium
Category
Data Flow
Content
def save_state(state):
    ensure_dirs()
    with open(STATE_FILE, "w", encoding="utf-8") as f:
        json.dump(state, f, ensure_ascii=False, indent=2)

def load_collections():
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Tainted flow: 'COLLECTIONS_FILE' from os.environ.get (line 95, credential/environment) → open (file write)

Medium
Category
Data Flow
Content
def save_collections(collections):
    """保存归档数据"""
    with open(COLLECTIONS_FILE, "w", encoding="utf-8") as f:
        json.dump(collections, f, ensure_ascii=False, indent=2)

def _migrate_v1_to_v2(state):
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Tainted flow: 'STATE_FILE' from os.environ.get (line 94, credential/environment) → shutil.copy2 (file write)

Medium
Category
Data Flow
Content
bak_path = STATE_FILE + ".v1.bak"
    if not os.path.exists(bak_path):
        import shutil
        shutil.copy2(STATE_FILE, bak_path)
        log.info(f"[migrate] backup → {bak_path}")

    # 提取归档数据
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The skill exposes force-status and reset administrative commands that can alter or delete persisted state and are not necessary for the advertised postcard/photo travel experience. In an agent setting, these extra controls expand the attack surface and could be abused to erase history, manipulate behavior, or disrupt expected operation.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
The skill mandates `exec` to run a local Python script on every startup and for user-triggered actions, creating a broad shell-execution capability that exceeds what is necessary for a conversational travel persona. Even if the intended commands are fixed, normalizing `exec` in the policy increases the chance of command abuse, argument injection, or future expansion into unsafe shell operations.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The diary feature instructs the agent to automatically append detailed interaction-derived entries to dated files, including conversations and learned information, without requiring user-facing notice. This is a privacy and transparency issue because users may not realize their messages or inferred details are being persistently stored.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The learning rules direct the agent to save user-shared places, preferences, and knowledge into long-term memory files, but they do not tell the user that this information will be retained. In context, this creates a meaningful privacy risk because casual chat input becomes persistent profile data without transparent notice or consent.

Intent-Code Divergence

Medium
Confidence
88% confidence
Finding
The safety section claims the agent should not execute out-of-game requests, but the rest of the document still relies on broad `exec`-based command and file operations. This mismatch is dangerous because it creates a weak policy boundary: the agent is given powerful execution mechanisms while only being restrained by natural-language instructions, which are easier to bypass or reinterpret.

Skill Enumeration

Medium
Category
Agent Snooping
Content
# HEARTBEAT.md - 心跳事件处理

> 命令详情见 skills/travel-frog/SKILL.md

## 执行
Confidence
80% confidence
Finding
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
The file explicitly requires all engine commands to be executed through an `exec` tool, but provides no warning or restriction around subprocess or shell execution. This increases attack surface because downstream command construction may incorporate dynamic data from engine output or memory files, enabling unsafe command execution patterns in an autonomous loop.

Missing User Warnings

Medium
Confidence
84% confidence
Finding
The workflow directs automatic updates to persistent memory files such as `memory/world_knowledge.md` with no warning, approval boundary, or integrity controls. Persistent memory modification can be abused to poison future behavior, create hidden state, or store misleading instructions that later influence destination planning and messaging.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The skill instructs the agent to append to diary files using `exec` and shell redirection (`echo >> file`) without any disclosure or guardrails around persistent file modification. This is dangerous because it normalizes opaque state changes and, if any diary content or path components become attacker-influenced elsewhere in the system, shell-based appends can lead to unintended file writes or command-injection-adjacent risks.

Natural-Language Policy Violations

Medium
Confidence
86% confidence
Finding
The instruction to use local dialects with Chinese explanations imposes a specific language/locale behavior in the skill's natural-language guidance. The file does not offer the user a choice of language or indicate that Chinese is optional, which can violate language/locale policy requirements.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
This markdown file is written entirely in Chinese and presents the tool instructions as mandatory guidance, with no indication that users may choose another language or locale. Under the stated policy, forcing a specific language without opt-in is a natural-language policy violation unless the constraint is explicitly justified.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The file content is entirely written in Chinese and includes operational guidance for how memory should be recorded, with no indication that language selection is based on user preference. In an agent skill, forcing a specific language can cause the agent to respond or store memory in a language the user did not request, degrading usability and potentially causing misunderstandings in safety-relevant interactions.

Context-Inappropriate Capability

Low
Confidence
84% confidence
Finding
The engine reads a workspace-level IDENTITY.md file outside the skill's own data directory to derive the frog's name. That broadens data access beyond the stated travel simulation purpose and can unintentionally ingest user/workspace metadata, which is a privacy and scope-creep issue even if only a small field is extracted.

Context-Inappropriate Capability

Low
Confidence
84% confidence
Finding
The instructions authorize persistent writes to memory files as part of normal interaction, which expands the agent from a travel role into a stateful file-writing actor. This can enable unintended data retention, prompt-influenced content poisoning of local memory, and modification of files beyond what users reasonably expect from a simple character skill.

Static analysis

No suspicious patterns detected.