Back to skill

Security audit

Memory Core

Security checks for vulnerabilities and agentic risk

Overview

This memory skill is functional, but it may send saved memories and search queries to a cloud embedding service by default while reusing an existing local API key despite claiming local-first behavior.

Install only if you are comfortable with persistent local memory and with memory text or search queries being sent to SiliconFlow or another configured embedding provider. Prefer configuring Ollama or local_mock before use, avoid storing secrets or highly sensitive personal data, and review whether automatic reuse of ~/.openclaw/openclaw.json credentials is acceptable in your environment.

Vulnerability Patterns
  • 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
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • 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 (1)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/embedding.py:13
Finding
Cloud embedding is enabled by default and transmits memory content without explicit per-use consent<![CDATA[ ## Vulnerability Details **File Location**: `scripts/embedding.py:13-25, 37-55`; `scripts/config.py:42-49, 108-112`; `scripts/memory_manager.py:67-71, 82-91`; `README.md:13-17, 43-51`; `SKILL.md:13-17, 58-76` **Vulnerability Type**: Sensitive data disclosure through default cloud processing **Risk Level**: High ### Vulnerable Code ```python # scripts/config.py:42-49 defaults = { "embedding": { "provider": os.getenv("MEMORY_CORE_EMBEDDING_PROVIDER", "siliconflow"), "model": os.getenv("MEMORY_CORE_EMBEDDING_MODEL", "BAAI/bge-m3"), "api_key": os.getenv("MEMORY_CORE_EMBEDDING_API_KEY", ""), "base_url": os.getenv("MEMORY_CORE_EMBEDDING_BASE_URL", "https://api.siliconflow.cn/v1"), "timeout_sec": float(os.getenv("MEMORY_CORE_EMBEDDING_TIMEOUT_SEC", "15")), "max_input_chars": int(os.getenv("MEMORY_CORE_EMBEDDING_MAX_INPUT_CHARS", "2000")), }, ``` ```python # scripts/config.py:108-112 if cfg.get("embedding", {}).get("provider") == "siliconflow" and not cfg.get("embedding", {}).get("api_key"): sf = _load_siliconflow_key_from_openclaw() cfg["embedding"] = _deep_merge(cfg.get("embedding") or {}, sf) return cfg ``` ```python # scripts/embedding.py:13-25 def _openai_embeddings(text: str, api_key: str, base_url: str, model: str, timeout_sec: float): if not api_key: return _mock_vector(text) base = base_url.rstrip("/") if not base.endswith("/v1"): base = f"{base}/v1" url = f"{base}/embeddings" r = requests.post( url, json={"model": model, "input": text}, headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}, timeout=(3, timeout_sec), ) r.raise_for_status() return r.json()["data"][0]["embedding"] ``` ```python # scripts/embedding.py:37-55 def get_embedding(text: str): cfg = get_config() emb = cfg.get("embedding") or {} provider = emb.get("provider") or "siliconflow" model = e ...[truncated 4797 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Change the default provider to a local implementation such as Ollama. Cloud embeddings should require explicit opt-in: ```python "provider": os.getenv("MEMORY_CORE_EMBEDDING_PROVIDER", "ollama"), "base_url": os.getenv("MEMORY_CORE_EMBEDDING_BASE_URL", "http://localhost:11434"), ``` 2. Do not automatically reuse credentials from `~/.openclaw/openclaw.json` unless the user has explicitly enabled cloud embeddings for this Skill. 3. Before the first cloud request, clearly disclose: - The destination provider and hostname. - That raw memory or query text will be transmitted. - The maximum transmitted input length. - Whether provider-side retention or logging may apply. 4. Require an explicit configuration value such as `allow_remote_embedding: true`; fail closed when a remote provider is selected without this consent. 5. Add optional local redaction for common sensitive values, including access tokens, passwords, private keys, email addresses, and financial identifiers. 6. Replace silent exception handling with an explicit error or a visible warning. Do not silently switch vector-generation algorithms because this conceals network failures and can degrade retrieval integrity. 7. Update `README.md` and `SKILL.md` to remove the claim that data does not leave the machine by default unless the implementation is changed to a local default. 8. Add tests confirming that: - No network request occurs under the default configuration. - Cloud requests require explicit opt-in. - Auto-discovered credentials are not used without consent. - Logs and error messages never expose bearer credentials. ]]>
Vulnerability Patterns
  • 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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (23)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The documented behavior claims local LanceDB-backed long-term memory with isolation controls, yet the analyzed behavior indicates those protections and storage logic are absent while external HTTP access to embedding providers is present. This mismatch can cause users to entrust sensitive long-term memory data to a skill that may transmit it externally without the advertised safeguards.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The README explicitly documents a cloud embedding configuration for a long-term memory system but does not clearly warn that memory content and queries may be transmitted to a third-party remote service for embedding. In this skill context, the transmitted data is especially sensitive because it consists of user memories, preferences, and potentially personal facts retained across sessions, so users may unknowingly send private data off-device.

External Transmission

Medium
Category
Data Exfiltration
Content
{
  "embedding_provider": "siliconflow",
  "embedding_model": "BAAI/bge-m3",
  "embedding_base_url": "https://api.siliconflow.cn/v1",
  "max_results": 5
}
```
Confidence
91% confidence
Finding
The documented endpoint points to an external embedding API, which means memory text and search queries may leave the local machine when this configuration is used. In a memory-core skill, that creates a real confidentiality risk because long-term memory often contains sensitive personal or operational data, and the README does not pair the example with a strong warning or consent guidance.

Lp3

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding
The skill declares executable commands and configuration that imply environment access, file reads, and possible network access, but it does not declare any tool scope or permissions boundary in the manifest. This weakens reviewability and least-privilege controls, making it easier for a host agent to run the skill with broader capabilities than users expect.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill encourages storing, retrieving, and deleting long-term memory but does not clearly warn users that data is persisted across sessions or explain retention and deletion semantics. For a memory feature, that omission materially increases the risk of users storing sensitive data without informed consent and misunderstanding whether deletion is complete.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The cloud embedding configuration describes a remote provider but does not explicitly warn that memory text or queries may be sent to an external service for embedding. In the context of a long-term memory skill, this is particularly sensitive because stored personal facts and recall queries may include confidential or identifying information.

External Transmission

Medium
Category
Data Exfiltration
Content
{
  "embedding_provider": "siliconflow",
  "embedding_model": "BAAI/bge-m3",
  "embedding_base_url": "https://api.siliconflow.cn/v1",
  "auto_budget": true,
  "default_tier": "medium",
  "embedding_timeout_sec": 15,
Confidence
78% confidence
Finding
The presence of a remote API endpoint indicates external transmission to a third-party service. While remote embedding can be legitimate, in a memory-storage skill it raises meaningful confidentiality concerns because user memories and queries may leave the local machine.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The code automatically reads an API key from the user's ~/.openclaw/openclaw.json and reuses it for this skill without an explicit consent or scoping check. This creates a cross-component secret-sharing issue: a memory skill can silently inherit credentials intended for another tool/provider configuration, increasing the risk of unintended secret use and data transmission to external services.

External Transmission

Medium
Category
Data Exfiltration
Content
base = (p or {}).get("baseUrl") or ""
        if "siliconflow" in k or "siliconflow" in base:
            api_key = (p or {}).get("apiKey") or ""
            base_url = base or "https://api.siliconflow.cn/v1"
            return {"api_key": api_key, "base_url": base_url}
    return {}
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
base = (p or {}).get("baseUrl") or ""
        if "siliconflow" in k or "siliconflow" in base:
            api_key = (p or {}).get("apiKey") or ""
            base_url = base or "https://api.siliconflow.cn/v1"
            return {"api_key": api_key, "base_url": base_url}
    return {}
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
base = (p or {}).get("baseUrl") or ""
        if "siliconflow" in k or "siliconflow" in base:
            api_key = (p or {}).get("apiKey") or ""
            base_url = base or "https://api.siliconflow.cn/v1"
            return {"api_key": api_key, "base_url": base_url}
    return {}
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
if not base.endswith("/v1"):
        base = f"{base}/v1"
    url = f"{base}/embeddings"
    r = requests.post(
        url,
        json={"model": model, "input": text},
        headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The code transmits the input text to a remote embeddings API via `requests.post`, which may send user data to OpenAI or SiliconFlow. There is no confirmation prompt, logging, comment, or docstring in this file warning that text content is sent off-box to third-party services.

External Transmission

Medium
Category
Data Exfiltration
Content
def _ollama_embeddings(text: str, base_url: str, model: str, timeout_sec: float):
    url = f"{base_url.rstrip('/')}/api/embeddings"
    r = requests.post(url, json={"model": model, "prompt": text}, timeout=(3, timeout_sec))
    r.raise_for_status()
    return r.json()["embedding"]
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
try:
        if provider in ("siliconflow", "openai"):
            if provider == "openai" and not base_url:
                base_url = "https://api.openai.com/v1"
            if provider == "siliconflow" and not base_url:
                base_url = "https://api.siliconflow.cn/v1"
            return _openai_embeddings(text_for_embedding, api_key, base_url, model, timeout_sec)
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
The code reads ~/.openclaw/openclaw.json to infer the agent's model tier, which is external local state unrelated to the core responsibility of storing and retrieving memory. Even though the value is only used for budgeting, this expands the skill's access to user-local configuration and creates unnecessary data exposure and coupling to sensitive local environment details.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The ingest method embeds and stores the provided text in a database via get_embedding and self.db.add, which affects user data persistence. In this file there is no confirmation prompt, user-facing log/print, docstring, or comment warning that input text will be stored as memory.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The trigger list includes very generic words such as "memory", "context", "remember", and their Chinese equivalents, which are likely to appear in ordinary conversations. In an agent framework, overly broad triggers can cause unintended activation of a memory skill, leading to accidental storage, recall, or deletion of user content and increasing the attack surface for prompt-driven misuse.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The manifest explicitly supports cloud embedding providers and API keys, but it does not disclose that stored or queried memory text may be transmitted to external services for embedding generation. Because this skill handles long-term memory and context, such transmission can expose sensitive user data, secrets, or conversation history to third parties without clear warning or consent.

Missing User Warnings

Low
Confidence
81% confidence
Finding
This function posts the text as `prompt` to an HTTP endpoint, which is a network transmission of user data. Although the default target is localhost, the configurable `base_url` could point elsewhere, and the file contains no user-facing warning, comment, or docstring describing this behavior.

Missing User Warnings

Low
Confidence
76% confidence
Finding
The code reads a local configuration file from the user's home directory without any visible notice or obvious necessity for the main memory feature. While the data accessed appears limited to agent/model settings, undisclosed local file reads reduce transparency and can expose environmental information that other components may not expect this skill to access.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
The manifest description is presented only in Chinese and does not indicate language selection or user opt-in. This can violate a language/locale policy when skills are expected to be language-neutral or to let users choose their preferred language.

Missing User Warnings

Low
Confidence
79% confidence
Finding
This code writes user-like personal/profile data into a memory system via `mm.ingest(...)` and immediately prints the stored results. While the script includes progress logging, it does not disclose that potentially sensitive user data is being persisted and echoed to output, which matters for code files handling user data.

Static analysis

No suspicious patterns detected.