Back to skill

Security audit

Dream

Security checks for vulnerabilities and agentic risk

Overview

This memory skill is not clearly malicious, but it needs Review because it stores and rewrites personal memory automatically and includes helper-script paths that can exceed the advertised file scope.

Review carefully before installing. This skill is designed to preserve and reuse personal memory long term, including a permanent ledger that `dream forget` does not erase. Avoid it for sensitive, shared, regulated, or multi-user workspaces unless you are comfortable with silent scheduled maintenance, broad memory indexing, and the current helper-script security weaknesses being fixed first.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
dream-tools.sh:91
Finding
Unrestricted Arbitrary File Replacement Through --atomic-write<![CDATA[ ## Vulnerability Details **File Location**: `dream-tools.sh`, lines 91–112 **Vulnerability Type**: Arbitrary file write and replacement **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 caller-controlled source and destination paths without enforcing an allowed directory or destination list. Although special size validation is attempted for paths resembling `MEMORY.md`, every other destination is accepted without scope validation. The function also calls `ensure_dir`, which creates the destination's parent directory, and then uses `mv` to replace the destination. It does not verify that: - The destination is the configured `MEMORY_MD`. - The destination is inside `DREAM_VAULT_PATH` or `OPENCLAW_WORKSPACE`. - The source is an approved temporary file. - The source or destination does not traverse symbolic links. - The destination is a regular file rather than a sensitive configuration or instruction file. The suffix test `[[ "$target" == *"MEMORY.md" ]]` is not a security boundary. It only applies a size limit and still permits an arbitrary path ending in `MEMORY.md`. This behavior contradicts the README claim that file operations ...[truncated 1453 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Restrict destinations to an explicit allowlist, preferably only `MEMORY_MD` for this operation. 2. Canonicalize and validate both paths before performing any write. 3. If multiple destinations are required, ensure each canonical path is either an explicitly approved file or a descendant of an approved root. 4. Reject symbolic links in the source, destination, and all relevant parent path components. 5. Require the temporary file to be a regular file created in the destination directory with restrictive permissions. 6. Use `mktemp` in the target directory so that the final rename occurs on the same filesystem. 7. Avoid suffix-based authorization such as `*"MEMORY.md"`. 8. Refuse destinations containing traversal components or resolving outside the approved roots. 9. Consider replacing the generic interface with a purpose-specific command: ```bash dream-tools.sh --write-memory <approved-temporary-file> ``` 10. Add tests covering absolute paths, `..` traversal, symlink traversal, paths outside the workspace, and unrelated files ending in `MEMORY.md`. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
dream-tools.sh:453
Finding
Python Code Injection Through last-review.txt<![CDATA[ ## Vulnerability Details **File Location**: `dream-tools.sh`, lines 453–466 **Vulnerability Type**: Code injection through generated Python source **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 content of `meta/last-review.txt` is inserted directly into a Python program passed to `python3 -c`. No syntax-safe argument passing or format validation is performed. A malicious value can terminate the quoted timestamp, supply additional Python statements, and comment out the remainder of the generated line. Because Python can import modules and start processes, this provides command execution under the account running the helper. Shell quoting of `"$last_review"` does not protect the Python interpreter. The unsafe interpretation occurs after shell expansion, when Python parses the resulting source code. ### Attack Path 1. An attacker or compromised local component obtains write access to: ```text $DREAM_VAULT_PATH/meta/last-review.txt ``` 2. The attacker stores a value structured like: ```text 2026-01-01 00:00', '%Y-%m-%d %H:%M'); __import__('os').system('id > /tmp/dream-pwned'); # ``` 3. The user or agent invokes: ```bash dream-tools.sh --status ``` 4. The generated Python line becomes equivalent to: ```python last = datetime.strptime('2026-01-01 00:00', '%Y-%m-%d %H:%M'); __import__('os').system('id > /tmp/dream-pwned'); #', '%Y-%m-%d %H:%M') ``` 5. Python executes the injected operating-system command. This path requires the attacker to influence the state file. ...[truncated 858 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Never interpolate file content into Python source. Pass the value as an argument: ```bash if [[ "$last_review" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}\ [0-9]{2}:[0-9]{2}$ ]]; then 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 ) else hours_since="-" fi ``` Additional hardening should include: 1. Validate the timestamp against a strict format before parsing. 2. Reject multiline input and unexpected trailing data. 3. Apply restrictive permissions to the vault and metadata files. 4. Write state files atomically using temporary files in the same directory. 5. Avoid dynamic-language interpreters for simple date arithmetic where a safe platform utility is available. 6. Add regression tests with quotes, semicolons, newlines, comments, and Python expressions in `last-review.txt`. ]]>

other

Warning
Location
Skill.md:270
Finding
Forget Operation Retains and May Reactivate Sensitive Personal Data<![CDATA[ ## Vulnerability Details **File Location**: `Skill.md`, lines 270–278 **Vulnerability Type**: Incomplete deletion and unexpected data reactivation **Risk Level**: Medium ### Relevant Instructions ```markdown 在 `memory/YYYY-MM-DD.md` 和 MEMORY.md 中语义搜索匹配条目并清除。 无需确认,直接执行。 **Re-emergence 机制:** 清除时将条目摘要写入 `meta/removed-entries.json`,记录清除时间和内容哈希。 后续对话中若该内容再次出现,自动触发 re-emergence,重新写入 MEMORY.md 并提升优先级。 被遗忘后又出现的内容,比从未被遗忘的内容更值得保留。 ledger 中的记录不受 `dream forget` 影响,永久保留。 执行时告知:「已从记忆中清除,永久档案不受影响。」 ``` ### Technical Analysis The `dream forget` operation removes matching content from active memory files but deliberately retains related data in two places: - Existing ledger records remain permanently stored and searchable. - A summary and content hash are written to `removed-entries.json`. If related content appears later, the skill automatically restores the forgotten subject to `MEMORY.md` and raises its retention priority. Consequently, “forget” is not a permanent erasure operation and can cause information the user attempted to remove to return to active context. The detailed Skill instructions disclose that the ledger is unaffected. However, the command name, automatic execution without confirmation, and reactivation behavior create a material privacy risk, particularly where users interpret “forget” as deleting sensitive information from the system. ### Attack Path 1. Sensitive personal information is recorded in `MEMORY.md` and later archived in `ledger.md`. 2. The user invokes `dream forget` for that information. 3. The active-memory entry is removed, but: - The ledger record remains. - A summary and hash are added to `removed-entries.json`. 4. A later conversation contains semantically or lexically similar information. 5. Re-emergence detection matches the removed-entry summary. 6. The skill restores the subject to active `MEMORY.md` and increases its retention priority. No external attacker is required for this privacy failure. An attacker w ...[truncated 719 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Separate temporary active-memory removal from permanent erasure: - `dream hide` or `dream forget-active` for active-memory removal. - `dream erase` for permanent deletion. 2. Require explicit confirmation before permanent erasure and clearly list all affected storage locations. 3. For permanent erasure, remove matching records from: - `MEMORY.md` - `memory/YYYY-MM-DD.md` - `ledger.md` - `ledger-index.json` - `removed-entries.json` - Obsidian indexes where applicable 4. Add a tombstone or suppression record that prevents explicitly erased information from triggering re-emergence, without retaining the sensitive content itself. 5. Clearly state before execution that the current `forget` operation does not erase the permanent archive. 6. Provide a verification report listing which files were modified and whether residual copies remain. 7. Document limitations caused by backups, synchronization history, Git history, or external Obsidian storage. 8. Protect retained memory and ledger files with restrictive filesystem permissions. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (18)

Intent-Code Divergence

High
Confidence
95% confidence
Finding
The skill declares daily memory files are read-only for Dream, but later authorizes write and delete operations against those same memory stores. That contradiction can cause an implementation to exceed intended boundaries and modify canonical user-memory records, increasing the chance of silent tampering, data loss, or unauthorized persistence behavior.

Missing User Warnings

High
Confidence
98% confidence
Finding
`dream forget` performs destructive deletion from memory stores without confirmation. A mistaken match, ambiguous description, prompt injection, or accidental invocation could irreversibly remove user data or selectively erase context that would otherwise help detect abuse or preserve user intent.

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 documented trigger phrases are extremely broad, including generic words like `dream`, `review`, and a natural-language query asking what the system remembers. In an agent setting, such triggers can be activated during ordinary conversation, causing unintended memory operations or disclosure of sensitive memory contents without clear user intent.

Natural-Language Policy Violations

Medium
Confidence
78% confidence
Finding
The manifest description and the rest of the skill are written as Chinese-only instructions and trigger phrases, with no indication that users may choose another language. Under the stated policy, forcing a specific language without opt-in is a natural-language policy concern unless the locale restriction is clearly justified.

Intent-Code Divergence

Medium
Confidence
91% confidence
Finding
The documentation states 'Dream 的职责是蒸馏者,不是捕获者', which narrows intent to post-hoc distillation only. However, later sections direct the skill to '直接写入 MEMORY.md' during live conversation and to also record into daily memory files, which is active capture behavior rather than mere distillation.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill authorizes automatic real-time writes to persistent memory during conversation without clear user-facing notice or opt-in. This can cause users to disclose sensitive information under the assumption it is ephemeral, while the agent silently persists it to long-lived files.

Ssd 3

Medium
Confidence
97% confidence
Finding
The skill prescribes broad ongoing capture of user preferences, decisions, projects, corrections, and inferred content into persistent memory files. Without narrow retention rules, sensitivity checks, or explicit consent, this creates a durable behavioral profile that can be misused, over-retained, or exposed through later summaries and search operations.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
Scheduled silent maintenance performs background writes, compaction, and archival without clear upfront warning or runtime visibility. This is dangerous because the system can alter or move user data while the user is unaware, making consent, accountability, and incident investigation harder.

Ssd 3

Medium
Confidence
95% confidence
Finding
The skill directs persistent retention and summarization of personal and contextual information for an Obsidian index without meaningful minimization, consent, or sensitivity filtering. In context, this is more dangerous because the skill is explicitly designed for long-term memory accumulation, increasing privacy risk, profiling, and secondary use of data beyond the user's immediate request.

Ssd 3

Medium
Confidence
96% confidence
Finding
The wakeup flow automatically surfaces stored memory and archive summaries at the first new conversation after inactivity. This can expose sensitive historical information at an unexpected moment, including in shared environments or when the user did not ask for a recap, turning persistence into unsolicited disclosure.

Natural-Language Policy Violations

Medium
Confidence
98% confidence
Finding
This shell script embeds its description and usage text in Chinese, and the command help later in the file is also Chinese-only. Because the file does not provide any opt-in, alternative language, or justification for a Chinese-only locale, it creates a natural-language policy concern under the language/locale rule.

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
84% confidence
Finding
The script intentionally persists session-derived data to disk across multiple files, including MEMORY.md, ledger.md, ledger-index.json, removed-entries.json, and active-days.json. In an agent skill context, this creates a real retention risk: sensitive prompts, user content, URLs, or operational history may be stored long-term without redaction, minimization, access controls, or consent checks, increasing exposure if the workspace or vault is later accessed by another user, process, or backup system.

Ssd 3

Medium
Confidence
96% confidence
Finding
The README explicitly describes indefinite preservation of user memories in a searchable permanent archive, which materially increases privacy and data-exposure risk. In a memory skill, retaining sensitive personal information forever—even after it is 'forgotten' from active memory—creates a larger attack surface and undermines user expectations around deletion.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill advertises silent nightly operation and permanent archival of memories, but the usage section does not foreground the privacy and persistence implications. Users may enable it without understanding that personal data is retained indefinitely and files are modified automatically, increasing the risk of uninformed consent and accidental over-retention of sensitive information.

Ssd 3

Medium
Confidence
97% confidence
Finding
Returning a full `MEMORY.md` snapshot in response to a natural-language query can expose sensitive personal context too broadly, especially if the trigger is matched unintentionally or in mixed-user/shared environments. This creates a straightforward data disclosure risk because memory contents may include profile, relationship, and current-state information accumulated over time.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The section says '`dream search` calls the native command, does not build its own index,' which asserts no custom indexing behavior. Elsewhere, the README explicitly describes `obsidian-index/` files being created and a `dream index <content>` command that saves articles or webpages into that index, directly contradicting the claim.

Intent-Code Divergence

Low
Confidence
88% confidence
Finding
The security claim is absolute about file-operation scope. However, the installation steps instruct appending an export line to `~/.zshrc`, which is a write outside `DREAM_VAULT_PATH` and the OpenClaw workspace, so the documentation overstates the scope restriction.

Static analysis

No suspicious patterns detected.