Back to skill

Security audit

Lily Memory 5.0.0

Security checks for vulnerabilities and agentic risk

Overview

This memory skill largely does what it advertises, but it stores and reinjects conversation data by default and has unsafe command and network handling that should be reviewed before installation.

Review this carefully before installing. Use only a local trusted Ollama endpoint, disable autoCapture and autoRecall for sensitive work unless you have a retention policy, avoid storing secrets or credentials, and do not expose this plugin to untrusted tool calls until the SQLite shell execution is replaced with a non-shell API or argument-array invocation.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
lib/sqlite.js:43
Finding

Shell Command Injection in SQLite CLI Invocation

Content
View full analysis
Remediation
View remediation

T02 · Agent Memory Poisoning

Warning
Location
lib/recall.js:16
Finding

Persistent Prompt Injection Through Untrusted Memory Values

Content
View full analysis
${now}) LIMIT 1`); let aid; if (existing.length > 0) { aid = existing[0].id; sqliteExec(dbPath, `UPDATE decisions SET fact_value = '${sv}', timestamp = ${now}, last_accessed_at = ${now}, ttl_class = '${tc}', expires_at = ${exp} WHERE id = '${escapeSqlValue(aid)}'`); } else { aid = randomUUID(); sqliteExec(dbPath, `INSERT INTO decisions (id, session_id, timestamp, category, description, rationale, classification, importance, ttl_class, expires_at, last_accessed_at, entity, fact_key, fact_value, tags) VALUES ('${escapeSqlValue(aid)}', 'tool', ${now}, 'manual', '${se}.${sk} = ${sv}', 'Stored via memory_store tool', 'ARCHIVE', 0.9, '${tc}', ${exp}, ${now}, '${se}', '${sk}', '${sv}', '["tool"]')`); } } ``` Permanent values are added to every future Agent context: ```js const permanent = sqliteQuery(dbPath, ` SELECT entity, fact_key, fact_value, importance FROM decisions WHERE ttl_class = 'permanent' AND entity IS NOT NULL AND fact_key IS NOT NULL ORDER BY importance DESC LIMIT 15 `); if (permanent.length > 0) { lines.push("## Permanent Knowledge"); for (const row of permanent ...[truncated 2978 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
lib/embeddings.js:32
Finding

Unrestricted Embedding Endpoint Enables Memory Disclosure and SSRF

Content
View full analysis
setTimeout(r, 50)); } ``` The configuration schema places no host or protocol restrictions on the endpoint: ```json "ollamaUrl": { "type": "string", "default ...[truncated 2647 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Rogue AgentSelf-Modification, Session Persistence
Findings (29)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The supplied code chunk is specifically a test file (test/entities.test.js) focused on entity validation and basic SQLite entity storage behavior. While it touches SQLite via helper functions and may be part of a larger system, the observable behavior in this chunk is unrelated to the declared core functionality of a persistent memory plugin with hybrid search and autonomous memory features. There are no signs here of FTS5 indexing/search, Ollama integration, semantic retrieval, memory capture/recall pipelines, stuck detection, or consolidation logic. Because the code’s actual purpose in this chunk is materially different from the declared description, this should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The README advertises automatic capture and persistent storage of conversation facts, but it does not clearly warn users that potentially sensitive information may be retained on disk across sessions. In a memory plugin, this creates a real privacy and data-retention risk because users may unknowingly expose personal, proprietary, or credential-adjacent information to long-term storage.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README describes auto-recall but does not clearly emphasize that stored memories are injected into future LLM turns, which can propagate previously captured sensitive information into later prompts. This is dangerous because users may not realize that old data can resurface in unrelated contexts, increasing the chance of inadvertent disclosure to models, tools, logs, or downstream systems.

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/

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill advertises capabilities that imply shell execution (sqlite3 CLI) and network access (Ollama HTTP requests) but does not declare any explicit tool scope or permission boundaries. This is dangerous because operators and downstream policy engines cannot clearly restrict or review the skill's ability to access local execution and external services, increasing the chance of unintended command execution or data egress.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill describes auto-recall behavior but does not present it as a clear user-facing warning that prior memories are automatically injected into future prompts before each turn. This can cause sensitive or stale information to be reintroduced into model context unexpectedly, increasing prompt leakage, privacy exposure, and unintended influence on future agent behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill states that it provides persistent memory but does not clearly warn users that conversation facts may be automatically extracted and written to disk. In a memory plugin context this is especially sensitive because users may disclose secrets, personal data, or internal operational details during normal conversation without realizing they will be retained across sessions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The documentation does not clearly warn that semantic search may send stored memory content to the Ollama embedding endpoint for vectorization. Even if Ollama is expected to run locally, this still creates a data-transfer boundary; if reconfigured to a remote host, sensitive stored content could be exposed over the network.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The memory_search tool is explicitly designed to recall persisted facts, decisions, and prior context, which establishes a durable natural-language retention and retrieval channel. Because the plugin also stores conversation-derived content, this can surface previously shared private data in later interactions to whoever can invoke the tool or influence the agent to use it.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The before_agent_start hook prepends recalled memory directly into future prompts, meaning previously captured content is automatically disclosed to downstream model processing on later tasks. This is more dangerous than manual retrieval because it broadens exposure without an explicit request, increases cross-task leakage risk, and can cause private context from one interaction to influence unrelated future sessions.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The agent_end hook automatically processes completed message history, extracts facts, stores them for future reuse, and may also create embeddings from those new records. In the context of a persistent memory skill, this creates a genuine long-term data retention path for user-provided content, including potentially sensitive information, with no visible consent, review, or secret-detection safeguards in this file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The plugin automatically extracts facts from completed conversations and persists them without any consent gate, notice, or sensitivity filtering visible in this file. In a memory plugin, this creates a real privacy and data-governance risk because users may disclose secrets, personal data, or credentials during normal use and have them silently retained beyond the session.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

Newly stored memories are sent to the Ollama embedding service for vectorization when vectors are enabled, but this file shows no warning, consent flow, or trust-boundary check around that transmission. Even if Ollama is configured as localhost by default, it is still a separate service endpoint and may be reconfigured remotely, so conversation-derived data can leave the immediate plugin boundary unexpectedly.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This function automatically extracts facts from user and assistant messages and persists them to a long-lived SQLite store without any notice, consent, or policy enforcement in this code path. In a memory plugin, that creates a real privacy and data-governance risk because users may disclose sensitive personal, credential, or business information that is silently retained for weeks to months and later recalled in unrelated contexts.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The function transmits the caller-provided text in an HTTP request body to ${ollamaUrl}/api/embeddings. While the code comments describe the API call, there is no confirmation prompt, user-facing log, or warning indicating that potentially sensitive text will be sent over the network for embedding generation.

Content

No source excerpt is available for this finding.

Unbounded Output

Medium
Category
Output Handling
Confidence
60% confidence
Finding

Output size or generation rate is not bounded. Unbounded output enables denial-of-service through resource exhaustion, log flooding, or context-window stuffing.

Content

Scanner excerpt · lib/embeddings.js (reported line 118)May include surrounding context.

js
const safeText = escapeSqlValue(text);
  const safeDecisionId = escapeSqlValue(decisionId);
  const safeModel = escapeSqlValue(model);
  // Embeddings are compact numeric JSON — no truncation, only quote-escape.
  const embJson = JSON.stringify(embedding).replace(/'/g, "''");

  return sqliteExec(dbPath, `

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This loop constructs text from stored decision fields such as entity, fact_key, fact_value, and description, then passes it to storeEmbedding, which sends it to the Ollama service. The logger messages mention backfilling activity but do not disclose that stored data content is being transmitted to an external/local HTTP endpoint for processing.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code automatically injects persistent memory content into the model context, including permanent facts, recent decisions, and semantic/keyword matches, without any consent gate, redaction, or user-visible notice. Because the stored fields can contain sensitive user data and are broadly rendered into every recall block, unrelated prompts or downstream tool/model consumers may receive personal or confidential information unexpectedly.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest describes a persistent memory plugin using SQLite and semantic search, which implies local database access, but this file implements that by spawning shell commands through execSync. Subprocess execution is a broader capability than ordinary in-process database access and is not explicitly justified by the stated purpose or description.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code builds shell command strings with interpolated dbPath and SQL, then executes them via execSync. Although the SQL text is partially escaped, dbPath is not safely passed as a separate argument and quote-based shell injection remains possible; additionally, this enables arbitrary sqlite3 dot-commands or dangerous SQL if untrusted input reaches these functions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The plugin is explicitly designed to persistently capture, store, and later re-inject conversation-derived facts, but the manifest text does not clearly warn users that their conversation content may be retained and reused automatically. In a memory skill, that omission creates a real privacy and data-governance risk because operators may enable it without understanding that sensitive prompts, secrets, or personal data can be stored across sessions and surfaced later.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The manifest advertises semantic search through a configurable Ollama endpoint but does not clearly disclose that conversation-derived text may be transmitted to that service for embedding generation. Even if the default is localhost, the URL is configurable and could point to a remote or proxied endpoint, creating an unannounced data exfiltration path for sensitive conversation content.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The natural-language value "TypeScript for all new projects" imposes a specific programming language choice universally rather than offering a choice or recording explicit opt-in in context. This matches the policy-violation category for language/locale constraints expressed in natural-language content.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script states that it exercises the plugin against the live database but does not provide a prominent warning, confirmation prompt, or safe guardrail before accessing a real user memory store. In a memory plugin context, that database likely contains sensitive personal or operational information, so casual execution can expose private data during testing and lead operators to run unsafe commands unintentionally.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The smoke test is hard-coded to query a real user memory database under a home directory path instead of using only isolated test fixtures. Even though the shown operations are reads against the live DB, exercising production-like personal memory during tests can expose sensitive data, create privacy risk, and normalize unsafe test behavior around real user state.

Content

No source excerpt is available for this finding.