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<![CDATA[ ## Vulnerability Details **File Location**: `keep/integrations.py:293-315, 329-358, 479-532`; `keep/cli.py:1419-1427`; `SKILL.md:25-27, 53, 63` **Vulnerability Type**: Persistent agent configuration modification **Risk Level**: Critical ### Vulnerable Code ```python def _try_install_claude_code_plugin() -> 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
<![CDATA[ ## Remediation Suggestions 1. Remove `check_and_install()` from ordinary CLI initialization. 2. Expose integration installation only through a dedicated command such as `keep integrations install`. 3. Require explicit confirmation separately for every target tool and display: - The exact destination file. - The complete content or JSON changes. - Any subprocess commands that will run. - Whether the configuration is workspace-local or global. 4. Default to workspace-local configuration and require a separate explicit option for home-directory changes. 5. Do not automatically invoke remote marketplace installation. Provide the command for the user to run manually, or pin installation to a reviewed immutable commit. 6. Remove instructions telling agents to restore deleted protocol rules automatically. 7. Implement `keep integrations uninstall` with reliable rollback of every installed block, hook, plugin entry, and MCP configuration entry. 8. Back up existing configuration atomically before modification and preserve file permissions. 9. Make setup opt-in rather than relying on `KEEP_NO_SETUP` as an opt-out. 10. Add integration tests proving that ordinary read, search, and write commands do not modify unrelated configuration files. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
keep/integrations.py:73
Finding
Automatic Persistent Capture of User Prompts and Conversation Content<![CDATA[ ## Vulnerability Details **File Location**: `keep/integrations.py:73-84`; `claude-code-plugin/hooks/hooks.json:14-23`; `keep/data/openclaw-plugin/src/index.ts:663-755, 843-900` **Vulnerability Type**: Sensitive conversation data retained automatically **Risk Level**: High ### Vulnerable Code The automatically installed Claude Code hook captures part of each submitted prompt: ```python "UserPromptSubmit": [ { "hooks": [ { "type": "command", "command": "jq -r '\"User prompt: \" + .prompt[:500]' 2>/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
<![CDATA[ ## Remediation Suggestions 1. Disable conversation capture by default and require explicit, informed opt-in. 2. Display a persistent indicator whenever prompt or conversation recording is active. 3. Provide per-session and per-message controls such as: - `capture: false` - Private-session mode - Exclusion by project or workspace - A command to prevent the next message from being retained 4. Apply secret and PII detection before persistence. At minimum, redact: - API keys and bearer tokens. - Passwords and connection strings. - Private keys and certificates. - Cloud credentials. - Common `.env` assignments. 5. Encrypt stored conversation content at rest with a user-controlled key. 6. Define a configurable retention period and automatically delete expired session records. 7. Separate conversation capture consent from document-indexing consent. 8. Clearly disclose when configured external providers receive message-derived content. 9. Add a complete export, inspection, and deletion workflow for captured sessions. 10. Avoid suppressing all hook errors with `2>/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<![CDATA[ ## Vulnerability Details **File Location**: `keep/data/openclaw-plugin/src/index.ts:307-347, 865-870`; `keep/data/system/ignore.md:1-32` **Vulnerability Type**: Excessive filesystem access and sensitive-file indexing **Risk Level**: High ### Vulnerable Code The plugin defaults the indexing path to the whole current workspace: ```typescript function getConfig(): { contextBudgetRatio: number; captureHeartbeats: boolean; indexPaths: string[]; indexExclude: string[]; } { const cfg = api.pluginConfig ?? {}; return { contextBudgetRatio: typeof cfg.contextBudgetRatio === "number" ? Math.max(0, Math.min(1, cfg.contextBudgetRatio)) : 0.3, captureHeartbeats: cfg.captureHeartbeats === true, indexPaths: Array.isArray(cfg.indexPaths) ? cfg.indexPaths : ["./"], indexExclude: Array.isArray(cfg.indexExclude) ? cfg.indexExclude : [], }; } ``` Every configured directory is registered recursively as a persistent watch: ```typescript function ensureWatches(workspaceDir: string): void { if (watchesInitialized) return; watchesInitialized = true; const cfg = getConfig(); for (const relPath of cfg.indexPaths) { const absPath = path.resolve(workspaceDir, relPath); if (!fs.existsSync(absPath)) continue; const stat = fs.statSync(absPath); const args: string[] = ["put", absPath]; if (stat.isDirectory()) args.push("-r"); args.push("--watch"); for (const pattern of cfg.indexExclude) { args.push("--exclude", pattern); } try { execFileSync("keep", args, { encoding: "utf-8", timeout: 30_000, stdio: ["pipe", "pipe", "pipe"], }); api.logger?.info(`[keep] Watch set up for ${relPath}`); } catch (err: any) { if (err.stderr?.includes("Already watching") || err.message?.includes("Already watching")) { api.logger?.debug(`[keep] Watch already active for ${relPath}`); } else { api.logger?.warn(`[keep] Failed to set up wat ...[truncated 3162 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Change the default `indexPaths` value from `["./"]` to an empty list. 2. Require users to select each indexed directory explicitly. 3. Prefer a narrow default such as `MEMORY.md` and `memory/*.md` when those files are intentionally created for memory. 4. Present a dry-run inventory before establishing a recursive watch. 5. Add mandatory default exclusions for: - `.env` and `.env.*` - `*.pem`, `*.key`, `*.p12`, and `*.pfx` - `.ssh/**` - `.aws/**`, `.azure/**`, and cloud SDK credential directories - Kubernetes secrets and kubeconfig files - Terraform state files - Password databases and browser profiles - Git credential stores 6. Use allowlisted content types rather than indexing every non-binary file. 7. Resolve and validate symlinks so watched paths cannot escape approved roots. 8. Add maximum file count, file size, and total ingestion limits. 9. Show active watches and provide a reliable command to disable them and delete associated indexed records. 10. Require separate consent before sending indexed content to network-backed embedding or summarization providers. ]]>

T01 · Skill Instruction Hijacking

Error
Location
keep/data/openclaw-plugin/src/index.ts:781
Finding
Untrusted Retrieved Memory Is Injected into Privileged Model Context<![CDATA[ ## Vulnerability Details **File Location**: `keep/data/openclaw-plugin/src/index.ts:781-830`; `SKILL.md:116-126` **Vulnerability Type**: Indirect prompt injection through indexed memory **Risk Level**: High ### Vulnerable Code The latest user message is used to retrieve and render memory, after which the resulting text is inserted as a system-prompt addition: ```typescript const lastUser = [...params.messages] .reverse() .find((m: any) => 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
<![CDATA[ ## Remediation Suggestions 1. Do not place retrieved document content in `systemPromptAddition`. 2. Return memory through a normal tool-result or user-data channel with explicit provenance. 3. Wrap every retrieved item in strong structural delimiters and state that its contents are untrusted evidence, not instructions. 4. Keep developer-authored instructions separate from retrieved values during template expansion. 5. Preserve source URI, item ID, content type, trust level, and retrieval score for each result. 6. Apply prompt-injection detection to indexed and retrieved content. Detection should supplement, not replace, privilege separation. 7. Prevent retrieved text from directly authorizing tool use, memory writes, file modifications, or network operations. 8. Require user confirmation before taking consequential actions suggested only by retrieved memory. 9. Use trust-aware retrieval so user-authored memory, local reviewed files, arbitrary web pages, and imported third-party content are not treated equivalently. 10. Add adversarial tests using indexed documents that contain explicit instruction overrides, secret-exfiltration requests, and tool-use directives. ]]>
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
Content
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:
Confidence
90% confidence
Finding
External input (network, user) flows to a code execution sink. This enables remote code execution or command injection.

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

Critical
Category
Data Flow
Content
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.'
Confidence
90% confidence
Finding
External input (network, user) flows to a code execution sink. This enables remote code execution or command injection.

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

Critical
Category
Data Flow
Content
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:
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

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

Critical
Category
Data Flow
Content
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)
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Credential Access

High
Category
Privilege Escalation
Content
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)
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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