Back to skill

Security audit

Smart Memory (Zero Dep)

Security checks for vulnerabilities and agentic risk

Overview

This memory skill is purpose-aligned overall, but it needs review because it can persist conversation data, overwrite memory state, and has unsafe local file and temporary-file handling.

Review before installing. Use this only in a private workspace, avoid automatic extraction unless users explicitly opt in, and fix restore to accept only validated snapshot files. The /tmp cache and health script should be hardened before use on shared machines. Treat saved memories as untrusted data, not instructions.

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

T02 · Agent Memory Poisoning

Error
Location
scripts/extract_memories.sh:55
Finding

Persistent Agent Memory Poisoning Through Untrusted Conversation Extraction

Content
View full analysis
15 and not line.endswith("?"): tag = f"[{current_type}]" if current_type else "[TECH]" extracted.append(f"{tag} {line.lstrip('- *')}") if extracted: ts = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC") with open(daily_file, "a", encoding="utf-8") as f: f.write(f"\n## Auto-extracted ({ts})\n") for item in extracted[:10]: # Cap at 10 f.write(f"- {item}\n") ``` The associated workflow directs the Agent to persist and subsequently load this state: ```markdown Critical rule: Write BEFORE responding. When the user provides information that should be remembered: 1. Write to SESSION-STATE.md 2. Then respond to the user ``` ### Technical Analysis The extraction routine copies qualifying conversation lines almost verbatim into persistent daily memory. Acceptance depends only on line length, whether the line ends in a question mark, a limited sensitive-data regex, and broad classification keywords. There is no validation for imperative instructions, prompt injection, role changes, tool directives, policy overrides, or text intended to control future Agent behavior. There is also no structured trust boundary distinguish ...[truncated 1204 chars]
Remediation
View remediation

T02 · Agent Memory Poisoning

Error
Location
scripts/session_state.py:215
Finding

Arbitrary File Restore Into Trusted Session State

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/memory_health.sh:99
Finding

Python Code Injection Through Attacker-Controlled Temporary Filenames

Content
View full analysis
/dev/null | wc -l | tr -d '[:space:]' || echo 0) CACHE_COUNT=${CACHE_COUNT:-0} if [ "$CACHE_COUNT" -gt 0 ]; then echo " Active caches: $CACHE_COUNT" for cache in /tmp/openclaw-session-cache-*.json; do KEYS=$(python3 -c "import json; print(len(json.load(open('$cache'))))" 2>/dev/null || echo 0) echo " $(basename "$cache"): $KEYS entries" done ``` ### Technical Analysis Each matching `/tmp` filename is inserted directly into a Python program enclosed by single quotes. The shell's double quotes protect the shell command from ordinary word splitting, but they do not protect the generated Python source. On typical systems, untrusted local users can create filenames in `/tmp` containing quotes, parentheses, semicolons, and other characters meaningful to Python. A crafted filename can terminate the `open('...')` string and append arbitrary Python expressions. The resulting program executes under the account running `memory_health.sh`. ### Attack Path 1. A local attacker creates a file in `/tmp` whose name matches `openclaw-session-cache-*.json` and contains Python syntax that closes the quoted path. 2. The victim or Agent runs `scripts/memory_health.sh`. 3. The shell loop expands the malicious filename into the `python3 -c` source string. 4. Python parses the injected filename characters as executable source code. 5. The attacker's Python command runs with the privileges and environment of the victim account. ### Impact Assessment An attacker with permission to create files in the shared temporary directory can execute arbitrary code as the user running the health report. This can provide access to that user's files, workspace data, environment variables, Agent s ...[truncated 163 chars]
Remediation
View remediation
/dev/null || echo 0 ) ``` Additional hardening should include: - Implement the entire cache scan in Python to avoid mixed shell/Python quoting. - Enumerate files from a private cache directory rather than shared `/tmp`. - Verify that each path is a regular file, is not a symbolic link, and is owned by the expected user. - Apply file-size limits before JSON parsing. - Avoid parsing cache files belonging to other users or sessions. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/session_cache.py:18
Finding

