Back to skill

Security audit

Travel Lobster

Security checks for vulnerabilities and agentic risk

Overview

The skill is openly designed as an autonomous recurring web-postcard agent, but its self-scheduling loop and unsafe shell-based configuration create risks users should review before installing.

Install only if you intentionally want a recurring autonomous agent that browses public sites, spends API credits, sends chat messages, and maintains a persistent journal. Review or fix the shell-sourced .travel-config handling before use, start with a one-shot/manual run, avoid adding the watchdog until trusted, and monitor/remove the travel-next cron job if you want it stopped.

Vulnerability Patterns
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • 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
Findings (3)

T06 · System Persistence

Error
Location
scripts/travel.sh:94
Finding
Indefinite Autonomous Execution Through Self-Recreating Scheduled Tasks<![CDATA[ ## Vulnerability Details **File Location**: `scripts/travel.sh:94-103`, `references/travel-prompt.md:155-163`, `scripts/watchdog.sh:21-41` **Vulnerability Type**: Cross-session scheduled-task persistence **Risk Level**: High ### Vulnerable Code `scripts/travel.sh:94-103`: ```bash openclaw cron add \ --name "travel-next" \ --at "${NEXT_MIN}m" \ --delete-after-run \ --session isolated \ --model "openrouter/google/gemini-3.1-pro-preview" \ --timeout-seconds 300 \ --no-deliver \ --message "$PROMPT" \ 2>> "$LOGFILE" ``` `references/travel-prompt.md:155-163`: ```markdown ## Step 7: Schedule next trip (CRITICAL — DO NOT SKIP) This is the most important step. Without it, the travel loop dies. Run this command IMMEDIATELY, even if previous steps had errors: ```bash bash ${SKILL_DIR}/scripts/travel.sh ${CHAT_ID} ${CHANNEL} ``` If this step fails, the entire travel loop stops. Always run it, no matter what happened before. ``` `scripts/watchdog.sh:21-41`: ```bash # Check if travel-next cron job exists JOB_EXISTS=$(openclaw cron list 2>/dev/null | grep -c "travel-next" || true) if [ "$JOB_EXISTS" -eq 0 ]; then echo "$(date -u '+%Y-%m-%d %H:%M:%S UTC') ⚠️ Watchdog: travel-next not found, restarting loop" >> "$LOGFILE" CHAT_ID="${TRAVEL_CHAT_ID}" CHANNEL="${TRAVEL_CHANNEL:-feishu}" if [ -z "$CHAT_ID" ]; then echo "$(date -u '+%Y-%m-%d %H:%M:%S UTC') ❌ Watchdog: No CHAT_ID in config, cannot restart" >> "$LOGFILE" exit 1 fi bash "$SKILL_DIR/scripts/travel.sh" "$CHAT_ID" "$CHANNEL" echo "$(date -u '+%Y-%m-%d %H:%M:%S UTC') ✅ Watchdog: Loop restarted" >> "$LOGFILE" else echo "$(date -u '+%Y-%m-%d %H:%M:%S UTC') ✅ Watchdog: Loop is alive" >> "$LOGFILE" fi ``` ### Technical Analysis The Skill installs an OpenClaw cron task that launches an isolated Agent session after a random delay. Although each individual task uses `--delete-after-run`, the scheduled Agent is ...[truncated 2003 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Make one-shot execution the default and require explicit opt-in before enabling recurrence. 2. Add mandatory limits such as maximum trip count, expiration timestamp, daily spending cap, and maximum consecutive failures. 3. Do not reschedule after an error unless the user explicitly selected a documented retry policy. 4. Store a user-controlled enabled/disabled state and verify it immediately before every scheduling operation. 5. Use unique, ownership-scoped task identifiers so the Skill cannot remove or interfere with unrelated jobs. 6. Require separate confirmation before enabling the watchdog. 7. Provide an idempotent uninstall command that removes both the OpenClaw task and any system-cron watchdog entry. 8. Display the next execution time, estimated cost, expiration, and stop command when recurrence is enabled. 9. Prefer a platform-managed scheduler with explicit lifecycle controls over a prompt instruction that asks an Agent to recreate itself. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/setup.sh:21
Finding
Arbitrary Shell Command Execution Through Sourced Configuration Values<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup.sh:21-44`, `scripts/setup.sh:104-111`, `scripts/travel.sh:17-50`, `scripts/watchdog.sh:18` **Vulnerability Type**: Shell command injection through unsafe configuration serialization and evaluation **Risk Level**: High ### Vulnerable Code `scripts/setup.sh:21-44` obtains values from workspace files without shell-syntax validation: ```bash if [ -f "$WORKSPACE/IDENTITY.md" ]; then AGENT_NAME=$(grep -oP '\*\*Name:\*\*\s*\K.+' "$WORKSPACE/IDENTITY.md" 2>/dev/null || true) fi if [ -z "$AGENT_NAME" ] && [ -f "$WORKSPACE/SOUL.md" ]; then AGENT_NAME=$(grep -oP '我是\K[^—— ]+' "$WORKSPACE/SOUL.md" 2>/dev/null | head -1 || true) [ -z "$AGENT_NAME" ] && AGENT_NAME=$(grep -oP 'I am \K\w+' "$WORKSPACE/SOUL.md" 2>/dev/null | head -1 || true) fi AGENT_NAME="${AGENT_NAME:-Explorer}" # --- Detect user name --- USER_NAME="" if [ -f "$WORKSPACE/USER.md" ]; then USER_NAME=$(grep -oP '\*\*What to call them:\*\*\s*\K.+' "$WORKSPACE/USER.md" 2>/dev/null || true) [ -z "$USER_NAME" ] && USER_NAME=$(grep -oP '\*\*Name:\*\*\s*\K.+' "$WORKSPACE/USER.md" 2>/dev/null || true) fi USER_NAME="${USER_NAME:-friend}" # --- Detect user timezone --- USER_TZ="" if [ -f "$WORKSPACE/USER.md" ]; then USER_TZ=$(grep -oP '\*\*Timezone:\*\*\s*\K.+' "$WORKSPACE/USER.md" 2>/dev/null || true) [ -z "$USER_TZ" ] && USER_TZ=$(grep -oiP 'timezone[:\s]*\K\S+' "$WORKSPACE/USER.md" 2>/dev/null | head -1 || true) fi USER_TZ="${USER_TZ:-UTC}" ``` `scripts/setup.sh:104-111` writes those values directly into shell syntax: ```bash cat > "$SKILL_DIR/.travel-config" << CONFIG_EOF AGENT_NAME="$AGENT_NAME" USER_NAME="$USER_NAME" USER_TZ="$USER_TZ" USER_LANG="$USER_LANG" WORKSPACE="$WORKSPACE" JOURNAL="$JOURNAL" SKILL_DIR="$SKILL_DIR" CONFIG_EOF ``` `scripts/travel.sh:17` evaluates the resulting file: ```bash source "$CONFIG" ``` It then rewrites command-line and configuration values into the same executable shell file at ` ...[truncated 2928 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Never use `source` to load a file containing data. 2. Store configuration in a non-executable format such as JSON. 3. Parse JSON with a data parser and assign each expected field explicitly. 4. Apply strict allowlists: - Validate timezone against known IANA timezone identifiers. - Validate language against supported language codes. - Restrict channel names to supported identifiers. - Validate chat identifiers using the platform's documented format. - Reject newlines, control characters, and unexpected lengths in display names. 5. If shell serialization is unavoidable, encode each value with `printf '%q'`; however, a non-executable format remains preferable. 6. Create the configuration atomically with restrictive permissions, such as mode `0600`. 7. Verify that the configuration is a regular file owned by the expected user and is not a symbolic link before reading or replacing it. 8. Avoid retaining sensitive environment variables when scheduled scripts do not require them. 9. Add regression tests containing quotes, semicolons, backticks, command substitutions, newlines, and shell redirection characters. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
references/travel-prompt.md:18
Finding
Indirect Prompt Injection Exposure in a Tool-Capable Web Exploration Session<![CDATA[ ## Vulnerability Details **File Location**: `references/travel-prompt.md:18-22`, `references/travel-prompt.md:111-163` **Vulnerability Type**: Untrusted web content processed in a session authorized for shell, messaging, file modification, and scheduling **Risk Level**: Medium ### Vulnerable Code `references/travel-prompt.md:18-22` permits retrieval from broad, uncontrolled public sources: ```markdown ## Step 3: Explore Use `web_fetch` to read public knowledge sources: Wikipedia, news sites, academic journals, blogs, educational sites, and other publicly accessible content. **Allowed**: Any publicly accessible website with educational, scientific, cultural, or general-interest content. **Forbidden**: Private/internal IPs (10.x, 172.16-31.x, 192.168.x, 127.x, localhost), authenticated services, APIs requiring credentials, file:// URLs, and any non-HTTP(S) protocols. ``` The same Agent session is subsequently authorized to execute local commands, send messages, modify persistent state, and schedule another session at `references/travel-prompt.md:111-163`: ```markdown ### 5a. Generate the image ```bash python3 ${SKILL_DIR}/scripts/gen_image.py "image prompt matching the mood" ${WORKSPACE}/postcard_${NEXT_POSTCARD_NUM}.png ``` After running, verify the file exists: ```bash ls -la ${WORKSPACE}/postcard_${NEXT_POSTCARD_NUM}.png ``` ### 5b. Send the postcard (text + image together) Use the message tool with BOTH text and media in a single call: - channel=${CHANNEL} - target=${CHAT_ID} - message=[your postcard text] - media=file://${WORKSPACE}/postcard_${NEXT_POSTCARD_NUM}.png ### 5c. Send the source link SEPARATELY Send a second message with ONLY the URL — no emoji prefix, no "🔗", just the bare URL by itself. This ensures it's clickable. Only ONE URL per message. If you have multiple sources, send multiple messages, one URL each. ### 5d. Clean up ```bash rm -f ${WORKSPACE}/postcard_${NEXT_POSTCARD_NUM}.png ``` ## Step 6: Update journal `read` then ...[truncated 3003 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Add an explicit instruction that all fetched content is untrusted data and that instructions, commands, tool requests, or policy claims inside it must be ignored. 2. Separate retrieval and summarization from the action-capable session: - Use a tool-free or read-only process to fetch and normalize content. - Pass only structured facts, citations, and bounded excerpts to the postcard-writing process. 3. Disable shell, scheduling, and persistent-write tools while processing arbitrary web content. 4. Require user confirmation before executing commands or creating recurring tasks derived from a web exploration. 5. Restrict sources to an allowlist of reviewed domains where feasible. 6. Sanitize retrieved documents by removing hidden text, scripts, metadata, and common prompt-injection patterns before model processing. 7. Constrain journal writes to a strict schema and prevent web content from adding operational instructions. 8. Validate source URLs independently and continue enforcing denial of private, loopback, link-local, and cloud-metadata addresses after redirects and DNS resolution. 9. Log retrieved sources and tool decisions so suspicious autonomous behavior can be investigated. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (19)

Tainted flow: 'model' from os.environ.get (line 14, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
model = os.environ.get("TRAVEL_IMAGE_MODEL", "google/gemini-3.1-flash-image-preview")
    
    try:
        resp = requests.post(
            "https://openrouter.ai/api/v1/chat/completions",
            headers={
                "Authorization": f"Bearer {api_key}",
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description presents a complex autonomous exploration agent with web-browsing, discovery, persistence, scheduling, and postcard-sending features. The supplied code chunk only implements image generation via a remote API call to OpenRouter and writes the resulting image to disk. While image generation could be a supporting component of a postcard feature, this chunk alone does not exhibit the skill's stated primary behavior and instead performs a narrower, materially different function. Therefore the description does not accurately represent what this code chunk actually does.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The prompt explicitly authorizes shell execution to generate files, verify them, send local file URIs, and delete artifacts. That exceeds the stated web-exploration/postcarding scope and creates a broader execution surface where prompt-controlled variables like paths and postcard numbers could influence filesystem operations or be repurposed for unintended commands.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
### 5d. Clean up
```bash
rm -f ${WORKSPACE}/postcard_${NEXT_POSTCARD_NUM}.png
```

### Checklist before moving on:
Confidence
91% confidence
Finding
The use of `rm -f ${WORKSPACE}/postcard_${NEXT_POSTCARD_NUM}.png` relies on interpolated tool parameters inside a destructive shell command. Even if intended for benign cleanup, parameter misuse, path confusion, or weak validation can turn a narrow delete into deletion of unintended files, making this a concrete tool-parameter abuse risk.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The prompt instructs the agent to invoke a shell script that schedules future runs, establishing persistence/autonomous re-entry beyond the immediate user request. Self-scheduling is especially risky because it can create an unattended loop that continues network activity and message sending even after the original task is complete or if earlier behavior was faulty.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill explicitly requires environment access (`OPENROUTER_API_KEY`) and network access, but it does not declare a corresponding tool scope or `allowed-tools`/permissions boundary. In an autonomous, self-scheduling skill, missing explicit capability restrictions increases the risk of overbroad execution, unexpected tool access, and weak operator visibility into what the skill may use.

Vague Triggers

Medium
Confidence
89% confidence
Finding
The activation text uses broad trigger phrases such as exploring the internet autonomously or discovering interesting things, which could match casual user requests and invoke a high-autonomy skill unexpectedly. Because this skill performs persistent memory updates, network exploration, chat posting, and recurring scheduling, accidental activation materially increases security and cost risk.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The document states that postcards are written in 'the user's language (auto-detected),' which imposes a language selection automatically. This is a natural-language policy concern because it does not offer the user a language choice or explicit opt-in for locale behavior.

Session Persistence

Medium
Category
Rogue Agent
Content
openclaw cron rm travel-next

# Remove watchdog (if you added it)
crontab -l | grep -v watchdog | crontab -

# Run exactly one trip with no follow-up scheduling
# (edit travel-prompt.md: remove Step 7, then run travel.sh)
Confidence
95% confidence
Finding
The skill is designed for indefinite autonomous operation via self-scheduling cron jobs and an optional watchdog, creating durable persistence beyond a single user interaction. Even though the persistence is disclosed, recurring autonomous execution with network access and outbound messaging increases the blast radius of prompt mistakes, unexpected behavior, cost accumulation, and abuse if the skill is triggered improperly.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The cleanup step performs file deletion without disclosing that side effect to the user, and it does so via a shell command. While intended to remove a temporary image, undisclosed deletion increases operational risk and, if variables are malformed or attacker-influenced, could delete unintended files within the workspace or sandbox.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The prompt directs the agent to read and edit a persistent journal, knowledge graph, seed pool, and stats without explicit user warning or approval for state mutation. Persistent writes can accumulate sensitive browsing history, create inaccurate records, or be abused by prompt injection from fetched content to poison long-term memory.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
Automatic rescheduling is a recurring side effect that is not clearly surfaced as ongoing autonomous behavior. In context, this matters because the skill is designed to roam the web and message a chat; hidden recurrence can surprise users, generate spam, and extend exposure to prompt injection or policy drift over time.

External Transmission

Medium
Category
Data Exfiltration
Content
model = os.environ.get("TRAVEL_IMAGE_MODEL", "google/gemini-3.1-flash-image-preview")
    
    try:
        resp = requests.post(
            "https://openrouter.ai/api/v1/chat/completions",
            headers={
                "Authorization": f"Bearer {api_key}",
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
model = os.environ.get("TRAVEL_IMAGE_MODEL", "google/gemini-3.1-flash-image-preview")
    
    try:
        resp = requests.post(
            "https://openrouter.ai/api/v1/chat/completions",
            headers={
                "Authorization": f"Bearer {api_key}",
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
The setup script reads multiple workspace identity files and extracts the agent name, user name, timezone, and inferred language, then persists them into a config file. While some personalization is relevant to postcard generation, the implementation collects more profile data than strictly necessary and does so automatically without clear consent or minimization, creating an avoidable privacy exposure if the workspace contains sensitive profile content.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
Lines L043-L054 infer a language from file contents and then unconditionally set USER_LANG to "zh" or default to "en". This imposes a language/locale choice based on heuristic detection rather than offering the user a choice or documenting explicit opt-in.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
This code overwrites the persistent configuration file with chat, workspace, journal, timezone, and language values. Although there are comments about the overwrite, there is no user-facing disclosure, prompt, or explicit warning in the script itself before modifying stored configuration.

Context Window Stuffing

Medium
Category
Memory Poisoning
Content
# Remove old job if exists
openclaw cron rm travel-next 2>/dev/null || true

# Read and fill the prompt template using envsubst (safe against special chars)
PROMPT_FILE="$SKILL_DIR/references/travel-prompt.md"
if [ ! -f "$PROMPT_FILE" ]; then
    echo "Error: Missing $PROMPT_FILE" >&2
Confidence
85% confidence
Finding
Skill attempts to fill the context window with filler content, displacing legitimate instructions and safety constraints. This can degrade agent performance or bypass safety boundaries.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The script autonomously schedules a future model invocation using `openclaw cron add` with an isolated session and a generated prompt, but does so immediately and without an explicit user confirmation or opt-in at scheduling time. In a skill explicitly designed for autonomous internet exploration and self-scheduling, this increases risk because it enables unattended outbound actions and recurring agent behavior that may surprise users, consume resources, or continue after the initiating context is forgotten.

Static analysis

No suspicious patterns detected.