Back to skill

Security audit

Fluid Memory

Security checks for vulnerabilities and agentic risk

Overview

This local memory skill is not exfiltrating data, but it stores broad chat content in plaintext and has under-disclosed retention and deletion behavior.

Install only if you are comfortable with a local plaintext memory system. Before enabling the hook, understand that it records sent messages to ~/.openclaw/workspace/database/conversation_log.txt with no built-in retention limit or purge shown in the inspected code. Use disk encryption or strict local permissions, avoid sending secrets while it is enabled, and manually review or delete the database files if you need to clear retained content.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
hooks/fluid-memory-sync/handler.js:40
Finding

Unbounded Plaintext Retention of Conversation Content

Content
View full analysis

Vulnerability Details

File Location: hooks/fluid-memory-sync/handler.js:40-66; fluid_skill.py:31-32; fluid_skill.py:234-245
Vulnerability Type: Plaintext sensitive-data storage and unbounded transcript retention
Risk Level: Medium

Vulnerable Code

javascript
export default async function handler(event) {
  // Only handle message:sent events
  if (event.type !== "message" || event.action !== "sent") {
    return;
  }

  // Skip if no content
  if (!event.content) {
    return;
  }

  try {
    // 记录对话到临时文件
    const timestamp = new Date().toISOString();
    const logEntry = `[${timestamp}] 用户说: ${event.content}\n`;
    
    // 确保目录存在
    const dir = path.dirname(CONVERSATION_LOG);
    if (!fs.existsSync(dir)) {
      fs.mkdirSync(dir, { recursive: true });
    }
    
    // 追加到日志文件
    fs.appendFileSync(CONVERSATION_LOG, logEntry);
    
    console.log("[fluid-memory-sync] 对话已记录,等待原生 flush 触发...");
    
  } catch (error) {
    console.error("[fluid-memory-sync] Failed to log conversation:", error.message);
  }
}

The summary buffer is also stored in plaintext:

python
# 增量总结缓冲区文件
BUFFER_FILE = os.path.join(WORKSPACE_ROOT, r"database\summary_buffer.json")
python
def _save_buffer(self, summary, round_count):
    """保存总结缓冲区"""
    os.makedirs(os.path.dirname(BUFFER_FILE), exist_ok=True)
    with open(BUFFER_FILE, 'w', encoding='utf-8') as f:
        json.dump({'summary': summary, 'round_count': round_count}, f, ensure_ascii=False)

Technical Analysis

Every qualifying message:sent event is appended verbatim to conversation_log.txt. The hook does not redact credentials or personal information, limit the transcript size, rotate the file, encrypt its contents, define a retention period, or explicitly create it with owner-only permissions.

Although the project documentation describes this transcript as temporary and ...[truncated 1888 chars]

Remediation
View remediation

Remediation Suggestions

  1. Disable raw transcript collection by default and require explicit user consent before retaining conversation content.
  2. Store only memories explicitly approved by the user instead of recording every qualifying message.
  3. Redact common secret formats, including API keys, authorization headers, passwords, private keys, session tokens, and access tokens.
  4. Create storage directories with mode 0700 and files with mode 0600 on platforms that support POSIX permissions.
  5. Validate that target files are regular files owned by the expected account before writing, and prevent symbolic-link traversal.
  6. Apply bounded retention, file-size limits, log rotation, and secure deletion after successful processing.
  7. Encrypt sensitive records at rest using an operating-system-backed key store or a user-managed encryption key.
  8. Clear conversation_log.txt only after processing succeeds, using an atomic workflow that prevents both data loss and indefinite retention.
  9. Store paths portably with separate components, for example:
python
DATABASE_DIR = os.path.join(WORKSPACE_ROOT, "database")
BUFFER_FILE = os.path.join(DATABASE_DIR, "summary_buffer.json")
CHROMA_PATH = os.path.join(DATABASE_DIR, "chroma_store")
  1. Document the exact event semantics, collected fields, retention period, deletion behavior, and local-access risks.

T08 · Insecure Dependencies

Note
Location
SKILL.md:8
Finding

Unpinned Third-Party Runtime Dependencies

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:8-10
Vulnerability Type: Unrestricted dependency resolution
Risk Level: Low