Predictable Temporary Cache Permits Symlink Overwrite and Cross-Session Collisions

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/session_state.py:145
Finding

Sensitive-Data Hard Block Can Be Bypassed Through Unvalidated Write Paths

Content
View full analysis
Remediation
View remediation
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
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (21)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The code only covers a narrow subset of the declared functionality: classification and tagging of memory entries in markdown files, plus duplicate checking. While this partially aligns with 'memory type classification' and organizing memory files, the description presents a much broader memory system with extraction from conversations, decay/archival, temporary/session memory, HOT RAM/WAL mechanisms, search, and task-state tracking—none of which appear in this code. Additionally, the implemented classifier includes a PEOPLE type that is not listed in the declared memory categories. This is a material description-behavior mismatch because the declared purpose substantially overstates the capabilities of the supplied code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The code does support part of the description: automatic memory extraction from conversation text, basic memory type classification, writing to a memory file, and guidance about promoting items to MEMORY.md. However, most of the advanced system behaviors in the declared description are not present in this code chunk. There is no archival or decay logic, no temporary cache, no working-memory/HOT RAM implementation, no WAL protocol, no search capability, and no current-task state tracking. The actual behavior is much narrower: it is a daily-file extractor/appender script with simple keyword classification and sensitive-string filtering. Therefore the declared description materially overstates the implemented functionality.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description presents a broad, sophisticated memory-management system, but the supplied code implements only one narrow component: a temporary session cache backed by a JSON file. It does not extract memories from conversations, classify memories, archive stale data, implement WAL/HOT RAM semantics, or search memories by type. The only clear overlap is the session-scoped temporary cache portion of the description. Because the actual code chunk's behavior is substantially narrower and lacks most of the advertised capabilities, the description does not accurately represent this code chunk as provided.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

The code clearly supports part of the declared description: a session-scoped temporary cache / HOT RAM working memory with persistence and snapshot/restore behavior. However, most of the declared system's headline capabilities are absent. There is no conversation parsing or automatic extraction, no classification into memory categories, no broader memory-file organization, no cleanup of stale memories, and no search functionality. The code operates only on SESSION-STATE.md and snapshot files, not on MEMORY.md or a general long-term memory system. This is therefore a material description-to-behavior mismatch: the implementation is a narrower session state manager rather than the full enhanced memory system described.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill describes capabilities that read environment variables and perform local file reads/writes, but it does not declare any explicit tool scope or permissions boundary. In agent frameworks, missing scope declarations can cause overbroad access by default or make reviewers unable to verify intended access, increasing the risk of unauthorized persistence or workspace data modification.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The activation conditions are broad and include common phrases like 'remember this' or 'what are we working on', which can trigger the skill in ordinary conversations without a high-confidence intent match. In a memory-oriented skill, accidental activation is risky because it can cause unintentional storage, modification, or retrieval of user data beyond what the user expected.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill instructs automatic persistence of conversation-derived information to local files before responding, but it does not require a clear user-facing notice or consent flow for storing that data. This is dangerous because users may disclose sensitive personal, project, or operational information in normal dialogue without realizing it will be retained on disk, creating privacy, compliance, and data-retention risks.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger phrase "archive old stuff" is vague and likely to appear in ordinary conversation, which can cause the skill to initiate archival behavior without clear, informed user intent. In a memory-management skill that can move stored files, ambiguous natural-language triggers increase the risk of unintended state-changing actions and accidental data reorganization.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The rules authorize moving files into archive paths and compressing summaries, but they do not require warning the user that persisted data will be modified. In this skill context, these are destructive or at least state-altering operations on memory storage, so lack of explicit notice and consent can lead to unexpected data loss, reduced accessibility, or hard-to-audit changes.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The prompt explicitly instructs the agent to extract durable, long-term memories from full conversations, including categories such as preferences, projects, technical details, lessons, and people, but it provides no user-consent, minimization, or retention warning. Although it excludes credentials, it still encourages persistence of potentially sensitive personal and contextual data, which can create privacy, profiling, and over-retention risks if users are unaware their conversations are being mined for long-term memory.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script automatically persists conversation-derived content to a workspace memory file, but it does not require explicit user confirmation or provide a clear warning that extracted personal or sensitive facts will be stored long-term. Although it filters some obvious secrets, the regex is narrow and will not catch many categories of sensitive personal data, so users may unknowingly have private information retained on disk.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The guide explicitly instructs operators to store durable facts from conversations, including social and personal details via tags like [PEOPLE] and [PREF], into persistent memory files without defining consent limits, retention rules, or sensitivity boundaries. In a memory-management skill, this increases the chance of over-collection and long-term storage of personal data that users did not expect to be retained.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The top-level documentation claims the script 'Preserves high-value entries (LESSON, active PROJECT) based on rules.' In practice, daily-file archival is driven only by filename age, and MEMORY.md analysis only checks for missing type tags; there is no implemented rule that detects or preserves active PROJECT entries during archival.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script automatically moves files and modifies MEMORY.md without interactive confirmation, which creates a risk of unintended destructive changes when run in an agentic workflow. In the context of a memory-management skill that may be invoked automatically, this is more dangerous because an agent or user can trigger archival and promotion actions on local knowledge files without a second check, increasing the chance of accidental data loss or integrity issues.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The module docstring and CLI description frame this file as a 'Temporal decay and archival' tool for stale memory files, but the code also implements a separate capability that mines repeated LESSON entries from daily files and writes them into MEMORY.md. That behavior is not an obvious implementation detail of archival/decay; it is a distinct memory-extraction/promotion feature.

