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

Content
View full analysis

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
View 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

Content
View full analysis

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
View 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
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.

Content

Scanner excerpt · templates/TOOLS.md (reported line 13)May include surrounding context.

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

Undeclared Tool Scope

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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

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

Medium
Category
Data Flow
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.

Content

Scanner excerpt · scripts/frog_engine.py (reported line 137)May include surrounding context.

python
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():

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

Medium
Category
Data Flow
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.

Content

Scanner excerpt · scripts/frog_engine.py (reported line 153)May include surrounding context.

python
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):

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

Medium
Category
Data Flow
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.

Content

Scanner excerpt · scripts/frog_engine.py (reported line 164)May include surrounding context.

python
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}")

    # 提取归档数据

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Skill Enumeration

Medium
Category
Agent Snooping
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.

Content

Scanner excerpt · templates/HEARTBEAT.md (reported line 3)May include surrounding context.

md
# HEARTBEAT.md - 心跳事件处理

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

## 执行

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.