Vulnerable Code

json
"requires": {
  "bins": ["python"],
  "python_packages": ["chromadb", "pyyaml"]
}

Technical Analysis

The skill declares chromadb and pyyaml without exact versions, integrity hashes, or an accompanying lock file. As a result, different installations may resolve materially different package releases over time.

This weakens reproducibility and makes the effective reviewed code larger than the contents of the project. A future compromised, malicious, or incompatible dependency release could be installed without a corresponding change to this repository. No evidence was found that the currently named packages are malicious; the finding concerns the absence of dependency integrity controls.

Attack Path

  1. An attacker compromises a declared package, its release credentials, or the package-distribution channel.
  2. The attacker publishes a release under a version accepted by the unrestricted dependency declaration.
  3. A user installs or reinstalls the skill after that release becomes available.
  4. The package resolver selects the attacker-controlled release.
  5. Package installation or subsequent import executes dependency-controlled code under the agent user's account.

Impact Assessment

A malicious dependency would execute with the privileges of the account installing or running the skill. It could potentially read the plaintext conversation database, access files available to that account, modify agent state, or communicate with external systems.

The project does not request elevated installation privileges, so direct system-wide compromise is not established. The practical scope is normally the agent user's files, credentials, environment, and accessible services.

Remediation
View remediation

Remediation Suggestions

  1. Pin every runtime dependency to an explicitly reviewed version.
  2. Maintain a lock file containing cryptographic hashes for all direct and transitive dependencies.
  3. Install packages with hash verification, such as pip --require-hashes, where supported by the deployment platform.
  4. Use only trusted package indexes and disable unintended fallback to public or untrusted repositories.
  5. Perform dependency updates through an explicit review and testing process rather than automatically accepting new releases.
  6. Run vulnerability and software-composition scans against the locked dependency graph.
  7. Install and execute the skill in a least-privileged virtual environment that cannot access unrelated credentials or sensitive directories.
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
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (33)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

Permanent physical deletion of archived memories and direct modification of the local Chroma store goes beyond a benign 'forget/archive' abstraction and can cause irreversible data loss. In a memory-management skill, this is especially dangerous because users may expect reversible archiving rather than destructive deletion of stored data.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

Permanent physical deletion of archived memories and direct modification of the local Chroma store goes beyond a benign 'forget/archive' abstraction and can cause irreversible data loss. In a memory-management skill, this is especially dangerous because users may expect reversible archiving rather than destructive deletion of stored data.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

Permanent physical deletion of archived memories and direct modification of the local Chroma store goes beyond a benign 'forget/archive' abstraction and can cause irreversible data loss. In a memory-management skill, this is especially dangerous because users may expect reversible archiving rather than destructive deletion of stored data.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

Permanent physical deletion of archived memories and direct modification of the local Chroma store goes beyond a benign 'forget/archive' abstraction and can cause irreversible data loss. In a memory-management skill, this is especially dangerous because users may expect reversible archiving rather than destructive deletion of stored data.

Content

No source excerpt is available for this finding.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding

Suspicious Unicode normalization or mixed-script content

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README explicitly describes automatically logging every conversation to a local file and persisting summaries into a vector database, creating a clear data retention and exposure surface for sensitive user content. In the context of a memory skill, this behavior is functional, but the danger is elevated because collection is automatic, broad in scope, stored in plaintext, and tied to long-lived retrieval mechanisms.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill declares Python execution and package dependencies but does not define any explicit tool scope or allowed-tools boundary, while the described implementation implies shell, file, and environment access. That makes the skill harder to sandbox and review, and can expose broader host capabilities than users or operators expect.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

Automatic conversation recording without a clear warning or consent expectation creates a significant privacy risk because users may unknowingly have their chats stored and later retrieved. In a memory skill, hidden recording is more dangerous because the whole purpose is retention and resurfacing of prior content.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The recall triggers are broad enough to match ordinary conversation, which can cause the skill to invoke memory retrieval unexpectedly. Overbroad triggering can leak prior stored information into unrelated contexts and can also reinforce or expose sensitive memories without clear user intent.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The daemon searches multiple environment-controlled and PATH-derived interpreter locations, then uses the discovered binary to execute code. That creates an execution trust boundary on local environment state: a poisoned CONDA/CONDA_PREFIX/PATH or substituted python executable could cause arbitrary code execution under the daemon's privileges.

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 · dream_daemon.py (reported line 73)May include surrounding context.

