Back to skill

Security audit

memory-plus

Security checks for vulnerabilities and agentic risk

Overview

This memory skill has a coherent purpose, but it needs Review because it installs persistent always-on agent memory behavior and can store or transmit complete conversations without adequate scoping or confirmation.

Review before installing. Only use this skill if you are comfortable with persistent memory being added to AGENTS.md, memory being searched on every message, complete conversations being saved, and stored text being sent to configured Ollama, embedding, or Milvus services. Prefer explicit memory commands, disable or firewall remote backends unless needed, and avoid saving secrets or sensitive conversations.

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)

T02 · Agent Memory Poisoning

Error
Location
SKILL.md:5
Finding

Persistent Memory Poisoning Through Untrusted Conversation Content

Content
View full analysis
The following rules need to be added to `~/.openclaw/workspace/AGENTS.md`. **Add the following content to the top of AGENTS.md:** ```markdown ## On every message Automatically search related memories and use them when results are returned: Exec: python3 $HOME/.openclaw/workspace/skills/memory-workflow/memory_ops.py search --query "[original user message]" --llm-answer --limit 3 ## /save command When the user sends /save, force the complete conversation from the current session into the memory system: Exec: cat << 'EOF' | python3 $HOME/.openclaw/workspace/skills/memory-workflow/scripts/save_session.py {"messages": [ {"role": "user", "content": "[obtained from the current conversation context]"}, {"role": "assistant", "content": "[obtained from the current conversation context]"} ]} EOF ``` ``` `memory_ops.py:38-52` stores message content without trust classification or instruction filtering: ```python # If a session file is specified, read and store multiple messages if session_file: try: with open(session_file, "r", encoding="utf-8") as f: session_data = json.load(f) messages = session_data.get("messages", []) if not isinstance(messages, list): messages = [messages] results = [] for msg in messages: msg_content = msg.get("content", "") if isinstance(msg, dict) else str(msg) if msg_content and not msg_content.strip().startswith("## System"): stored = store_memory(msg_content, tags) results.append(stored) ``` `scripts ...[truncated 3245 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/store.py:28
Finding

Sensitive Conversation Content Sent to Unauthenticated Plaintext Services

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/store.py:307
Finding

Milvus Expression Injection Through Unescaped Memory Content

