Back to skill

Security audit

Reflective Memory

Security checks for vulnerabilities and agentic risk

Overview

Keep appears to be a legitimate memory and indexing skill, but it automatically persists agent configuration, captures conversation content, and watches broad workspace content in ways users should review before installing.

Install only if you want a persistent cross-session memory system that can modify agent configs, capture conversation text, index workspace files, and process content with configured local or remote providers. Before first use, consider setting KEEP_NO_SETUP=1, narrowing OpenClaw indexPaths, adding secret-file exclusions, using local-only providers or disk encryption, and reviewing how to remove hooks, watches, and stored memory.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
Findings (4)

T06 · System Persistence

Error
Location
keep/integrations.py:293
Finding

Automatic Persistent Modification of Agent Configuration and Lifecycle Hooks

Content
View full analysis
bool: """Try to install the keep plugin via claude CLI. Runs `claude plugin marketplace add` and `claude plugin install`. Uses a short timeout to avoid blocking. Returns True on success. """ claude = shutil.which("claude") if not claude: return False try: # Add marketplace (idempotent) subprocess.run( [claude, "plugin", "marketplace", "add", CLAUDE_CODE_MARKETPLACE_URL], timeout=30, capture_output=True, ) # Install plugin (idempotent) result = subprocess.run( [claude, "plugin", "install", f"{CLAUDE_CODE_PLUGIN_NAME}@{CLAUDE_CODE_MARKETPLACE_NAME}"], timeout=30, capture_output=True, ) return result.returncode == 0 except (subprocess.TimeoutExpired, OSError) as e: logger.debug("claude plugin install failed: %s", e) return False ``` ```python def install_codex(config_dir: Path) -> list[str]: """Install protocol block for OpenAI Codex. Returns list of actions taken. """ actions = [] agents_md = config_dir / "AGENTS.md" if _install_protocol_block(agents_md): actions.append("protocol block") return actions ``` ```python def _check_cwd_agents_md() -> None: """Install protocol block into AGENTS.md in cwd if present.""" agents_md = Path.cwd() / "AGENTS.md" if agents_md.is_file(): if _install_protocol_block(agents_md): print( f"keep: installed protocol block in {agents_md}", file=sys.stderr, ) ``` ```python def check_and_install(config: "StoreConf ...[truncated 3922 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
keep/integrations.py:73
Finding

Automatic Persistent Capture of User Prompts and Conversation Content

