Back to skill

Security audit

Tiered Memory

Security checks for vulnerabilities and agentic risk

Overview

This skill is a real memory archiver, but it asks for unsafe optional install steps and persistent automated access to potentially sensitive memory without enough guardrails.

Review this skill before installing. Avoid the README's curl-to-shell Ollama install path; use a trusted packaged installer or verify any downloaded script first. Only enable the cron job if you want old OpenClaw memory files summarized, moved to archive, and retained in a permanent local SQLite database. Use --dry-run first, consider --skip-llm for sensitive logs, and plan how to inspect, protect, and delete the archive database.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
Findings (4)

T03 · Remote Payload Retrieval and Execution

Error
Location
README.md:253
Finding

Unverified Remote Installation Script Is Executed Directly by a Shell

Content
View full analysis

Vulnerability Details

File Location: README.md:253-257
Vulnerability Type: T03: Remote Payload Retrieval and Execution
Risk Level: Critical

Vulnerable Code

bash
### Install Ollama (Optional)

```bash
# For LLM-powered summarization
curl -fsSL https://ollama.com/install.sh | sh
ollama pull qwen2.5-coder:14b
text

### Technical Analysis

The installation instructions pipe content retrieved from an external URL directly into `sh`. The downloaded payload is mutable and is not pinned to a reviewed version, inspected before execution, or verified using a cryptographic checksum or publisher signature.

HTTPS protects the connection in transit but does not establish that the script currently hosted at the URL is identical to the script that was reviewed when this Skill was published. A compromise of the upstream server, distribution infrastructure, DNS or certificate trust chain, or the upstream publisher account could cause arbitrary replacement code to execute.

The Ollama dependency is relevant to optional LLM summarization, but immediate remote script execution is not the minimum privilege or safest installation mechanism necessary to provide that functionality.

### Attack Path

1. An attacker compromises the upstream installation endpoint or infrastructure capable of controlling its response.
2. The attacker replaces or modifies `install.sh` with a malicious payload.
3. A user follows the Skill's documented installation instructions.
4. `curl` retrieves the current attacker-controlled response.
5. The shell executes the response immediately, without an opportunity for inspection or integrity verification.
6. The payload performs arbitrary actions using all permissions available to the installing user. If the user runs the command through an elevated shell, the impact extends to elevated system permissions.

### Impact Assessment

Successful exploitation provides arbitrary code executi
...[truncated 509 chars]
Remediation
View remediation

Remediation Suggestions

  • Remove the curl | sh pipeline.
  • Prefer an operating-system package manager or the publisher's signed, versioned package.
  • If a script must be used, download it as a separate file and pin it to an immutable release.
  • Publish and verify a SHA-256 checksum or a trusted publisher signature before execution.
  • Instruct users to inspect the downloaded script before running it.
  • Run installation without administrative privileges unless a specific installation step demonstrably requires them.
  • Document Ollama as optional and make --skip-llm the safe default where practical.

T02 · Agent Memory Poisoning

Warning
Location
scripts/memory_archiver.py:112
Finding

Untrusted Memory Content Can Poison LLM-Generated Long-Term Archives

Content
View full analysis

Vulnerability Details

File Location: scripts/memory_archiver.py:112-135, with persistence at scripts/memory_archiver.py:185-205
Vulnerability Type: T02: Agent Memory Poisoning
Risk Level: Medium

Vulnerable Code

python
prompt = f"""You are a memory summarizer. Read this daily log and extract:
1. A concise summary (2-3 sentences)
2. Key facts learned (max 5 bullet points)
3. Main topics discussed (max 3 tags)

Format your response as:
SUMMARY: <summary text>
FACTS:
- <fact 1>
- <fact 2>
...
TOPICS: <tag1>, <tag2>, <tag3>

---
LOG CONTENT:
{content}
---
"""

try:
    result = subprocess.run(
        ["ollama", "run", OLLAMA_MODEL, prompt],
        capture_output=True,
        text=True,
        timeout=60
    )

    output = result.stdout.strip()
    return self._parse_summary(output)

The resulting model output is persisted as follows:

python
cursor.execute('''
    INSERT INTO archived_sessions 
    (source_file, session_date, summary, key_facts, topics, message_count)
    VALUES (?, ?, ?, ?, ?, ?)
''', (
    str(file_path),
    session_date,
    summary_data['summary'],
    json.dumps(summary_data['facts']),
    json.dumps(summary_data['topics']),
    summary_data.get('message_count', 0)
))

conn.commit()

Technical Analysis

Daily memory content is interpolated verbatim into the same prompt that contains the summarization instructions. There is no strong trust-boundary separation between system instructions and untrusted log data. A memory entry can contain prompt-injection text instructing the model to disregard the requested format, fabricate facts, omit important events, or generate misleading topics.

The parser validates only superficial prefixes such as SUMMARY:, FACTS:, and TOPICS:. It does not establish that generated facts are supported by source text. Accepted output ...[truncated 1613 chars]

Remediation
View remediation

Remediation Suggestions

  • Explicitly state that all log content is untrusted data and that instructions found inside it must never be followed.
  • Use a model interface supporting separate system and user messages rather than combining instructions and content into one string.
  • Request schema-constrained JSON and validate the complete response against a strict schema.
  • Require each extracted fact to include a supporting quotation or source-line reference.
  • Reject generated facts that cannot be traced to the source content.
  • Preserve provenance and clearly mark LLM-generated summaries as untrusted derived data.
  • Add an approval workflow before generated facts are promoted into trusted long-term memory.
  • Consider using deterministic, non-LLM fallback extraction for unattended archival.

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/tiered_memory.py:191
Finding

Unvalidated Session Identifier Permits Markdown File Path Traversal

Content
View full analysis

Vulnerability Details

File Location: scripts/tiered_memory.py:191-202
Vulnerability Type: T05: Unauthorized Access and Privilege Escalation
Risk Level: Medium

Vulnerable Code

python
# Try Tier 0 first (file system)
file_path = self.memory_dir / f"{date_str}.md"
if file_path.exists():
    try:
        content = file_path.read_text(encoding='utf-8')
        return {
            'date': date_str,
            'content': content,
            'tier': 0,
            'source': str(file_path)
        }
    except Exception as e:
        pass

Technical Analysis

The method documentation says date_str must use the YYYY-MM-DD format, but the implementation does not enforce that constraint. The value is directly incorporated into a filesystem path. Components such as ../ are therefore interpreted by the operating system rather than rejected.

The forced .md suffix limits direct access to filenames ending in .md, but it does not confine access to the configured memory directory. A value containing traversal components can resolve to another user-readable Markdown file outside that directory.

The issue becomes exploitable where an agent tool, API endpoint, plugin, or other caller passes untrusted input to get_session().

Attack Path

  1. An attacker gains control of the date_str argument supplied to get_session().
  2. The attacker provides a traversal value such as ../../target.
  3. The code constructs a path equivalent to memory_dir/../../target.md.
  4. The filesystem resolves the traversal components outside memory_dir.
  5. If the target exists and is readable by the process, read_text() loads it.
  6. The method returns the file contents and resolved source path to the caller.

Impact Assessment

Exploitation can disclose Markdown files accessible to the current process outside the intended OpenClaw memory directory. It does not bypass operating-sys ...[truncated 298 chars]

Remediation
View remediation

Remediation Suggestions

  • Validate the input with a full-match expression such as ^\d{4}-\d{2}-\d{2}$.
  • Parse the validated value with datetime.strptime() to reject impossible calendar dates.
  • Resolve both the base directory and candidate path before access.
  • Verify that the candidate's parent is exactly the resolved memory directory.
  • Reject absolute paths, path separators, traversal components, and symbolic-link escapes.
  • Avoid silently swallowing validation and file-access exceptions; return a controlled error that does not expose sensitive paths.

Example hardening approach:

python
import re
from datetime import datetime

if not re.fullmatch(r"\d{4}-\d{2}-\d{2}", date_str):
    raise ValueError("Invalid session date")

datetime.strptime(date_str, "%Y-%m-%d")

base = self.memory_dir.resolve()
candidate = (base / f"{date_str}.md").resolve()

if candidate.parent != base:
    raise ValueError("Session path escapes memory directory")

T08 · Insecure Dependencies

Warning
Location
references/qmd-setup.md:45
Finding

Setup Guide Installs Unpinned Python Dependencies

Content
View full analysis

Vulnerability Details

File Location: references/qmd-setup.md:45-51
Vulnerability Type: T08: Insecure Dependencies
Risk Level: Medium

Vulnerable Code

bash
# Check CUDA is available
nvidia-smi

# Install PyTorch with CUDA
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121

# Install sentence-transformers
pip install sentence-transformers

Technical Analysis

The instructions install packages without exact version constraints or hash verification. As a result, the effective dependency set can change after the Skill has been reviewed. Transitive dependencies are also unconstrained.

The PyTorch command identifies a dedicated package index but does not pin package versions or artifacts. The sentence-transformers command relies on the environment's default package-index configuration. Package installation may execute build backends, setup logic, native components, and imported code with the privileges of the invoking user.

No evidence was found that the named packages are intentionally malicious. The risk is uncontrolled supply-chain mutability rather than a confirmed malicious package.

Attack Path

  1. A user follows the QMD setup instructions.
  2. pip resolves the latest compatible direct and transitive package versions at installation time.
  3. An upstream account, release, dependency, configured package index, or artifact is compromised or replaced.
  4. pip downloads the affected package because no reviewed version or hash is enforced.
  5. Package installation or later import executes attacker-controlled code under the user's account.

Impact Assessment

A compromised dependency can execute code with the privileges of the user running pip or importing the installed package. This can expose application data and OpenClaw memory, modify the Python environment, or install additional payloads.

The instructions do not explicitly us ...[truncated 125 chars]

Remediation
View remediation

Remediation Suggestions

  • Pin all direct dependencies to reviewed exact versions.
  • Generate a lock file that also fixes transitive dependency versions.
  • Require artifact hashes, for example through a requirements file used with pip --require-hashes.
  • Explicitly define approved package indexes and avoid inheriting untrusted environment configuration.
  • Install dependencies inside a dedicated virtual environment rather than the global Python environment.
  • Periodically review and deliberately update pinned dependencies after vulnerability and integrity checks.
  • Document supported Python, CUDA, PyTorch, and sentence-transformers version combinations.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (19)

External Script Fetching

High
Category
Supply Chain
Confidence
98% confidence
Finding

The README instructs users to pipe a remotely fetched script directly into the shell, which can lead to arbitrary code execution if the remote server, transport, or installer content is compromised. This is especially dangerous in an agent skill setup document because users may copy-paste commands into environments that also contain credentials, memory stores, and agent tooling.

Content

Scanner excerpt · README.md (reported line 256)May include surrounding context.

bash
# For LLM-powered summarization
curl -fsSL https://ollama.com/install.sh | sh
ollama pull qwen2.5-coder:14b

Chaining Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

The use of a shell pipeline ending in '| sh' is a classic chaining-abuse pattern because it combines network retrieval and immediate execution in one step, eliminating review opportunities and amplifying compromise impact. In this skill's context, that risk is heightened because installation occurs alongside a component that processes and stores memory data, so a compromised installer could access sensitive archives or modify agent behavior.

Content

Scanner excerpt · README.md (reported line 256)May include surrounding context.

bash
# For LLM-powered summarization
curl -fsSL https://ollama.com/install.sh | sh
ollama pull qwen2.5-coder:14b

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The documented behavior materially overstates what the skill does, including claims about QMD semantic search, automatic archival, and LLM summarization. This kind of mismatch is security-relevant because operators may trust the skill with sensitive memory data under false assumptions about how it is processed, stored, or searched.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The README instructs users to enable unattended archival of memory files and describes permanent SQLite storage, but it does not prominently warn that historical session content will be summarized, moved, and retained long-term. In a memory-management skill, this creates a real privacy and integrity risk because users may deploy it expecting temporary recall rather than persistent archival and mutation of past records.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
91% confidence
Finding

The README recommends installing a cron job that runs daily and continuously processes agent memory, creating durable session persistence without additional runtime consent or visibility. In the context of an agent memory skill, persistence is the core feature, but it still increases exposure of potentially sensitive conversations and makes accidental over-retention more likely.

Content

Scanner excerpt · README.md (reported line 55)May include surrounding context.

bash
# Add to crontab - runs daily at 2 AM
crontab -e

# Add this line:
0 2 * * * /usr/bin/python3 ~/.openclaw/skills/tiered-memory/scripts/memory_archiver.py --days 14 >> ~/.openclaw/workspace/memory/archive.log 2>&1

Session Persistence

Medium
Category
Rogue Agent
Confidence
89% confidence
Finding

The documented SQLite schema stores archived session summaries, key facts, and topics in a permanent local database, which is a form of session persistence that may retain sensitive agent-derived information longer than intended. Because this skill is explicitly about long-term memory, the persistence is contextually expected, but it remains security-relevant if users are not warned about retention and access controls.

Content

Scanner excerpt · README.md (reported line 197)May include surrounding context.

sql
-- Archived sessions with summaries
CREATE TABLE archived_sessions (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    source_file TEXT NOT NULL,
    session_date DATE NOT NULL,

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill instructs users to run shell commands and access local files, but it does not declare an explicit tool scope such as permissions or allowed-tools. That omission weakens security review and can cause agents or users to grant broader capabilities than necessary, especially for a memory skill that touches persistent local data.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 63)May include surrounding context.

2. Set Up Archive Directory

bash
mkdir -p ~/.openclaw/workspace/memory/archive

3. Install Cron Job (Auto-archive)

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

The cron job establishes recurring automated processing of memory data, creating persistent behavior that continues after initial setup. Persistence is not inherently malicious here, but it increases attack surface and risk because sensitive files will be processed regularly without per-run user review, and compromise of the script or environment would have durable effects.

Content

Scanner excerpt · SKILL.md (reported line 70)May include surrounding context.

bash
# Add to crontab
crontab -e

# Add this line for daily 2 AM archive
0 2 * * * /usr/bin/python3 ~/.openclaw/skills/tiered-memory/scripts/memory_archiver.py --days 14 >> ~/.openclaw/workspace/memory/archive.log 2>&1

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 144)May include surrounding context.

Database Schema

sql
CREATE TABLE archived_sessions (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    source_file TEXT NOT NULL,
    session_date DATE NOT NULL,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill mentions Ollama-based summarization but does not present a clear warning that memory contents may be transmitted to an LLM service during archiving. For a memory-management skill, archived content can include sensitive conversations, credentials, internal plans, or personal data, so silent model exposure materially increases confidentiality risk.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The prompt explicitly asks the model to extract and retain 'key facts learned' from daily logs for long-term storage. In a memory-management skill, this is contextually more dangerous because the source material is likely to include sensitive user-provided information, and the extraction step can preserve private details in a searchable archive even after original files are moved.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
90% confidence
Finding

The script passes full memory log contents to an external subprocess (ollama run) for summarization. Although subprocess.run is used safely with an argument list rather than a shell, this still creates a data exposure boundary because sensitive memory contents leave the Python process and are handled by another executable/model runtime.

Content

Scanner excerpt · scripts/memory_archiver.py (reported line 127)May include surrounding context.

python
"""
        
        try:
            result = subprocess.run(
                ["ollama", "run", OLLAMA_MODEL, prompt],
                capture_output=True,
                text=True,

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill invokes an external LLM subprocess to process archived memory content, which may contain sensitive user data. Even if Ollama is local, this expands the trust boundary and may expose data to model logs, plugins, future remote backends, or other components outside the main application’s access controls.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Memory contents are sent to an LLM subprocess without an explicit warning or consent flow. Because memory logs can contain personal, confidential, or security-relevant information, silently forwarding them for summarization creates a privacy and data-handling risk even when no network transmission is obvious from this code.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script automatically moves memory files from the active directory into an archive directory, altering local user data state. Without an explicit warning, confirmation, or transactional rollback, users may lose expected access patterns or encounter operational issues if other tools depend on those files remaining in place.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The module docstring and class docstring explicitly state that Tier 0 is QMD semantic search. However, the corresponding implementation reads Markdown files directly and performs simple keyword containment checks, so the documentation actively misstates how the system behaves.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The manifest describes a two-tier memory system where Tier 0 is QMD semantic search for recent memories. In this file, Tier 0 is implemented by iterating over local .md files and checking whether the lowercase query string appears in the file content, which is materially different from semantic search and from using QMD.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The manifest focuses on tiered memory storage and automatic archival with summarization, but this script also provides CLI capabilities to list all archived sessions and search archived summaries/facts. Those retrieval features are additional user-facing behaviors not reflected in the stated description of this component.

Content

No source excerpt is available for this finding.