Back to skill

Security audit

Memory Dream

Security checks for vulnerabilities and agentic risk

Overview

This memory-management skill has a coherent purpose, but it automatically captures and rewrites persistent agent memory with under-disclosed data access and weak boundaries.

Review carefully before installing. This skill should only be used if you are comfortable with automatic LLM processing of memory files, recent conversation content, and transcript excerpts, and with automatic writes to persistent memory. Configure memoryFiles conservatively, consider disabling capture if supported, keep memory files under version control or backups, and avoid using it in workspaces containing sensitive conversations or credentials until path validation, disclosure, redaction, and review controls are improved.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (3)

T02 · Agent Memory Poisoning

Error
Location
src/capture.ts:8
Finding

Persistent Agent Memory Poisoning Through Untrusted LLM Prompt Content

Content
View full analysis
- Be brief and specific. Do NOT include commentary, headers, or explanations outside the bullet list.`; } ``` ```ts const prompt = buildCapturePrompt(conversationText); const result = await callCaptureLlm(prompt, config, api, agentId); const trimmed = result.trim(); if (!trimmed || trimmed === "NOTHING" || !trimmed.startsWith("-")) { return false; } const date = new Date().toISOString().split("T")[0]; const entry = `\n## [${date}] Captured\n${trimmed}\n`; const stagingPath = join(workspaceDir, STAGING_FILE); await mkdir(workspaceDir, { recursive: true }); let existing = ""; try { existing = await readFile(stagingPath, "utf-8"); } catch { // File doesn't exist yet — start fresh } await writeFile(stagingPath, existing + entry, "utf-8"); ``` ...[truncated 3985 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/consolidate.ts:10
Finding

Unrestricted Memory File Paths Permit Reads and Writes Outside the Workspace