Content
View full analysis
/dev/null | keep now 2>/dev/null || true", "statusMessage": "Reflecting...", } ], } ], ``` The packaged Claude Code plugin contains equivalent behavior: ```json { "matcher": "", "hooks": [ { "type": "command", "command": "keep now 'User prompt: ${.prompt:500}' -t 'session=${.session_id}' 2>/dev/null || true" } ] } ``` OpenClaw ingestion stores complete truncated user and assistant message text as memory versions: ```typescript async ingest(params: { sessionId: string; sessionKey?: string; message: any; isHeartbeat?: boolean; }) { const cfg = getConfig(); if (params.isHeartbeat && !cfg.captureHeartbeats) { return { ingested: false }; } if (!mcp.connected) { try { await mcp.connect(); } catch { return { ingested: false }; } } const role: string = params.message.role || "unknown"; if (!INGEST_ROLES.has(role)) { return { ingested: false }; } try { const text = extractText(params.message.content); if (!text.trim()) { return { ingested: false }; } const content = `[${role}] ${truncate(text, maxInlineLength)}`; const itemId = sessionItemId(params); await mcp.flow({ state: "put", params: { content, id: itemId, tags: sessionTags({ ...params, extra: { role } }), }, }); return { ingested: true }; } catch (err: ...[truncated 3478 chars]
Remediation
View remediation
/dev/null || true`; failures should be visible enough for users to know whether recording occurred. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
keep/data/openclaw-plugin/src/index.ts:307
Finding

Default Recursive Monitoring and Indexing of the Entire Workspace

Content
View full analysis
Remediation
View remediation

T01 · Skill Instruction Hijacking

Error
Location
keep/data/openclaw-plugin/src/index.ts:781
Finding

Untrusted Retrieved Memory Is Injected into Privileged Model Context

Content
View full analysis
m.role === "user"); const prompt = lastUser ? truncate(extractText(lastUser.content), 500) : ""; const totalBudget = params.tokenBudget || 8000; const keepBudget = Math.floor(totalBudget * cfg.contextBudgetRatio); const itemId = sessionItemId(params); const isFirstAssemble = sessionFirstAssemble.delete(itemId); // Call the prompt template — it runs the state doc flow internally, // expands bindings into the template, and returns rendered text. const contextText = await mcp.prompt({ name: "openclaw-assemble", text: prompt || "session context", id: itemId, token_budget: keepBudget, }); const keepTokens = estimateTokens(contextText); const parts: string[] = []; if (contextText.trim()) parts.push(`\`keep context\`:\n${contextText}`); if (isFirstAssemble) { parts.push( `\`keep tools\`: keep_flow, keep_help, and keep_prompt are available as tools. ` + `If unfamiliar with keep, start with keep_help(topic="flow-actions") ` + `and keep_help(topic="index") to learn the full capability set.` ); } return { messages: params.messages, estimatedTokens: conversationTokens + keepTokens, systemPromptAddition: parts.length > 0 ? parts.join("\n\n") : undefined, }; ``` The Skill explicitly encourages indexing arbitrary URLs and files: ```markdown **Index important documents.** Whenever you encounter documents (URLs, files, references) important to the user or task, index them: keep_flow(state="put", params={content: "https://example.com/doc", tags: {topic: "auth", project: "myapp"}}) keep ...[truncated 2735 chars]
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (371)

Tainted flow: 'out' from sys.stdin.read (line 2574, user input) → subprocess.Popen (code execution)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

External input (network, user) flows to a code execution sink. This enables remote code execution or command injection.

Content

Scanner excerpt · keep/cli.py (reported line 3269)May include surrounding context.

python
from .mcpb import generate_mcpb
        out = generate_mcpb(store_path=store_path)
        if platform.system() == "Darwin":
            subprocess.Popen(["open", str(out)])
        elif platform.system() == "Windows":
            os.startfile(str(out))
        else:

Tainted flow: 'out' from sys.stdin.read (line 2574, user input) → subprocess.Popen (code execution)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

External input (network, user) flows to a code execution sink. This enables remote code execution or command injection.

Content

Scanner excerpt · keep/cli.py (reported line 3273)May include surrounding context.

