Back to skill

Security audit

Lily Memory Plugin

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it says, but it also automatically modifies global OpenClaw session files and stores/re-injects conversation memory by default with limited user control.

Review before installing. Use this only where persistent local memory is acceptable, prefer capturePolicy set to assistant-only or tagged-only, consider disabling autoCapture, autoRecall, and vectorSearch for sensitive work, and avoid non-local Ollama endpoints. The session health guard is the main concern because it can automatically reset OpenClaw sessions; install only if you accept that behavior or can patch/disable it.

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
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
lib/session-guard.js:68
Finding

Automatic Startup Logic Mutates and Resets Global OpenClaw Sessions

Content
View full analysis
maxTokens) { log(`session-guard: ${key} overflow detected — ${estTokens} est tokens > ${maxTokens} max (file: ${(stat.size / 1024 / 1024).toFixed(1)} MB)`); // Back up the session file const ts = new Date().toISOString().replace(/[:.]/g, "-"); const bakPath = sessionFile.replace(/\.jsonl$/, `.overflow-${ts}.bak`); try { fs.renameSync(sessionFile, bakPath); log(`session-guard: backed up to ${path.basename(bakPath)}`); } catch (e) { log(`session-guard: backup failed: ${e.message}`); continue; } // Reset session entry delete entry.sessionId; delete entry.sessionFile; delete entry.inputTokens; delete entry.outputTokens; delete entry.totalTokens; delete entry.systemSent; modified = true; result.reset.push(key); // Write alert try { const alertDir = path.dirname(ALERT_FILE); if (!fs.existsSync(alertDir)) fs.mkdirSync(alertDir, { recursive: true }); fs.writeFileSync( ALERT_FILE, `Session ${key} auto-reset at ${new Date().toISOString()} (${estTokens} est tokens > ${maxTokens} cap).\n` ); } catch {} } if (modified) { try { fs.writeFileSync(SESSIONS_FILE, JSON.stringify(sessions, null, 2)); log(`session-guard: sessions.json updated (${result.reset.length} sessions reset)`); } catch (e) { log(`session-guard: failed to write sessions.json: ${e.message}`); } } ``` The operation is automatically invoked during service startup: ```js const guard = checkSessionHealth({ threshold: cfg.sessionOverflowThreshold || 0.8, log: (m) => log.info(m) }); if (guard.reset.length > 0) { log.warn(`Session overflow: ${guard.reset.join(", ")} auto-reset`); } ``` ### Technical Analysis The memory plugin reads the glo ...[truncated 3219 chars]
Remediation
View remediation

T02 · Agent Memory Poisoning

Warning
Location
lib/capture.js:45
Finding

User-Controlled Conversation Facts Can Poison Persistent Memory and Future Agent Context

Content
View full analysis
= maxCapture) break; // Skip injected memory context if ( text.includes("") || text.includes("") ) continue; // Skip very short or very long if (text.length < 30 || text.length > 5000) continue; // Capture policy enforcement if (capturePolicy === "assistant-only" && role === "user") continue; if ( capturePolicy === "tagged-only" && !text.includes("") ) continue; // Detect untrusted external content (emails, web pages, tool output) const untrusted = role === "user" && isUntrustedContent(text); const facts = extractFacts(text, runtimeEntities); for (const fact of facts) { if (stored >= ma ...[truncated 5222 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (34)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description is about a persistent memory/search plugin with keyword and semantic retrieval plus memory lifecycle features. The supplied code does not implement memory storage, SQLite FTS5, Ollama vectors, recall, capture, stuck detection, or consolidation. Instead, it manages session health by reading ~/.openclaw agent session metadata, estimating token usage from session files or message counts, backing up overflowing session logs, clearing session fields, and writing an alert file. This is a materially different purpose and includes undeclared file-management/reset behavior, so the description does not accurately represent this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The supplied code is a unit test file focused on entity validation and SQLite-backed entity persistence helpers. Its observable behavior is limited to testing functions such as isValidEntity, loadEntitiesFromDb, addEntityToDb, and mergeConfigEntities. While it touches SQLite through test setup, it does not show the declared memory-plugin behavior, nor any hybrid FTS5/vector search, Ollama integration, or agent memory features. This is a clear description-versus-code mismatch, with the code chunk serving a different and much narrower purpose.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The security log tool returns full fact values, matched patterns, and source snippets from blocked capture attempts. Security telemetry often contains exactly the sensitive or malicious payloads that should be quarantined; exposing them through a normal tool creates a secondary disclosure channel and could leak secrets, personal data, or prompt-injection content back into agent context.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · test/sqlite.test.js (reported line 47)May include surrounding context.

js
it("rejects paths outside allowed directory", () => {
      assert.throws(() => resolveDbPath("/tmp/test.db"), /Path traversal detected/);
      assert.throws(() => resolveDbPath("../../etc/passwd"), /Path traversal detected/);
      assert.throws(() => resolveDbPath("~/.openclaw/../../sensitive.db"), /Path traversal detected/);
    });

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This markdown file documents that the session health guard auto-resets sessions, backs up .jsonl files, and strips fields from sessions.json. Those behaviors affect user/session data and system state, but the entry provides no explicit warning or caution about the automatic modification of stored session data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README advertises automatic capture and persistent storage of conversation facts but does not clearly warn users that potentially sensitive content may be retained across sessions. In a memory plugin, this can lead to unintended collection of personal, confidential, or regulated data because operators may enable the feature without informed consent or retention controls.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README states that stored memories are automatically injected before each LLM turn, but it does not clearly disclose that previously captured data may be re-exposed to the model on future prompts. This increases the risk of unintended disclosure of sensitive or stale information in contexts where users may not expect persistent recall.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · README.md (reported line 26)May include surrounding context.