Content
View full analysis
bool: """Check whether Milvus already contains identical content""" try: from pymilvus import Collection, connections connections.connect( host=MILVUS_HOST, port=MILVUS_PORT, alias='default' ) collection = Collection('memory_workflow') collection.load() results = collection.query( expr=f'content == "{content}"', output_fields=['id'], limit=1 ) return len(results) > 0 except Exception: return False ``` ### Technical Analysis The `content` value is attacker-controlled memory text and is inserted directly into a Milvus Boolean expression using string interpolation. Quotes, backslashes, logical operators, or other expression syntax inside the content can terminate or alter the intended string literal. This violates the separation between query syntax and data. Depending on the Milvus version and accepted expression grammar, crafted content may broaden the predicate, change its meaning, or trigger parser errors. Errors are silently handled by returning `False`, which fails open and causes the application to treat the content as non-duplicate. ### Attack Path 1. An attacker submits memory content containing a quotation mark followed by valid Milvus expression syntax. 2. `store_memory()` passes the content to `check_milvus_duplicate()`. 3. The f-string inserts the content directly into `content == "..."`. 4. Milvus parses the attacker-controlled characters as part of the expression rather than solely as a string value. 5. The attacker may manipulate the duplicate-check result or cause a query failure. 6. If parsing fails, the broad exception handler returns `False`, allowing repeated ...[truncated 571 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (30)

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

Critical
Category
Data Flow
Confidence
94% confidence
Finding

The destination for the Ollama request is derived from an environment variable and arbitrary memory content is sent to that endpoint with no validation, allowlist, or trust boundary enforcement. In practice this enables exfiltration of stored user content to an attacker-controlled or unintended internal service if the environment is influenced, making this both a privacy issue and a potential SSRF-style outbound channel.

Content

Scanner excerpt · scripts/store.py (reported line 130)May include surrounding context.

python
data=data,
            headers={"Content-Type": "application/json"}
        )
        with urlopen(req, timeout=15) as resp:
            result = json.loads(resp.read().decode("utf-8"))
            content = result.get("message", {}).get("content", "").strip()
        try:

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

Critical
Category
Data Flow
Confidence
95% confidence
Finding

The embedding request sends raw text to a URL derived from environment configuration without validating the target. If an attacker can influence EMBEDDING_URL or deployment configuration, sensitive memory content can be silently exfiltrated to an untrusted service or routed to unexpected internal network locations.

Content

Scanner excerpt · scripts/store.py (reported line 337)May include surrounding context.

python
data=data,
            headers={"Content-Type": "application/json"}
        )
        with urlopen(req, timeout=10) as resp:
            result = json.loads(resp.read().decode("utf-8"))
            embedding = result["data"][0]["embedding"]
            return embedding

Vague Triggers

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill auto-activates on very generic memory-related language such as '记忆', '记得', '搜一下', '整理', which commonly appears in ordinary conversation. That makes unintended invocation likely, and because the skill can perform persistence and retrieval actions, accidental activation can cause unnecessary data processing or storage without clear user intent.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The trigger table includes ambiguous single-character and generic verbs like '记', '存', '搜', '找', '删除', and '整理一下' with no scope constraints. Such broad triggers can match routine user language and cause the agent to store, search, consolidate, or prune memories unexpectedly, increasing the chance of privacy-impacting actions from normal conversation.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code sends full user text to an Ollama chat service for triple extraction with no user warning, approval, or sensitivity checks. This expands the exposure surface from local storage to networked model processing, increasing the risk of privacy leakage and unintended handling by another service.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

User text is forwarded verbatim to external LLM and embedding services, which is dangerous because prompts, secrets, credentials, and personal data may leave the local trust boundary unchanged. In this skill's context, the feature is specifically a memory system, so the content is more likely than average to contain durable, sensitive user information.

Content

No source excerpt is available for this finding.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/store.py (reported line 174)May include surrounding context.

python
return valid, "llm"
    rule_triples = extract_triples_rule(text)
    if rule_triples:
        return rule_triples, "rule"
    return [], "none"

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code transmits memory text to an embedding service without informing the user or obtaining approval, and the default endpoint is a network service outside the process boundary. Because embeddings are generated from raw content, sensitive data may be disclosed to another host even when users expect local-only storage.

Content

No source excerpt is available for this finding.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · scripts/tools.py (reported line 57)May include surrounding context.

python
capture_output=True,
                text=True,
                timeout=30,
                env={**os.environ, "PYTHONPATH": str(Path(__file__).parent.parent)}
            )
            if result.returncode != 0:
                return {"success": False, "error": result.stderr or result.stdout}

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README presents the skill description entirely in Chinese and frames the assistant as a Chinese-language helper without any indication that users may choose another language. Under the policy, forcing a specific language without opt-in is a natural-language policy concern unless the locale restriction is explicitly justified.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README advertises commands that store, deduplicate, prune, and save session data, but it does not clearly warn users that these operations write persistent memory or may delete existing user data. In an agent-tooling context, unclear documentation around destructive or persistent actions can lead to unintended retention or loss of sensitive information.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The /save workflow instructs the agent to persist the complete session conversation but does not require a user-facing warning about what will be stored, where it will be stored, or how long it will be retained. This creates a privacy and consent gap, especially because full conversations may contain credentials, personal data, or sensitive business information.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Saving the entire current session on a simple '/save' trigger creates a natural-language data retention risk because users may invoke it without appreciating that all prior messages, including sensitive content, will be written to persistent storage. The danger is amplified by the instruction to capture the '完整对话' rather than a scoped excerpt, which increases the chance of overcollection and later leakage.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code file contains natural-language strings for usage and command descriptions primarily in Chinese, while the policy requires flagging language or locale constraints that are imposed without user choice. There is no indication that the tool is region-specific or that users can select another language/locale.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The docstring and comments are written entirely in Chinese (for example, "Memory Workflow 配置" and "获取所有记忆文件,按日期倒序"), which imposes a specific language in user/developer-facing natural-language content without any opt-in or documented locale constraint. Under the stated policy, forcing a language or locale without user choice is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code file contains natural-language documentation entirely in Chinese, including the feature description and operational notes, with no indication that the skill is region-specific or that users may choose another language. The policy for this audit flags language or locale constraints when a skill appears to force a specific language without opt-in or justification.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The module docstring documents usage as python3 .../save_session.py <session_json_file>, implying the argument is a file path. However, the implementation at L22-L28 calls json.loads(sys.argv[1]), treating the argument as raw JSON text, and only falls back to stdin if no argument is provided. This is an active contradiction between the documented interface and actual behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script writes full session messages to a named temporary file on disk before passing them to another component. Although this is a common implementation pattern, session data may contain sensitive prompts, credentials, or personal data, and persisting it to disk increases exposure through local file access, backups, crash artifacts, or delayed deletion.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/save_session.py (reported line 45)May include surrounding context.

python
temp_file = f.name

    try:
        result = subprocess.run(
            [sys.executable, str(memory_ops), "store", "--session-file", temp_file, "--json"],
            capture_output=True, text=True, timeout=30
        )

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The module-level natural-language description is entirely in Chinese and presents the skill behavior in that locale only. Under the policy, forcing a specific language without user opt-in or a documented region-specific justification is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The storage pipeline accepts arbitrary content and persists or propagates it across file storage, FTS indexing, knowledge graph extraction, and Milvus without semantic filtering or minimization. This broad retention model increases the blast radius of any secret, personal data, or malicious content that enters the system and makes accidental over-collection more likely.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The function writes arbitrary memory content to local markdown files automatically, but the code provides no notice, consent, retention control, or sensitivity filtering. This can lead to unintended persistence of secrets, personal data, or confidential prompts on disk where other local processes or users may later access them.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
82% confidence
Finding

The file presents itself as a set of memory workflow tools, but its core implementation delegates every operation by spawning a separate Python process with subprocess.run. Launching child processes and inheriting the full environment is a broader execution capability than the tool descriptions suggest, and that capability is not justified by any stated manifest purpose because no manifest is available.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/tools.py (reported line 52)May include surrounding context.

python
if extra_args:
            cmd.extend(extra_args)
        try:
            result = subprocess.run(
                cmd,
                capture_output=True,
                text=True,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
78% confidence
Finding

The dedup and consolidate tools trigger backend operations that remove duplicates or merge similar memory fragments, which can alter stored user data. In this file, those actions execute without any confirmation prompt or explicit user-facing warning beyond terse descriptions, so users may not realize their memory store will be modified.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.