Back to skill

Security audit

Memory Consolidate

Security checks for vulnerabilities and agentic risk

Overview

This memory skill is mostly coherent, but it can send persistent memory to a configurable LLM endpoint and load that model-generated text into future sessions without enough safeguards.

Install only if you intentionally want an automated, persistent memory system that stores summaries in your OpenClaw workspace, runs on a schedule, injects MEMORY_SNAPSHOT.md into future sessions, and may send selected memory content to your configured LLM provider. Use a trusted HTTPS endpoint, a dedicated low-privilege API key, review generated snapshots before enabling session injection, and avoid enabling the cron or semantic step for workspaces containing secrets or sensitive client data.

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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/memory_semantic_consolidate.py:38
Finding
Private memory content and API credentials can be transmitted to an arbitrary endpoint<![CDATA[ ## Vulnerability Details **File Location**: `scripts/memory_semantic_consolidate.py:38-83` **Vulnerability Type**: Arbitrary-endpoint sensitive data disclosure **Risk Level**: High ### Vulnerable Code ```python def _load_llm_config() -> Dict[str, str]: """Load Anthropic API config from openclaw.json tui provider.""" base_url = os.environ.get("ANTHROPIC_BASE_URL", "") api_key = os.environ.get("ANTHROPIC_API_KEY", "") model = os.environ.get("SEMANTIC_LLM_MODEL", "claude-haiku-4-5-20251001") if not base_url or not api_key: try: cfg_path = Path.home() / ".openclaw" / "openclaw.json" cfg = json.loads(cfg_path.read_text("utf-8")) tui = cfg.get("models", {}).get("providers", {}).get("tui", {}) if not base_url: base_url = tui.get("baseUrl", "") if not api_key: api_key = tui.get("apiKey", "") except Exception: pass return {"base_url": base_url.rstrip("/"), "api_key": api_key, "model": model} def _call_anthropic(prompt: str, system: str, cfg: Dict[str, str]) -> Optional[str]: """Call Anthropic Messages API. Returns assistant text or None on failure.""" url = f"{cfg['base_url']}/v1/messages" body = json.dumps({ "model": cfg["model"], "max_tokens": 4096, "system": system, "messages": [{"role": "user", "content": prompt}], }).encode("utf-8") headers = { "Content-Type": "application/json", "x-api-key": cfg["api_key"], "anthropic-version": "2023-06-01", } try: req = Request(url, data=body, headers=headers, method="POST") with urlopen(req, timeout=60) as resp: data = json.loads(resp.read().decode("utf-8")) for block in data.get("content", []): if block.get("type") == "text": return block["text"] except Exception as exc: print(f"[semantic] LLM call fa ...[truncated 3601 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require an explicit opt-in before transmitting workspace memories to an external LLM. Default to the local deterministic fallback. 2. Require `https` and reject plaintext HTTP destinations. 3. Maintain an allowlist of approved provider hostnames and ports. Do not accept arbitrary environment-provided endpoints without explicit administrative approval. 4. Use a dedicated, least-privileged API credential for semantic consolidation rather than automatically reusing a general `tui` provider key. 5. Add a security-focused redaction pass before `_build_prompt()`. Remove credentials, authorization headers, tokens, passwords, private keys, email addresses, personal identifiers, and configurable sensitive patterns. 6. Minimize the transmitted fields and provide users with a preview or audit log showing exactly which memory items will leave the host. 7. Document the recipient, retention implications, and data categories transmitted. 8. Fail closed when destination validation fails and use the existing local fallback rather than attempting the request. ]]>

T02 · Agent Memory Poisoning

Error
Location
scripts/memory_semantic_consolidate.py:137
Finding
Untrusted LLM output can poison the persistent snapshot injected into future sessions<![CDATA[ ## Vulnerability Details **File Locations**: - `scripts/memory_semantic_consolidate.py:137-150, 187-220, 258-268` - `scripts/memory_snapshot_render.py:29-40, 43-79` - `scripts/memory_consolidate/main.py:375-382` - `SKILL.md:30-34` **Vulnerability Type**: Persistent memory poisoning through insufficiently validated remote output **Risk Level**: High ### Vulnerable Code The response parser accepts any JSON object under `sections` without enforcing a security-oriented schema: ```python def _parse_llm_response(raw: str) -> Optional[Dict[str, Any]]: """Extract sections dict and user_traits from LLM response.""" # Strip markdown fences if present cleaned = re.sub(r"^```(?:json)?\s*\n?", "", raw.strip()) cleaned = re.sub(r"\n?```\s*$", "", cleaned) try: data = json.loads(cleaned) if isinstance(data, dict): result = data.get("sections", {}) # Attach user_traits at top level for caller to extract if "user_traits" in data: result["__user_traits__"] = data["user_traits"] return result except json.JSONDecodeError: pass return None ``` Returned text receives only basic type, emptiness, item-count, and character-length checks: ```python if raw_response: parsed = _parse_llm_response(raw_response) if parsed: used_llm = True for key, limits in SECTION_LIMITS.items(): items = parsed.get(key, []) if not isinstance(items, list): continue cleaned = [] for idx, item in enumerate(items[:limits["items"]]): text = str(item.get("text") or "") if isinstance(item, dict) else str(item) text = text.strip() if not text: continue if len(text) > limits["chars"]: text = text[:limits["chars"] - 1] + "…" cleaned.append({ "rank": idx + 1, ...[truncated 4970 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Treat all model responses as untrusted data rather than authoritative memory. 2. Define and enforce a strict schema for every section and item. Reject unknown fields, non-string themes, malformed objects, and values outside narrowly defined formats. 3. Add content validation that rejects imperative instructions, role changes, references to system/developer messages, requests to invoke tools, credential requests, and attempts to override existing rules. 4. Preserve provenance and label generated entries as untrusted model summaries rather than presenting them as authoritative facts. 5. Require user or administrator approval before model-generated text is promoted to `MEMORY_SNAPSHOT.md`. 6. Compare generated statements against source candidates and require traceable source identifiers. Reject statements that cannot be linked to one or more submitted candidates. 7. Keep the deterministic rule snapshot as the default. Store the semantic version separately until it passes validation or approval. 8. Separate informational memory from instructions at the prompt/context layer so snapshot text cannot override higher-priority policies. 9. If validation fails, use `_fallback_consolidate()` and do not retain the unsafe remote response in the active snapshot. 10. Add adversarial tests covering instruction injection, fabricated facts, tool-use requests, encoded instructions, and malicious but valid JSON responses. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (27)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
This mismatch is more severe because the documented purpose omits that the skill sends data to an external Anthropic-compatible API using configured credentials. Undeclared external network transmission in a memory-related skill can expose sensitive session-derived content and credentials context, while users may believe the tool is only performing local consolidation.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
This mismatch is more severe because the documented purpose omits that the skill sends data to an external Anthropic-compatible API using configured credentials. Undeclared external network transmission in a memory-related skill can expose sensitive session-derived content and credentials context, while users may believe the tool is only performing local consolidation.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill requests or implies powerful capabilities (environment access, file read/write, shell, and network via external API use) but does not declare an explicit tool scope or permissions boundary. This is dangerous because users and the hosting agent cannot reliably constrain what the skill may do, increasing the chance of over-privileged execution, data exfiltration, or unintended system modification during installation and operation.

Vague Triggers

Medium
Confidence
96% confidence
Finding
The activation rules are unusually broad and include many generic phrases about memory issues, making the skill likely to trigger in situations where the user did not intend to authorize file, config, cron, or network-affecting guidance. In context, this increases risk because the skill also recommends persistent system modifications and may route memory-related content into external processing.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill instructs the agent/user to patch configuration, inject a file into every session, and install a daily cron job, all of which create persistent system changes and ongoing automated execution. Without an explicit warning and consent checkpoint, this can lead to surprise persistence, repeated processing of sensitive logs, and long-lived changes that are hard for users to notice or undo.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The script serializes extracted memory candidates and writes them to both a latest file and a timestamped history file, creating persistent on-disk copies of potentially sensitive session-derived content. In a memory-consolidation skill, this is especially risky because the data source is agent session logs and extracted facts/decisions, which can include secrets, personal data, internal project details, or operational context; history retention also multiplies exposure.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The README explicitly states that the skill reads daily logs and session transcripts and later injects a generated memory snapshot into every session, but it does not prominently warn users that sensitive data from conversations and workspace files may be collected, retained, summarized, and resurfaced automatically. In a persistent memory system, this creates a real privacy and data-minimization risk because secrets, personal data, or sensitive project context may be unintentionally ingested and propagated across future sessions.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README documents automatic extraction of identity information from IDENTITY.md and USER.md without an explicit warning or consent flow. This is dangerous because identity attributes such as owner name, timezone, and language can be silently harvested from workspace files and then used in generated memory artifacts, increasing the chance of privacy leakage and unintended exposure in downstream agent context.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The activation criteria are unusually broad and include many generic phrases about memory being stale, missing, broken, or needing optimization. This can cause the skill to trigger in contexts where the user did not intend persistent memory operations, increasing the chance of unnecessary access to session logs and accidental modification of long-lived memory artifacts.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill instructs the agent to patch runtime configuration to inject MEMORY_SNAPSHOT.md into every session and to install a daily cron job, both of which create persistent behavior changes. Without an explicit warning and user confirmation, this can silently establish ongoing data collection, recurring automation, and broad propagation of potentially sensitive memory content across future sessions.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The summary content is prefixed with the fixed Chinese string "归档回流[{label}]:", which forces a specific language in generated output. The file does not offer a language choice or document a justified region-specific constraint, so this is a natural-language locale policy violation.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
This code sets a default `owner_language` of `English`, which imposes a specific language preference whenever `IDENTITY.md` or `USER.md` do not provide one. The policy for this category prohibits forcing a language or locale unless the user is given a choice or the constraint is clearly justified.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The normalization logic rewrites multiple English and Chinese prefixes into fixed Chinese labels such as "问题:", "决策:", and "方案:", and also prepends those Chinese labels when none are present. This is a natural-language locale policy concern because the file forces Chinese output conventions rather than preserving the user's original language or offering a language choice.

Description-Behavior Mismatch

Medium
Confidence
89% confidence
Finding
The function accepts caller-supplied agent IDs and constructs paths to sibling agents' session directories, then enumerates recent session logs from each. In a memory-consolidation skill, those logs can contain sensitive user and assistant content, so broad cross-agent access expands the data exposure boundary beyond the current agent unless strict authorization and scoping are enforced elsewhere.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
This code parses session JSONL files and extracts text from user and assistant messages for later processing, which is effectively surveillance of conversation content. In the context of persistent memory generation, that creates privacy risk and potential secret retention because users may not realize their full message text is being harvested and transformed into durable memory.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
This Python file performs many persistent writes, including replacing active memory files, archive files, snapshot files, health/status files, and state data. While the module docstring describes consolidation at a high level, there is no user-facing disclosure such as logging, print output, or confirmation that these files will be modified, and the operations include purging/archive behavior that can materially affect retained data.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
status["steps"].append(step)
            break
        try:
            completed = subprocess.run(
                ["python3", str(script_path)],
                cwd=str(WORKSPACE),
                check=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
The manifest describes a persistent memory workflow that reads logs, extracts knowledge, manages lifecycle, and renders a snapshot. Spawning external Python interpreters to run multiple scripts is a broader capability than the stated memory-purpose operations and introduces general command-execution behavior that is not explicitly justified by the manifest text.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The generated snapshot hardcodes English section headings and user-facing labels such as 'User', 'Prefers', 'Timezone', and multiple English section titles. This creates a locale-policy concern because the skill emits a fixed language regardless of the user's preferred language, even though a language preference field is available.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The script reads API credentials from the user's global OpenClaw config when environment variables are absent, which grants this skill access to a broader trust domain than its own local function requires. In a memory-consolidation context, this creates an unnecessary secret-access path and can enable unintended external use of the user's provider credentials if the skill is run without explicit per-skill configuration.

Description-Behavior Mismatch

Medium
Confidence
97% confidence
Finding
The code sends memory candidate content to an external Anthropic-compatible endpoint over HTTP(S), which may include sensitive session-derived facts, decisions, and user traits. Because the endpoint is configurable via environment or global config, this creates a real exfiltration path for persistent memory data to a remote service outside the local memory processor's expected boundary.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The skill transmits memory-candidate data to a remote endpoint without any explicit user-facing warning or consent mechanism in the code path. Since this skill processes persistent memory derived from session logs, lack of disclosure increases the risk of silent exposure of sensitive personal or operational data.

Description-Behavior Mismatch

Low
Confidence
82% confidence
Finding
The manifest describes a persistent memory system that reads session logs, extracts memories, manages lifecycle, and generates MEMORY_SNAPSHOT.md. In this config module, the skill also parses IDENTITY.md and USER.md to extract assistant and owner identity details, which goes beyond straightforward memory-consolidation configuration and log processing as described.

Natural-Language Policy Violations

Low
Confidence
75% confidence
Finding
The docstring explicitly constrains pattern handling to Chinese and English only. That is a natural-language locale limitation, and the file does not indicate user opt-in, configurability, or a documented region-specific justification for excluding other languages.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
The generated summary text is hard-coded in Chinese, which forces one language for user-visible output regardless of user preference or environment. The file does not offer a locale choice or document that the skill is intentionally limited to a Chinese-language context.

Static analysis

No suspicious patterns detected.