Back to skill

Security audit

Dream

Security checks for vulnerabilities and agentic risk

Overview

This memory-management skill matches its stated purpose, but it needs Review because it permanently retains personal memory and ships a helper script with unsafe file-write and code-injection behavior.

Install only if you are comfortable with automatic local memory rewriting, permanent archives, and personal context resurfacing later. Before use, restrict atomic writes to approved paths, fix the Python timestamp handling, require confirmation for forget/delete actions, and add a real full-erasure path for ledger and re-emergence records.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
dream-tools.sh:92
Finding
Unrestricted Atomic-Write Command Allows Arbitrary File Replacement<![CDATA[ ## Vulnerability Details **File Location**: `dream-tools.sh`, lines 92–113 **Vulnerability Type**: Arbitrary file write through missing path authorization **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` operation accepts both its source and destination from command-line arguments. It does not verify that the canonical destination is located under either `DREAM_VAULT_PATH` or `OPENCLAW_WORKSPACE`. The `realpath` comparison only determines whether to apply the `MEMORY.md` size limit. It is not an access-control check. For any destination that does not end in `MEMORY.md`, the script creates the destination's parent directory and moves the supplied file over the destination. Consequently, any component or user able to invoke this helper can replace any file writable by the OpenClaw operating-system account. This directly contradicts the security claim in `readme.md` that all file operations are strictly scoped to the vault and workspace. Path and symlink behavior also require hardening. A lexical prefix check alone would not be sufficient because traversal components and symlinks could redirect writes outside an approved root. ### Attack Path 1. Th ...[truncated 1429 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Canonicalize the destination and enforce an explicit allowlist of permitted files or directories. 2. Require every destination to resolve beneath `DREAM_VAULT_PATH` or `OPENCLAW_WORKSPACE`. 3. Reject symbolic-link destinations and symbolic-link parent components. 4. Restrict `--atomic-write` to known destinations such as the configured `MEMORY_MD` rather than accepting a general path. 5. Create temporary files in the destination directory to preserve same-filesystem atomic replacement. 6. Verify ownership and permissions before replacement. 7. Use `mv -- "$tmpfile" "$target"` and similar end-of-options markers as defense in depth. 8. Add negative tests covering absolute paths, `..` traversal, symlink escapes, shell configuration files, and destinations outside approved roots. A hardened implementation should derive the target internally where possible instead of trusting a caller-supplied path. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
dream-tools.sh:455
Finding
Persisted Timestamp Is Interpolated into Executable Python Source<![CDATA[ ## Vulnerability Details **File Location**: `dream-tools.sh`, lines 455–465 **Vulnerability Type**: Code injection through unsafe source-code construction **Risk Level**: High ### Vulnerable Code ```bash 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 inserted directly inside a single-quoted Python string embedded in the `python3 -c` program. Shell quoting does not make this safe: variable expansion occurs inside the outer shell double-quoted argument, and the expanded data becomes part of the Python source. A crafted timestamp can close the Python call, inject another Python statement, and comment out the remaining generated source. This is source-code injection rather than ordinary malformed-input handling. No strict format validation occurs before interpolation. For example, a value shaped like the following can preserve a valid initial timestamp parse and then inject another statement: ```text 2026-01-01 00:00', '%Y-%m-%d %H:%M'); __import__('os').system('id'); # ``` The generated Python source executes the injected `os.system` call when `--status` is invoked. ### Attack Path 1. The attacker modifies: ```text DREAM_VAULT_PATH/meta/last-review.txt ``` This may occur through local write access, a compromised cooperating component, or the unrestricted `--atomic-write` operation identified separately. 2. The attacker stores a Python-breaking payload in the file: ```text 2026-01-01 00:00', '%Y-%m-%d %H:%M'); __import__('os').system('id'); # ``` 3. A user or scheduled agent invokes: ```bash ./dream-too ...[truncated 864 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Never interpolate file content into executable source. Pass the timestamp as a normal argument: ```bash hours_since=$(python3 - "$last_review" <<'PY' from datetime import datetime import sys last = datetime.strptime(sys.argv[1], "%Y-%m-%d %H:%M") diff = datetime.now() - last print(int(diff.total_seconds() / 3600)) PY ) ``` Additionally: 1. Validate the input first with a strict pattern such as `^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$`. 2. Reject unexpected newlines and excessive input length. 3. Handle invalid dates explicitly without executing dynamically generated code. 4. Ensure `last-review.txt` is writable only by the expected account. 5. Apply the path restrictions recommended for `--atomic-write` so that untrusted callers cannot replace the state file. 6. Add tests containing quotes, semicolons, comments, newlines, and Python expressions. ]]>

other

Warning
Location
Skill.md:264
Finding
Forget Operation Retains Requested Data in a Permanent Searchable Archive<![CDATA[ ## Vulnerability Details **File Location**: `Skill.md`, lines 264–279 **Vulnerability Type**: Privacy and incomplete data erasure **Risk Level**: Medium ### Relevant Skill Instructions ```markdown ### `dream forget <描述>` — 从 memory 中清除 在 `memory/YYYY-MM-DD.md` 和 MEMORY.md 中语义搜索匹配条目并清除。 无需确认,直接执行。 **Re-emergence 机制:** 清除时将条目摘要写入 `meta/removed-entries.json`,记录清除时间和内容哈希。 后续对话中若该内容再次出现,自动触发 re-emergence,重新写入 MEMORY.md 并提升优先级。 被遗忘后又出现的内容,比从未被遗忘的内容更值得保留。 ledger 中的记录不受 `dream forget` 影响,永久保留。 执行时告知:「已从记忆中清除,永久档案不受影响。」 ``` In English, these instructions state that `dream forget` removes matching entries from daily memory files and `MEMORY.md`, but records a summary in `removed-entries.json` and leaves ledger records permanently intact. ### Technical Analysis The operation is named and presented as a memory-forgetting function, but its erasure scope excludes the permanent ledger. It also deliberately writes a summary and content hash to re-emergence tracking state. The retention behavior is disclosed in the skill instructions, so it is not a covert exfiltration mechanism. Nevertheless, it creates a privacy and lifecycle-control weakness: sensitive information can remain searchable after the active-memory copies have been removed. The design provides no documented command for deleting or redacting the retained ledger record. Because the ledger is described as append-only and never deleted, a user cannot achieve complete erasure through the provided interface. ### Attack Path 1. Sensitive personal information is captured and eventually archived in `ledger.md` and `ledger-index.json`. 2. The user invokes `dream forget` for that information. 3. Dream removes matching data from active memory files. 4. The ledger copy remains unchanged, while a summary and hash may also be added to `meta/removed-entries.json`. 5. A later `--ledger-search` or direct file read retrieves the supposedly forgotten information. ### Impact Assessment This issue does not provid ...[truncated 515 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Provide a separate explicit command for complete erasure from: - `MEMORY.md` - `memory/YYYY-MM-DD.md` - `ledger.md` - `ledger-index.json` - `removed-entries.json` - Obsidian indexes where applicable 2. Clearly distinguish “remove from active context” from “delete everywhere” in command names and confirmations. 3. Require confirmation that identifies every retained or deleted storage location. 4. Support ledger redaction or cryptographic erasure rather than enforcing unconditional permanent retention. 5. Add configurable retention periods and automatic expiration for sensitive categories. 6. Ensure backup and synchronization documentation explains that deletion must propagate to replicas. 7. Allow users to disable re-emergence tracking for information they intentionally erased. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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 (13)

Intent-Code Divergence

High
Confidence
98% confidence
Finding
The file allocation section labels daily memory files as read-only for Dream, yet later workflows direct the skill to write to and delete from those same files. This inconsistency is dangerous because it broadens write/destructive scope beyond what reviewers expect, increasing the risk of unauthorized modification or loss of memory data.

Missing User Warnings

High
Confidence
98% confidence
Finding
The `dream forget` workflow performs semantic search and deletion across memory stores without confirmation. Because the match is fuzzy and the action is immediate, the skill can delete the wrong entries or be triggered by ambiguous requests, causing irreversible loss or corruption of user memory state.

Ssd 3

High
Confidence
99% confidence
Finding
The forget workflow tells the user content has been cleared from memory while explicitly preserving permanent copies in the ledger. This is dangerous because it creates a false expectation of deletion, undermines user trust, and can retain sensitive data indefinitely despite a deletion request.

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.

Intent-Code Divergence

Medium
Confidence
94% confidence
Finding
The skill claims Dream is only a distiller and not a capture mechanism, but later instructs the agent to write newly observed conversational information directly into MEMORY.md during live conversations. This mismatch can mislead operators and users about when persistence occurs, weakening informed consent and making unintended data retention more likely.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The skill instructs the agent to write conversation-derived data into MEMORY.md in real time without telling the user at the moment of persistence. Silent background writes of profile, preference, and project data undermine user awareness and can store sensitive information the user did not expect to be retained.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The scheduled `dream review` process is designed to run silently and modify persistent memory artifacts without notifying the user. Background mutation of long-lived memory increases privacy and integrity risk because sensitive content may be transformed, archived, or surfaced later without contemporaneous user awareness.

Ssd 3

Medium
Confidence
85% confidence
Finding
The skill explicitly stores and later surfaces personal data such as preferences, projects, and important relationships in MEMORY.md, ledger files, and wakeup summaries. Even if intended for continuity, persistent aggregation and resurfacing of personal context increases privacy exposure if the files are accessed by other tools, users, or future sessions unexpectedly.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The header comments and all user-facing help/output strings are written only in Chinese, which effectively imposes a language choice on users without offering an alternative or opt-in. The policy specifically calls for flagging language or locale constraints when the skill forces a specific language without user choice.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The script invokes the external `openclaw` CLI via a shell command to query agent status. Although the code comments describe the behavior, there is no user-facing disclosure, confirmation, or prompt around this subprocess execution, and shell execution is one of the operations that requires some visible warning unless clearly disclosed as part of the skill behavior.

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
86% confidence
Finding
The script implements persistent recording of conversation-derived or agent-derived data into multiple long-lived files such as `MEMORY.md`, `ledger.md`, `ledger-index.json`, `removed-entries.json`, and `active-days.json`. This creates session persistence that can retain sensitive user content, behavioral history, and metadata without any built-in consent, retention control, access restriction, or data minimization, which is a real privacy/security risk if secrets or personal data are captured.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The skill advertises that it runs silently every night and modifies memory-related files automatically, but the README does not emphasize ongoing background data mutation, retention consequences, or operator visibility. This creates a consent and integrity risk: users may not realize their active memory is being rewritten, compressed, archived permanently, and potentially reintroduced later.

Vague Triggers

Medium
Confidence
96% confidence
Finding
The documented manual triggers are broad natural-language phrases such as "review" and "what do you remember about me," which can plausibly occur in ordinary conversation and unintentionally invoke file-reading or state-changing behavior. In a memory-management skill, accidental activation is risky because it may expose private memory contents, mutate MEMORY.md, or trigger archive/search operations without clear user intent.

Static analysis

No suspicious patterns detected.