python
"""执行维护脚本"""
    print(f"[{datetime.datetime.now()}] 🌙 梦境时刻到了,开始整理大脑...")
    try:
        result = subprocess.run(
            [PYTHON_PATH, MAINTENANCE_SCRIPT],
            capture_output=True,
            text=True

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill's natural-language interface, status/error messages, and instructional strings are written in Chinese throughout, with no mechanism for user language selection. This can violate language or locale policy when a skill imposes a specific language without opt-in or documented regional justification.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

When AUTO_LEARN is enabled, every recall operation silently writes the user's query into long-term memory. In a memory skill, queries can contain sensitive personal data, credentials, secrets, or regulated information, and persisting them without notice or consent creates a privacy and data-retention risk that can later expose or misuse that data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code writes conversation summaries to a local buffer file in the user's workspace without any warning, consent, or retention disclosure. Even summarized conversations can contain highly sensitive facts, preferences, tasks, or NSFW content, so silent local persistence increases the chance of unintended disclosure to other local users, tools, backups, or later processing.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The docstring at L279-L280 says the flow is 'load last summary → merge new conversation → write to ChromaDB → clear buffer'. In reality, the code writes to ChromaDB only when the round counter reaches SUMMARY_THRESHOLD; otherwise it saves the summary to BUFFER_FILE on disk at L315-L316 and does not write to ChromaDB.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The hook documentation explicitly states that every message:sent event appends conversation content to a local file, but it does not mention consent, visibility, retention limits, or handling of sensitive data. Because conversations may contain secrets or personal information, silent logging increases privacy and data-exposure risk, especially in shared or multi-user environments.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The file comment claims conversations are recorded to a temporary file until native flush occurs, but the implementation appends to a persistent conversation_log.txt file. This mismatch is dangerous because reviewers and users may underestimate data retention and privacy exposure, leading to uninformed deployment of a component that archives all messages.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill defines a separate local conversation log path under the workspace database and later stores raw message content there. Creating an additional datastore for full conversation text is sensitive because it duplicates user data without clear necessity for the advertised fluid-memory behavior, expanding exposure if the workstation or workspace is accessed by other processes or users.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The hook persistently appends every sent user message to conversation_log.txt even though the skill is described as a forgetting/archiving mechanism and the header comment says it records to a temporary file. This creates an unnecessary long-lived copy of potentially sensitive conversations, increasing privacy and retention risk beyond the stated purpose.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The handler writes raw event.content to a local file without any visible user notice, consent flow, or opt-out mechanism. Because message content may include secrets, personal data, or regulated information, silent logging materially increases privacy and compliance risk.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code logs all user message content verbatim to a persistent file, creating a comprehensive transcript outside the native memory system. This broad collection behavior is risky because it captures sensitive content indiscriminately and may outlive users' expectations about forgetting or fluid-memory decay.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill description emphasizes forgetting and archiving, but the implementation also performs irreversible hard deletion of archived memories after 120 days. This creates a data-destruction risk because users or downstream systems may reasonably expect archived data to remain recoverable, and the delete is automatic with no confirmation, backup, or explicit opt-in retention policy.

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 · wrapper.py (reported line 67)May include surrounding context.

python
elif action in ["summarize", "increment_summarize"] and conversation:
        cmd.extend(["--conversation", conversation])
    
    result = subprocess.run(cmd, capture_output=True, text=True)
    return result.stdout.strip()

# OpenClaw 会调用这个文件

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill launches another Python script via subprocess.run, which is a safety-relevant operation for code files. There is no confirmation prompt, logging/print statement describing the action, or explanatory comment/docstring near execution to disclose that the wrapper will spawn a separate process.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The primary descriptive content is presented in Chinese, and the README does not indicate any user choice, alternate locale, or justification for restricting the skill to that language. This can conflict with language/locale policy requirements when users are not given an opt-in or alternative.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.