Back to skill

Security audit

Dream

Security checks for vulnerabilities and agentic risk

Overview

This memory skill is not proven malicious, but it needs review because it silently and permanently stores personal memory and includes unsafe local file-write and install patterns.

Review before installing. Use this only if you want OpenClaw to automatically process and preserve personal memory across sessions, including a permanent archive that dream forget does not erase. Pin the repository to a reviewed commit, avoid running mutable remote code blindly, and do not enable the scheduled SOUL.md behavior unless you are comfortable with silent memory updates. The file-write and Python-state handling issues should be fixed before trusting it with sensitive memory data.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
dream-tools.sh:92
Finding
Unrestricted File Replacement Through the Atomic Write Command<![CDATA[ ## Vulnerability Details **File Location**: `dream-tools.sh`, lines 92–112 **Vulnerability Type**: Arbitrary file overwrite **Risk Level**: High ### Vulnerable Code ```bash cmd_atomic_write() { local target="${1:-}" local tmpfile="${2:-}" [[ -z "$target" || -z "$tmpfile" ]] && die "--atomic-write 需要 <target> <tmpfile>" [[ ! -f "$tmpfile" ]] && die "tmp 文件不存在:$tmpfile" # 若目标是 MEMORY.md,检查字符数上限 if [[ "$(realpath "$target" 2>/dev/null)" == "$(realpath "$MEMORY_MD" 2>/dev/null)" ]] || \ [[ "$target" == *"MEMORY.md" ]]; then local size size=$(wc -c < "$tmpfile" | tr -d ' ') if [[ $size -gt $MEMORY_HARD_LIMIT ]]; then die "写入中止:tmp 文件大小 ${size} 字符,超过硬上限 ${MEMORY_HARD_LIMIT}。请先压缩内容。" fi log "MEMORY.md 写入校验通过:${size}/${MEMORY_HARD_LIMIT} 字符" fi ensure_dir "$target" # mv 在同一文件系统上是原子操作 mv "$tmpfile" "$target" log "原子写入完成:$target" } ``` ### Technical Analysis The `--atomic-write` command accepts both the source and destination paths from command-line arguments. It validates only that the source exists. It does not constrain the destination to `MEMORY_MD`, `DREAM_VAULT_PATH`, or `OPENCLAW_WORKSPACE`. The `MEMORY.md` check imposes a size limit but is not an authorization check. For every other destination, the function creates the destination's parent directory and moves the supplied file into place without validating the canonical destination path. This contradicts the README claim that all file operations are strictly scoped to the Dream vault and OpenClaw workspace. Quoting the variables prevents shell metacharacter injection, but it does not prevent arbitrary path selection, traversal, symlink-based redirection, or replacement of unrelated files. ### Attack Path 1. An attacker or untrusted agent instruction creates a file containing attacker-selected data. 2. The attacker invokes the helper with that file and an arbitrary user-writable target: `` ...[truncated 1091 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Define an explicit allowlist of writable files rather than accepting arbitrary destinations. 2. Resolve the destination with `realpath` or `realpath -m` before writing. 3. Require the canonical destination to equal `MEMORY_MD` or be located beneath an explicitly approved canonical root. 4. Reject targets containing symlink components and revalidate immediately before replacement to reduce time-of-check/time-of-use risks. 5. Create the temporary file in the destination directory so the final rename remains atomic and cannot cross filesystem boundaries. 6. Ensure the source temporary file is owned by the current user and is not a symlink. 7. Use restrictive permissions for generated files and directories. For example: ```bash canonical_workspace=$(realpath -m "$WORKSPACE_PATH") canonical_vault=$(realpath -m "$DREAM_VAULT_PATH") canonical_target=$(realpath -m "$target") case "$canonical_target" in "$canonical_workspace/MEMORY.md"|"$canonical_vault"/*) ;; *) die "Destination is outside approved Dream paths" ;; esac [[ -L "$target" || -L "$tmpfile" ]] && die "Symlink paths are not allowed" ``` If the command is intended only for `MEMORY.md`, remove the destination argument entirely and always write to the predefined `MEMORY_MD` path. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
dream-tools.sh:451
Finding
Python Code Injection Through the Last Review State File<![CDATA[ ## Vulnerability Details **File Location**: `dream-tools.sh`, lines 451–466 **Vulnerability Type**: Code injection through unsafe source-code interpolation **Risk Level**: High ### Vulnerable Code ```bash local last_review="从未" local hours_since="-" if [[ -f "$last_review_file" ]]; then last_review=$(cat "$last_review_file") # 计算距上次蒸馏的小时数 if command -v python3 &>/dev/null; then hours_since=$(python3 -c " from datetime import datetime last = datetime.strptime('$last_review', '%Y-%m-%d %H:%M') diff = datetime.now() - last print(int(diff.total_seconds() / 3600)) " 2>/dev/null || echo "-") fi fi ``` ### Technical Analysis The contents of `meta/last-review.txt` are read into `last_review` and interpolated directly into a Python program passed to `python3 -c`. The value is placed inside a single-quoted Python string without validation or escaping. A value containing a quote and additional Python statements can terminate the intended string and inject executable Python code. Shell quoting does not protect the generated Python source because the dangerous interpretation occurs inside Python after shell expansion. This issue is exploitable when `python3` is installed and an attacker can modify `last-review.txt`. The vault is intentionally writable by the skill and normally resides under the user's documents directory, making this state file part of the skill's writable attack surface. ### Attack Path 1. The attacker writes a syntactically valid Python injection payload to: ```text $DREAM_VAULT_PATH/meta/last-review.txt ``` 2. A payload can begin with a valid timestamp and then terminate the function call, for example: ```text 2026-01-01 00:00', '%Y-%m-%d %H:%M'); __import__('os').system('id > /tmp/dream-pwned'); # ``` 3. The user or agent runs: ```bash dream-tools.sh --status ``` 4. The file content is inserted into the `python3 -c` program. 5. Python parses and executes the injected `os.system` s ...[truncated 804 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Never embed file contents directly into generated source code. 1. Validate the timestamp using a strict allowlist expression: ```bash [[ "$last_review" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}[[:space:]][0-9]{2}:[0-9]{2}$ ]] || die "Invalid last-review timestamp" ``` 2. Pass the value as a positional argument instead of interpolating it into Python source: ```bash hours_since=$(python3 - "$last_review" <<'PY' import sys from datetime import datetime last = datetime.strptime(sys.argv[1], "%Y-%m-%d %H:%M") diff = datetime.now() - last print(int(diff.total_seconds() / 3600)) PY ) ``` 3. Prefer a shell-native or platform-specific date calculation if Python is not a declared dependency. 4. Create the state file with restrictive permissions and ensure that it is a regular file owned by the expected user. 5. Treat malformed state as data corruption: report it and avoid executing any dynamically generated program. ]]>

T03 · Remote Payload Retrieval and Execution

Warning
Location
readme.md:83
Finding
Installation Executes Code From an Unpinned Remote Repository<![CDATA[ ## Vulnerability Details **File Location**: `readme.md`, lines 83–96 **Vulnerability Type**: Mutable remote payload retrieval and execution **Risk Level**: Medium ### Vulnerable Code ```bash # 1. Clone into OpenClaw skills directory cd ~/.openclaw/workspace/skills git clone https://github.com/teman2050/dream-skill dream # 2. Make the script executable chmod +x dream/dream-tools.sh # 3. Set vault path (add to your shell config) echo 'export DREAM_VAULT_PATH="$HOME/Documents/Obsidian/dream-vault"' >> ~/.zshrc source ~/.zshrc # 4. Initialize ./dream/dream-tools.sh --init ``` ### Technical Analysis The installation procedure clones the current default branch of a remote Git repository and then directly makes its script executable and runs it. No release tag, commit hash, checksum, or cryptographic signature is verified. As a result, the code executed by users can differ from the artifact that was audited. The effective installation payload remains controlled by the future state of the remote repository. Compromise of the repository, maintainer account, or upstream branch could therefore introduce arbitrary code into the installation flow. The bundled `dream-tools.sh` itself does not make network calls. This finding concerns the documented installation process, which retrieves a mutable remote payload and executes it. ### Attack Path 1. The upstream repository, maintainer account, or default branch is compromised or maliciously modified. 2. An attacker adds a payload to `dream-tools.sh` or another installation-relevant file. 3. A user follows the documented installation instructions and clones the mutable default branch. 4. The user marks the downloaded script executable. 5. The user runs `./dream/dream-tools.sh --init`, executing the modified payload under the user's account. 6. Because the project is installed inside the OpenClaw skills directory, malicious skill instructions may also be loaded by the agent after the gateway restart. ### Impac ...[truncated 641 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Publish immutable, versioned releases. 2. Pin installation instructions to a reviewed release tag and preferably an exact commit hash. 3. Publish SHA-256 checksums or signed release artifacts. 4. Require users to verify the checksum or signature before making scripts executable. 5. Protect release publication with signed commits or tags, multi-factor authentication, and restricted maintainer access. 6. Avoid instructing users to execute code directly from a mutable default branch. 7. Document the expected checksum and audited version alongside the installation command. A hardened installation flow should resemble: ```bash git clone --branch v0.2.1 --depth 1 \ https://github.com/teman2050/dream-skill dream cd dream git verify-tag v0.2.1 printf '%s %s\n' '<published-sha256>' dream-tools.sh | sha256sum --check - chmod +x dream-tools.sh ./dream-tools.sh --init ``` For stronger reproducibility, additionally verify that the checked-out commit exactly matches the published audited commit. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (16)

Missing User Warnings

High
Confidence
98% confidence
Finding
The forget command is designed to delete or clear entries from memory files immediately and explicitly states '无需确认,直接执行'. Destructive operations on user memory without confirmation create a high risk of accidental or induced data loss, especially if triggered by ambiguous input, prompt injection, or mistaken semantic matches.

Anti-Refusal Statement

High
Category
Anti-Refusal
Content
OpenClaw's native memory mechanism has three unhandled issues:

**1. MEMORY.md grows indefinitely and silently truncates**
OpenClaw truncates MEMORY.md at 20,000 characters — no error, no warning. The AI quietly loses the second half of your context. You think it remembers, but it doesn't. Dream triggers compression at 18,000 characters, archiving stale content to the ledger so MEMORY.md always stays within the effective range.

**2. No permanent archive**
Important memories disappear once cleaned up. Dream maintains a `ledger.md` — append-only, never deleted. Anything that has ever reached long-term memory is preserved forever, even after being forgotten, and remains searchable for deep recall.
Confidence
80% confidence
Finding
Skill instructs the agent to omit warnings, disclaimers, or ethical commentary. Stripping safety caveats hides risk from the user and is a common jailbreak preamble.

Vague Triggers

High
Confidence
97% confidence
Finding
The manual triggers include broad natural-language phrases like `dream`, `review`, and `what do you remember about me`, which are likely to appear in normal conversation. In an agent environment, this can cause unintended invocation of memory operations, including search, indexing, or modification of persistent user data without a deliberate command boundary.

Intent-Code Divergence

Medium
Confidence
93% confidence
Finding
At L042 the skill explicitly states its role is 'distiller, not capturer'. However, L103-L119 and L245-L250 describe real-time capture behavior during conversations, including directly writing detected information into MEMORY.md and memory/YYYY-MM-DD.md. This is an active contradiction in the skill's own documentation about intended behavior.

Intent-Code Divergence

Medium
Confidence
90% confidence
Finding
L068-L070 states that self-built search indexing is intentionally omitted and that search is delegated to native OpenClaw capabilities. But L214-L228 introduces dream-tools.sh --ledger-search over ledger-index.json, and L245-L250/L263 describe maintaining and searching an Obsidian index. That is a meaningful contradiction between the declared design intent and the described functionality.

Ssd 3

Medium
Confidence
97% confidence
Finding
The skill continuously records user information from conversations into persistent memory and also maintains a permanent ledger archive. Continuous capture combined with long-term retention materially increases the sensitivity of the system because even transient disclosures can become durable records, enabling profiling, unintended reuse, and greater impact from compromise or misuse.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill directs the agent to persist conversation-derived personal data into MEMORY.md and daily memory files automatically during live chats, without explicit just-in-time notice or user confirmation. This creates a meaningful privacy and consent risk because sensitive user information can be stored permanently or semi-permanently based on the agent's judgment rather than clear user authorization.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The scheduled review silently processes prior conversation logs and updates persistent memory artifacts in the background with no user-facing warning. Silent background mutation of personal memory stores reduces transparency, weakens informed consent, and can preserve or reshape sensitive context without the user's awareness.

Ssd 3

Medium
Confidence
95% confidence
Finding
The skill intentionally solicits and persists broad personal context such as tool preferences, core values, and important relationships into durable memory. Collecting and retaining this category of personal profiling data beyond immediate task necessity increases privacy exposure and can amplify harm if the memory store is misused, over-shared, or later surfaced unexpectedly.

Ssd 3

Medium
Confidence
93% confidence
Finding
The wakeup flow automatically surfaces stored memory and archive summaries at the first conversation after inactivity. Auto-revealing prior personal context without being asked can disclose sensitive historical information in the wrong moment, to the wrong viewer, or in a context where the user did not intend prior memories to be resurfaced.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This shell script presents its description, usage, command help, and operational messages in Chinese, which imposes a specific language on users. The policy allows locale constraints only when they are optional or clearly justified as region-specific, neither of which is stated here.

Session Persistence

Medium
Category
Rogue Agent
Content
--check-idle)             cmd_check_idle ;;
    --check-size)             cmd_check_size ;;
    --hash)                   cmd_hash "$@" ;;
    --atomic-write)           cmd_atomic_write "$@" ;;
    --ledger-append)          cmd_ledger_append "$@" ;;
    --ledger-search)          cmd_ledger_search "$@" ;;
    --ledger-mark-reemergence) cmd_ledger_mark_reemergence "$@" ;;
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README describes permanent archival and unattended automatic operation, but does not foreground a clear privacy warning or informed-consent notice. Because the skill stores personal memory indefinitely and operates silently on a schedule, users may enable it without understanding the long-term retention and autonomous processing implications.

Ssd 3

Medium
Confidence
97% confidence
Finding
The skill is intentionally designed to preserve personal context indefinitely and to restore information that the user previously cleared from active memory if it 're-emerges.' In context, this undermines user expectations around deletion and increases the sensitivity and persistence of stored personal data, creating privacy and compliance risks if the archive is accessed, leaked, or misused.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The README makes inconsistent claims about search behavior: it says `dream search` uses native OpenClaw search and does not build its own index, while elsewhere it documents `ledger-index.json` and an `obsidian-index/` search structure maintained by Dream. This kind of discrepancy is security-relevant because users may underestimate what data is being indexed, retained, and queried, which affects informed consent and trust boundaries.

Natural-Language Policy Violations

Low
Confidence
77% confidence
Finding
The activation phrases and operational instructions are presented in Chinese and imply the skill responds to Chinese-language triggers such as '复盘' and '整理记忆' without documenting language choice. Under the language/locale policy, forcing a specific language without user opt-in can be a policy concern unless explicitly justified.

Static analysis

No suspicious patterns detected.