python
elif platform.system() == "Windows":
            os.startfile(str(out))
        else:
            subprocess.Popen(["xdg-open", str(out)])
        return (
            'After installation, just say to Claude:\n'
            'Please read all the keep_help documentation, and then use keep_prompt(name="reflect") to save some notes about what you learn.'

Tainted flow: 'req' from os.environ.get (line 263, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · keep/config.py (reported line 228)May include surrounding context.

python
f"{base_url}/api/tags",
            headers={"User-Agent": user_agent()},
        )
        with urllib.request.urlopen(req, timeout=0.5) as resp:
            data = json.loads(resp.read())
            models = [m["name"] for m in data.get("models", [])]
            if models:

Tainted flow: 'req' from os.environ.get (line 263, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · keep/config.py (reported line 267)May include surrounding context.

python
f"{url}/api/pull", data=data,
            headers={"Content-Type": "application/json", "User-Agent": user_agent()},
        )
        with urllib.request.urlopen(req, timeout=600) as resp:
            buf = b""
            while True:
                chunk = resp.read(512)

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 · CLAUDE.md (reported line 8)May include surrounding context.

md
This repository is open-source and public on GitHub. Every commit is visible to the world.

**NEVER commit or include:**
- API keys, tokens, secrets, credentials, or .env files
- Business plans, financial data, pricing, or revenue information
- Customer data, user information, or private communications
- Internal infrastructure details (IPs, DSNs, deployment configs)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is too vague and does not accurately represent the concrete behavior of the code. Rather than implementing a user-facing reflective memory feature, this code functions as an offline benchmark ingestion script for LoCoMo-Plus data. It performs file I/O, creates a store, contacts a local embedding service over HTTP, transforms and timestamps records, ingests content and images, and writes state files. These are materially different from the expected behavior suggested by 'Reflective Memory,' and the declared permissions/triggers omit the code's actual resource access patterns.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description suggests a memory-oriented skill, but the supplied code does not implement reflective memory behavior such as saving, retrieving, summarizing, or reasoning over user memories. Instead, it is an offline benchmarking tool for LLM-as-judge scoring on LoCoMo predictions. Its primary purpose, resource usage, and operational mode (CLI evaluation with file I/O and external API calls) are materially different from the declared description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description suggests a memory-oriented skill, but the supplied code does not implement memory storage, retrieval, reflection, or recall. Instead, it provides infrastructure for invoking an OpenAI model with a prompt. It also accesses external resources and credentials (environment variables and macOS keychain), which are not reflected in the declared permissions or purpose. These are substantive behavioral differences, so this is a clear mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description does not accurately represent the code's actual function. Rather than implementing a reflective memory feature, the script performs offline ETL/data-preparation for a benchmark dataset. Its primary purpose is converting input JSON corpora into several structured output files for ingestion and evaluation. This is a materially different purpose from 'Reflective Memory,' and it also involves undeclared file I/O capabilities. There are no suspicious hidden behaviors beyond dataset processing, but the description is clearly mismatched to the supplied code.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared description 'Reflective Memory' does not accurately represent this code chunk's behavior. The actual code is not implementing a reflective memory feature; it is an evaluation/benchmark script for question answering over a stored corpus using retrieval plus LLM generation. It performs multiple concrete file I/O operations, loads configuration and a store, queries retrieval results, generates answers through selectable LLM backends, saves outputs, and updates run state. These are materially different from a simple memory-oriented skill description, and the lack of declared permissions is inconsistent with the code's read/write and model-query behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared description suggests a memory-oriented skill, but the supplied code is not implementing a reflective memory feature. Its primary purpose is to simulate and log retrieval traces for LoCoMo QA items using a Keeper system. It accepts CLI arguments, loads dataset/store resources, issues retrieval requests, processes async work ticks, refines searches by dominant conversation tag, and serializes full traces to JSON. That is a materially different purpose from 'Reflective Memory.' No hidden prompt instructions are relevant; the mismatch is based on direct code behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description suggests a memory-related skill, but the actual code is unrelated to memory or reflection. Instead, it implements a packaging/build hook that invokes external tooling (npm, node) to install dependencies and build a plugin artifact. This is a materially different primary purpose and introduces undeclared capabilities such as subprocess execution and build-time filesystem interaction. Therefore, the description does not accurately represent the code's behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The supplied code chunk is only a minimal launcher for a command-line interface. It does not itself implement or demonstrate reflective memory behavior, storage, recall, or related logic suggested by the description. Because the visible code’s purpose is simply to invoke a CLI main function, the declared description is not accurately represented by this chunk alone.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description 'Reflective Memory' does not accurately represent this code chunk. The implementation is infrastructure-oriented background job orchestration for a note/document system, not a memory or reflection feature. It manages queues, idempotency keys, task delegation, vector embeddings, OCR/analyze/summarize application, edge backfills, and spawns a daemon worker process. These are substantial operational capabilities that are undeclared and materially different from the stated purpose. No permissions are declared, yet the code uses subprocess spawning, filesystem reads/writes, and likely remote task service interaction, reinforcing the mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared description suggests a memory-related skill, likely for reflective recall or memory management. However, this code chunk does not implement a reflective memory feature directly. Its primary function is infrastructure for context assembly, prompt template loading/rendering, similarity lookup, meta-document resolution, and version navigation within a document/knowledge store. It accesses prompt documents, document stores, embeddings, flow runners, and metadata resolution machinery—substantial capabilities not implied by the minimal declared purpose. This is a material description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description suggests a memory-oriented skill, but this code chunk is not implementing reflective memory behavior itself. Instead, it provides infrastructure for managing multiple AI providers and related resources. Its primary purpose is lifecycle and resource management for embeddings, summarization, media, OCR/content extraction, and analysis providers, including cache handling and GPU memory release. That is a materially different function from the declared description, so this is a clear description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description 'Reflective Memory' does not accurately describe this code chunk's primary behavior. The code is not implementing a memory reflection feature; it is a search augmentation mixin for a Keeper system. Its functions focus on ranking and retrieval logic: recency decay, reciprocal rank fusion of semantic and FTS results, deep tag following, deep edge traversal across document relationships, reranking evidence units, and invoking a fallback search flow. This is a materially different purpose from the declared description. No explicit permissions are declared, yet the code clearly relies on document and vector stores and a read-flow mechanism, further indicating undeclared retrieval capabilities.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

The declared description suggests a memory-focused skill, but this code chunk does not implement reflective memory behavior itself. Instead, it provides generic infrastructure for registering and discovering actions in a package, including dynamic module imports and metadata for async/priority execution. While some protocol methods reference item/document retrieval and search, the actual code here does not perform memory reflection; it defines a reusable action system. That is a materially different primary purpose from the declared description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
79% confidence
Finding

The supplied code does not implement reflective memory behavior. Instead, it is infrastructure for item-scoped processing: it fetches items by ID, reads documents from context, compares stored tags against content or summary hashes, and returns text content for downstream actions. While this could support other skills, its primary purpose is state-resolution and change-detection utilities, not memory reflection. No obvious extra dangerous permissions are used, but the actual behavior is materially different from the declared description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

The supplied code is focused on tagging/classification infrastructure, not reflective memory. It reads .tag/* items, extracts prompts from summaries, builds constrained tag specs, resolves a summarization provider, and classifies parts accordingly. That is a materially different primary purpose from the declared description 'Reflective Memory.' No obvious extra dangerous permissions are shown, but the core behavior does not match the declared purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description 'Reflective Memory' does not accurately represent this code's primary behavior. The implementation is an item analysis pipeline: it reads item content, invokes analysis or summarization providers, creates structured parts, classifies them, deletes old derived part records, inserts new derived items, and updates tags with an analyzed hash. That is materially different from a memory/reflection capability and also involves undeclared storage mutations and provider-based analysis. No suspicious extra triggers are visible, but the stated purpose is not aligned with the actual code behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

The declared description suggests a memory-oriented skill, but the code implements automated tagging/classification for items. Its primary behavior is to read item content, classify it according to tag specs, and write tags back via mutations, with optimization based on content and summary hashes. There is no evident reflective memory functionality such as storing or retrieving memories. This is a material description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is broad and suggests reflective memory functionality, but this code chunk specifically implements destructive deletion of stored data. Deleting items and their version history is a significant capability not clearly represented by the declared purpose, and no declared permissions indicate destructive store access. This is a material mismatch in primary behavior and capability.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description does not match the code's actual function. Rather than reflective memory behavior, the implementation performs media content description for URI-backed files and updates stored summaries. This is a materially different primary purpose and includes undeclared capabilities such as reading local file paths, calling a media analysis provider, and mutating memory/item summaries. No evidence in the code suggests reflective-memory logic.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description 'Reflective Memory' does not match the concrete behavior of this code. The code is an 'extract_links' action whose primary purpose is link extraction and reference graph construction, not reflective memory functionality. It also performs undeclared state-changing operations: reading from the item store, listing vault items, checking filesystem directories for vault markers, creating stub items for link targets, and updating tags on the source item. These are materially different capabilities from the declared purpose, so this is a clear mismatch.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.exposed_secret_literal, suspicious.prompt_injection_instructions

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
keep/data/openclaw-plugin/index.legacy.ts:29

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
keep/data/openclaw-plugin/src/index.ts:252

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
bench/locomo/llm.py:23

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
tests/test_git_ingest.py:267

Prompt-injection style instruction pattern detected.

Warn
Code
suspicious.prompt_injection_instructions
Location
later/draft-supernode-prompts.md:107