Content

No source excerpt is available for this finding.

Tainted flow: 'CACHE_FILE' from os.environ.get (line 21, credential/environment) → pathlib.Path.write_text (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/session_cache.py (reported line 50)May include surrounding context.

python
def save_cache(data: dict):
    CACHE_FILE.write_text(json.dumps(data, indent=2, ensure_ascii=False), encoding="utf-8")


def cmd_set(key: str, value: str):

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The clear command unlinks the existing SESSION-STATE.md file and immediately reinitializes it, which is a destructive file operation. Although the file header describes the skill's general purpose, this specific irreversible action has no confirmation step and no inline warning to the user at the point of execution.

Content

No source excerpt is available for this finding.

Tainted flow: 'content' from pathlib.Path.read_text (line 201, file read) → pathlib.Path.write_text (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/session_state.py (reported line 221)May include surrounding context.

python
ts = datetime.now(timezone.utc).strftime("%Y%m%d-%H%M%S")
    snapshot_file = snapshot_dir / f"session-{ts}.md"
    content = read_state()
    snapshot_file.write_text(content, encoding="utf-8")
    # Keep only last 20 snapshots
    snapshots = sorted(snapshot_dir.glob("session-*.md"))
    while len(snapshots) > 20:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The restore command reads a snapshot and writes it over the active SESSION-STATE.md, replacing current session data. While it does create a backup snapshot first, there is no confirmation prompt or visible warning that the active state will be overwritten.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The restore command accepts a user-supplied file path via Path(file) and reads it if it exists, rather than restricting restores to the session snapshot directory. In an agent skill context, this expands the tool from 'restore a snapshot' into 'read arbitrary local files and copy their contents into SESSION-STATE.md', enabling unintended access to local files and persistence of their contents into memory files.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

Because restore will read any existing local path and then overwrite the active state with that content, it can be abused to ingest unrelated local files into the agent's working memory. In a memory-management skill, this is more dangerous because the resulting content may later be surfaced, snapshotted, searched, or incorporated into future agent outputs, turning a local file read into durable data exposure.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.