Installation

bash
mkdir -p ~/.openclaw/extensions/lily-memory
cp -r . ~/.openclaw/extensions/lily-memory/

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The semantic search documentation describes Ollama-backed embeddings but does not warn that query text and stored memory content may be transmitted to the configured embedding endpoint. Even if Ollama is commonly local, the URL is configurable, so data could be sent to another host and expose sensitive memory contents.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding

The skill metadata declares required binaries and dependencies but does not declare any explicit tool scope or permissions despite advertising capabilities that imply network access and likely shell-adjacent execution during installation/runtime. This reduces transparency and weakens policy enforcement, making it easier for an agent or operator to enable a skill without understanding its effective privilege boundary.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill prominently advertises auto-capture and persistent storage, but it does not present a clear user-facing warning that conversation facts may be automatically extracted and stored long-term. In a memory plugin, this materially increases privacy risk because users may disclose secrets, personal data, or internal operational details without informed consent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation states that semantic search uses Ollama embeddings but does not clearly warn that stored memory content may be sent to the Ollama service for embedding generation. Even if Ollama is local by default, this is a data-sharing boundary that can expose sensitive memory contents to another service or host if reconfigured.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

When vector features are enabled, the skill sends prompts and stored memory text to an Ollama HTTP endpoint for health checks, embedding generation, semantic search, and backfill. Even if the default URL is localhost, the endpoint is configurable and there is no visible warning, trust boundary check, or consent mechanism in this file, so sensitive conversational data may be transmitted to another service unexpectedly.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The skill is designed to store, search, and retrieve user-derived facts in plain language, and multiple tools return raw fact values directly to the caller. In the context of an agent memory plugin, that makes accidental disclosure materially easier: any agent or workflow with access to these tools can enumerate prior stored information, including potentially sensitive personal, operational, or credential-adjacent data captured from conversations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The plugin automatically captures and persists facts from conversation messages at the end of each successful agent run, but this file shows no user-facing notice, consent gate, or per-message opt-in before storage occurs. In a persistent memory skill, silent retention of user-provided content increases privacy risk and can preserve sensitive data far beyond the original session, especially because the same system also supports later recall and search over stored content.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This code permanently deletes rows from the decisions and vectors tables as part of consolidation and orphan cleanup. While there is a post-action log when merges occur, there is no confirmation, pre-action warning, or explanatory comment/docstring disclosing that records will be irreversibly deleted.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The function sends the provided text as prompt in an HTTP POST request to ${ollamaUrl}/api/embeddings. While the code has a docstring describing the API call, it does not warn that user-supplied content may be transmitted over the network to an external/local service, which is a safety-relevant operation under the rule.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

vectorSearch sends the user's query to the embedding service, and backfillEmbeddings eventually sends decision-derived text via storeEmbedding for bulk processing. These operations may transmit stored decision content or user queries to an HTTP endpoint, but this file provides no user-facing disclosure beyond implementation comments.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code unconditionally wraps recalled persistent memory into an auto-injected context block for downstream model consumption, but does not provide any user-facing notice, consent check, or sensitivity gate at the injection point. In a memory plugin, recalled data may contain sensitive personal, behavioral, or prior-conversation information; silently inserting it into prompts increases the risk of privacy leakage, unintended cross-task disclosure, and unsafe model actions based on hidden context.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The module performs autonomous filesystem actions outside simple memory retrieval: it scans a global sessions registry, estimates token usage from on-disk files, renames session files as backups, mutates session metadata, and writes an alert file. In a persistent-memory skill context, this is more dangerous because it can affect agent session integrity and availability without explicit user confirmation, potentially resetting unrelated or active sessions if thresholds or paths are wrong.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · lib/sqlite.js (reported line 16)May include surrounding context.

js
const dbConnections = new Map();

/**
 * Get or create a database connection.
 * @param {string} dbPath - Absolute path to database file
 * @returns {import('better-sqlite3').Database}
 */

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The plugin enables persistent auto-capture of conversation facts by default, but the metadata does not clearly warn users that potentially sensitive conversation content may be extracted and stored on disk. In a memory plugin, this creates real privacy and retention risk because users may unknowingly persist secrets, personal data, or regulated information beyond the current session.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The vector search feature uses an Ollama endpoint and defaults to an HTTP URL, but the metadata does not explicitly warn that memory content may be transmitted to another service for embedding generation. Even when targeting localhost, this crosses a trust boundary and can expose sensitive stored content to a separate process or to a remote host if reconfigured, increasing confidentiality risk.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest describes a persistent memory plugin using SQLite and Ollama-based search, which makes database access and local HTTP calls expected. However, this file imports child_process and repeatedly shells out to the sqlite3 executable, giving the skill process-spawning capability that is not inherent to the stated purpose of memory persistence/search.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The embedding helper posts the provided text to http://localhost:11434/api/embeddings, which transmits test content to another service. The file does not include an explicit warning in comments or user-facing output that running the test harness will send text to Ollama.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
test-v4.mjs:36

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
test/embeddings.test.js:34