Content
View full analysis
0 ? (config.memoryFiles as string[]) : defaultConfig.memoryFiles, ``` ```ts async function readMemoryFile( workspaceDir: string, filename: string ): Promise { try { return await readFile(join(workspaceDir, filename), "utf-8"); } catch { return null; } } ``` ```ts for (const filename of config.memoryFiles) { const content = await readMemoryFile(workspaceDir, filename); if (content === null) { skippedFiles.push(filename); logger.warn(`[memory-dream] Skipping ${filename} — file not found`); continue; } logger.info(`[memory-dream] Consolidating ${filename}`); try { const prompt = buildConsolidationPrompt( filename, content, lcmSummaries, transcripts, stagingContent ); const consolidated = await callLlm(prompt, config, api, agentId); if (consolidated && consolidated.trim().length > 0) { const originalLines = content.split("\n").length; const newLines = consolidated.trim().split("\n").length; const delta = newLines - originalLines; const deltaStr = delta <= 0 ? `${Math.abs(delta)} lines removed` : `${delta} lines added`; logger.info(`[memory-dream] Writing ${filename}: ${originalLines} → ${newLines} lines (${deltaStr})`); await writeFile(join(workspaceDir, filename), consolidated.trim() + "\n", "utf-8"); updatedFiles.push(filename); } } catch (err) { logger.error(`[memory-dream] Failed to consolidate ${filename}: ${err}`); ...[truncated 2027 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
src/scheduler.ts:16
Finding

Conversation Content Is Captured and Sent to a Model by Default Without Clear Skill Disclosure

Content
View full analysis
; const lastUser = rawCtx.lastUserMessage ?? rawCtx.userMessage ?? rawCtx.message; const lastAssistant = rawCtx.lastAssistantMessage ?? rawCtx.assistantMessage; if (lastUser || lastAssistant) { const conversationText = [ lastUser ? `User: ${String(lastUser)}` : null, lastAssistant ? `Assistant: ${String(lastAssistant)}` : null, ] .filter(Boolean) .join("\n"); const workspaceDir = api.runtime.agent.resolveAgentWorkspaceDir( api.config, agentId ?? "main" ); captureFromTurn( stateDir, workspaceDir, conversationText, cfg, api, agentId ?? "main" ).catch((err: unknown) => { api.logger.warn(`[memory-dream] Capture error (non-blocking): ${String(err)}`); }); } } ``` ```ts async function callCaptureLlm( prompt: string, config: DreamConfig, api: OpenClawPluginApi, agentId: string ): Promise { const sessionKey = `agent:${agentId}:subagent:memory-dream-capture-${Date.now()}`; const model = config.captureModel ?? "claude-haiku-4-5-20251001"; const { runId } = await api.runtime.subagent.run({ sessionKey, message: prompt, model, deliver: false, }); const result = await api.runtime.subagent.waitForRun({ runId, timeoutMs: 30_000 }); if (result.status !== "ok") { throw new Error(`Capture subagent failed: ${result.status}`); } ``` The documented configuration in `SKILL.md` lists ...[truncated 2136 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (18)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill documentation claims it safely consolidates and prunes existing memory after session thresholds, but the analyzed behavior reportedly performs different actions such as capturing new memory signals and writing to a staging file without the promised safeguards. This kind of description-behavior mismatch is dangerous because operators may grant trust, enable automatic execution, or expose sensitive memory workflows under false assumptions, leading to unintended data retention, silent modification, or privacy-impacting behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README promotes automatic, background LLM-driven rewriting of user memory files but does not clearly warn that the tool can modify or delete important content based on probabilistic model output. Because these files may contain durable preferences, history, or operational context, silent consolidation can cause integrity loss, accidental removal of important data, or subtle corruption that persists across future sessions.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The automatic trigger language is vague enough that users may not understand when consolidation runs, what counts as a session boundary, and what exclusions prevent execution. Ambiguous activation boundaries are dangerous for background file-modifying skills because they can trigger unexpectedly in sensitive contexts, causing unreviewed memory edits or retention changes.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The description emphasizes quiet background operation but does not clearly warn users that memory files may be modified automatically. In a skill that handles agent memory, undisclosed automatic writes are risky because they can alter persistent context, remove information, or introduce privacy and integrity issues without informed user consent.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The plugin description presents the skill as a post-session memory consolidation tool, but this code also captures recent user and assistant conversation content on every agent start when enableCapture is set. That creates a material mismatch between advertised behavior and actual data collection, which can undermine informed consent and cause sensitive conversation data to be persisted unexpectedly.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code automatically packages last user and assistant messages into conversationText and sends them to captureFromTurn without any visible notice or consent mechanism in this file. In a memory plugin context, this is risky because conversations may contain secrets, personal data, or confidential workspace context that users do not expect to be persistently stored.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The plugin starts background consolidation automatically and writes state, and likely memory artifacts, without any explicit user-facing disclosure in this code path. Silent background processing of memory files can expose sensitive persisted data to unintended retention, transformation, or leakage through logs and downstream LLM-based consolidation steps.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The prompt explicitly asks the model to identify and preserve 'memory-worthy signals' such as preferences, corrections, decisions, and facts for future sessions. In a memory-management skill this is contextually more dangerous, because the feature is designed to convert free-form user conversation into durable profile-like memory, which can easily include sensitive personal or operational details.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code does more than post-session consolidation: it actively derives new persistent memory from live conversation content and stores it in a workspace file. That expands the skill's data-collection scope beyond its stated role and can lead to retention of sensitive or user-unexpected information, especially because capture is automatic and silent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The full conversationText is embedded into a prompt and sent to a subagent model, creating a data-sharing path for potentially sensitive user content. Because this file shows no notice, consent, minimization, or redaction, users may unknowingly have private details transmitted to another model component and then persisted.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill reads recent transcripts from ~/.openclaw/<agentId>, which expands access beyond the declared workspace memory files and pulls potentially sensitive conversation history into the consolidation context. In this skill, that extra data is then fed into an LLM for rewriting memory files, so a compromise or misconfiguration could expose unrelated private content and create unnecessary data over-collection.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code sends transcript history and staging content to a subagent/LLM without any explicit user-facing notice or consent flow. Those inputs may contain sensitive or unintended data, and because they are incorporated into an external model-processing path, the user may not realize that broader conversational context is being disclosed during a memory-maintenance operation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The function enumerates recent transcript files, reads them, and returns excerpts of prior user and assistant messages without any consent check, visibility control, or data-minimization beyond simple salience heuristics. In a memory-consolidation skill, this creates a real privacy boundary risk because sensitive historical content can be surfaced into later model context or outputs unexpectedly.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code selects 'high-value' excerpts using keyword heuristics such as 'remember', 'important', 'prefer', and 'never', then returns up to 500 characters from matching user and assistant messages. This can preferentially capture exactly the kinds of persistent preference, correction, or sensitive contextual statements users may not expect to be replayed, increasing the chance of cross-session privacy leakage or prompt-context disclosure.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The returned status string says "ready (will trigger on next session end)", which contradicts the actual hook used by the plugin. Earlier comments and code show triggering occurs from the before_agent_start event via time/session checks, not on a session_end event.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 20)May include surrounding context.

json
],
  "license": "MIT",
  "devDependencies": {
    "@types/node": "^25.5.0",
    "openclaw": "^2026.3.23-2",
    "typescript": "^6.0.2"
  }

Unverifiable Dependency: openclaw has 16 known advisory(ies) (CVE-2026-53846 (OpenClaw: Workspace .env npm_execpath could influence bundled runtime dependency); CVE-2026-32064 (OpenClaw's andbox browser noVNC observer lacked VNC authentication); CVE-2026-32006 (OpenClaw has a BlueBubbles group allowlist mismatch via DM pairing-store fallbac) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
82% confidence
Finding

The manifest declares openclaw with a caret range, while the dependency family is reported to have multiple known advisories. Because the version is not exactly pinned, consumers may install different vulnerable releases over time, creating a real supply-chain exposure; this is more concerning in an agent-memory skill because it operates in a sensitive context that may access workspace data and persistent memory.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 22)May include surrounding context.

json
"devDependencies": {
    "@types/node": "^25.5.0",
    "openclaw": "^2026.3.23-2",
    "typescript": "^6.0.2"
  }
}

Static analysis

No suspicious patterns detected.