Back to skill

Security audit

Smart Memory

Security checks for vulnerabilities and agentic risk

Overview

This is a local memory skill with no external exfiltration found, but it automatically persists sensitive conversation data, including API keys, in plaintext and has unclear deletion behavior.

Install only if you are comfortable with a local plaintext memory database that may store personal facts, project details, standing instructions, and credentials unless the agent avoids doing so. Do not store API keys, passwords, tokens, or private infrastructure details with this skill. Review and restrict ~/.openclaw/smart-memory permissions, treat exports and stats output as sensitive, and verify deletion behavior before relying on forget requests.

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)

T09 · Insecure Skill Coding Practices

Warning
Location
memory-manager.sh:21
Finding
Automatic Plaintext Retention of Sensitive Conversation Data## Vulnerability Details **File Location**: `SKILL.md:27-39`; `memory-manager.sh:21-25`, `memory-manager.sh:77-109`, and `memory-manager.sh:207-225` **Vulnerability Type**: Plaintext sensitive-data storage with insufficient access-control hardening **Risk Level**: Medium The Skill explicitly instructs the Agent to collect personal information, infrastructure details, server addresses, and API keys: ```markdown Automatically extract and store memories whenever the user shares: - **Preferences**: "I prefer dark mode", "I like Python over JavaScript" - **Personal facts**: names, locations, roles, team members, project names - **Decisions**: "We decided to use PostgreSQL", "Let's go with the microservice approach" - **Instructions**: "Always run tests before committing", "Never deploy on Fridays" - **Important dates**: deadlines, birthdays, recurring events - **Technical context**: stack details, repo URLs, server addresses, API keys (stored locally only) - **Corrections**: "Actually, my name is spelled with a K" (update existing memory) ``` The storage locations are ordinary local JSON files: ```bash MEMORY_DIR="${OPENCLAW_MEMORY_DIR:-$HOME/.openclaw/smart-memory}" MEMORIES_FILE="$MEMORY_DIR/memories.json" ARCHIVE_FILE="$MEMORY_DIR/archive.json" STATS_FILE="$MEMORY_DIR/stats.json" CONFIG_FILE="$MEMORY_DIR/config.json" ``` Initialization creates the directory and files without explicitly enforcing restrictive permission modes: ```bash cmd_init() { mkdir -p "$MEMORY_DIR" if [ ! -f "$MEMORIES_FILE" ]; then echo '{"memories":[],"version":"1.0.0","created":"'"$(now_iso)"'"}' | jq . > "$MEMORIES_FILE" info "Created memories store: $MEMORIES_FILE" fi if [ ! -f "$ARCHIVE_FILE" ]; then echo '{"archived":[],"version":"1.0.0"}' | jq . > "$ARCHIVE_FILE" info "Created archive: $ARCHIVE_FILE" fi if [ ! -f "$STATS_FILE" ]; then cat > "$ ...[truncated 3306 chars]
Remediation
## Remediation Suggestions 1. Prohibit storage of passwords, API keys, session tokens, private keys, recovery codes, and authentication headers. 2. Add secret-detection rules before persistence and reject or redact values matching known credential formats and high-entropy token patterns. 3. Require explicit user opt-in before retaining personal, technical, or otherwise sensitive information; do not infer consent from ordinary conversation. 4. Create the storage directory with `install -d -m 0700` or an equivalent operation and enforce `0600` on every JSON and lock file. 5. Set a restrictive `umask`, such as `umask 077`, at script startup. 6. Offer encryption at rest using an operating-system key store or another appropriately protected key source. Do not store the encryption key beside the data. 7. Apply the same controls to archived values, update history, exports, and backups. 8. Warn users that exports contain sensitive memory content and avoid sending exports to logs or shared output channels.

T02 · Agent Memory Poisoning

Warning
Location
SKILL.md:23
Finding
Persistent Instruction Poisoning Through Untrusted Conversation Memory## Vulnerability Details **File Location**: `SKILL.md:23-39` and `SKILL.md:63-73`; `memory-manager.sh:182-217` **Vulnerability Type**: Persistent storage and later reuse of attacker-controlled behavioral instructions **Risk Level**: Medium The Skill directs the Agent to automatically persist user-provided instructions: ```markdown ## When to STORE a Memory Automatically extract and store memories whenever the user shares: - **Preferences**: "I prefer dark mode", "I like Python over JavaScript" - **Personal facts**: names, locations, roles, team members, project names - **Decisions**: "We decided to use PostgreSQL", "Let's go with the microservice approach" - **Instructions**: "Always run tests before committing", "Never deploy on Fridays" - **Important dates**: deadlines, birthdays, recurring events - **Technical context**: stack details, repo URLs, server addresses, API keys (stored locally only) - **Corrections**: "Actually, my name is spelled with a K" (update existing memory) ``` It then directs the Agent to retrieve and apply these memories before responding: ```markdown ## When to RETRIEVE Memories Before responding to any user message, check if relevant memories exist: ```bash bash ~/.openclaw/smart-memory/memory-manager.sh search --query "<relevant keywords>" ``` Use retrieved memories to: - Personalize responses (use their name, reference their preferences) - Avoid asking questions you already know the answer to - Provide continuity across conversations - Reference past decisions and context ``` The implementation stores arbitrary values and metadata but does not enforce trust boundaries during insertion: ```bash local new_memory new_memory=$(jq -n \ --arg key "$key" \ --arg value "$value" \ --arg category "$category" \ --arg confidence "$confidence" \ --arg source "$source" \ --arg created "$timestamp" \ --arg updated "$timestamp" ...[truncated 2541 chars]
Remediation
## Remediation Suggestions 1. Do not automatically persist behavioral instructions. Require explicit confirmation from an authenticated user before creating or modifying standing guidance. 2. Separate factual memory from executable or behavioral policy. Retrieved memory should be treated as untrusted reference data, not as instructions. 3. Bind every entry to a specific authenticated user, tenant, workspace, project, and session context as appropriate. 4. Enforce authorization checks when storing, updating, retrieving, forgetting, exporting, and purging entries. 5. Prevent memory content from overriding current user requests or higher-priority system and developer instructions. 6. Display the proposed instruction, origin, scope, and expiration to the user before persistence. 7. Add expiration dates and periodic reconfirmation for standing instructions. 8. Preserve provenance and present it when retrieving entries, while ensuring provenance labels cannot be selected arbitrarily by an untrusted caller. 9. Add an auditable interface through which users can inspect and revoke all persistent instructions.

other

Warning
Location
memory-manager.sh:409
Finding
Forget Operation Retains Complete Memory Values in the Archive## Vulnerability Details **File Location**: `SKILL.md:87-93` and `SKILL.md:124-129`; `memory-manager.sh:409-430` and `memory-manager.sh:510-533` **Vulnerability Type**: Privacy retention mismatch and incomplete deletion **Risk Level**: Medium The documentation describes `forget` as a soft deletion: ```markdown ## When to FORGET a Memory If the user explicitly asks you to forget something: ```bash bash ~/.openclaw/smart-memory/memory-manager.sh forget --key "<key_to_forget>" ``` This soft-deletes the memory (marks it as forgotten but retains it in the archive for 30 days before permanent deletion). ``` This conflicts with the stated privacy rule: ```markdown ## Privacy & Security Rules 1. **All data stays local** — Never transmit memory contents to external services 2. **Respect forget requests** — When the user says "forget X", delete it immediately 3. **No sensitive data in logs** — Memory contents never appear in system logs ``` The implementation marks the active entry as forgotten and copies the complete original entry into the archive: ```bash # Soft-delete: mark as forgotten and move to archive local updated_file updated_file=$(jq --arg k "$key" --arg ts "$timestamp" ' .memories |= map( if .key == $k then .forgotten = true | .forgotten_at = $ts else . end ) ' "$MEMORIES_FILE") echo "$updated_file" > "$MEMORIES_FILE" # Copy to archive local archived_entry archived_entry=$(echo "$existing" | jq --arg ts "$timestamp" '. + {forgotten: true, forgotten_at: $ts}') local updated_archive updated_archive=$(jq --argjson entry "$archived_entry" '.archived += [$entry]' "$ARCHIVE_FILE") echo "$updated_archive" > "$ARCHIVE_FILE" # Update stats local updated_stats updated_stats=$(jq '.total_deletes += 1' "$STATS_FILE") echo "$updated_stats" > "$STATS_FILE" release_lock trap - EXIT echo "Forgotten memory: $key (archived for $ ...[truncated 2793 chars]
Remediation
## Remediation Suggestions 1. Change `forget` to remove all matching records immediately from both `memories.json` and `archive.json`. 2. Remove matching historical values and any other derived copies or indexes. 3. Perform deletion under the existing write lock and use atomic file replacement to avoid partial updates. 4. Clearly distinguish permanent deletion from optional soft deletion. If recovery is desired, expose it as a separate, explicitly named operation. 5. Do not claim immediate deletion while retaining recoverable copies. 6. If an archive is retained for a legitimate purpose, obtain explicit consent, encrypt it, restrict access, define a guaranteed deletion schedule, and document that limitation before data is stored. 7. Run expiry automatically rather than relying only on optional maintenance, and report deletion failures. 8. Add tests confirming that a forgotten key and its value cannot be found in active storage, archives, history, exports, or generated reports.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (12)

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding
The code mostly aligns with the declared local persistent memory/storage purpose: it stores, retrieves, updates, forgets, archives, and maintains memories in local JSON files without external APIs. However, there is a meaningful description/behavior mismatch because the description claims the skill 'automatically extracts' key facts from conversations and 'makes your bot smarter over time,' while the supplied code is only a command-line CRUD/maintenance tool and contains no conversation parsing or automatic extraction logic. Additionally, the code includes notable undeclared capabilities such as exporting all memories, purging all memories, and logging token-savings/statistics. These are related to memory management but are still extra capabilities not reflected in the declared description. Therefore this should be flagged as a mismatch, though the primary domain and resource usage are largely consistent.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The declared description presents the skill primarily as a persistent memory system that extracts, stores, and retrieves conversation facts using local JSON storage. The supplied code chunk does not implement those core memory operations. Instead, it is a reporting utility (`memory-stats.sh`) that analyzes existing local JSON files (`memories.json`, `archive.json`, `stats.json`) and prints a status report. While this is related to the broader memory skill and still uses local storage with no external APIs, the chunk’s actual purpose is analytics/monitoring rather than the declared primary functionality. That is a material description-behavior mismatch for this specific code chunk.

Missing User Warnings

High
Confidence
98% confidence
Finding
The skill instructs automatic persistence of conversation data, including sensitive items like API keys, without requiring explicit opt-in or warning the user about retention risks. In the context of a persistent cross-session memory tool, this makes accidental collection of secrets and personal data significantly more dangerous.

Ssd 3

High
Confidence
99% confidence
Finding
The instructions explicitly tell the agent to retain and store highly sensitive user data, including API keys, in persistent local memory. Even without network exfiltration, storing secrets in a broad-access local JSON repository creates serious exposure through local compromise, backups, logs, exports, archives, or accidental disclosure in later responses.

Session Persistence

Medium
Category
Rogue Agent
Content
tools:
  - shell
  - file_read
  - file_write
heartbeat:
  enabled: true
  interval: daily
Confidence
91% confidence
Finding
This skill establishes persistent cross-session storage and a daily heartbeat maintenance flow, which creates ongoing retention and processing of user data outside the immediate session. Session persistence is contextually central to the feature, but it still increases the blast radius of privacy mistakes and makes other findings more dangerous because stored data can survive and be reprocessed over time.

Ssd 3

Medium
Confidence
93% confidence
Finding
The directive to 'Remember everything important. Forget nothing the user cares about.' promotes broad, effectively indefinite retention of user information across sessions. In a persistent assistant context, this increases privacy risk, over-collection, and the chance that stale or sensitive personal data is retained beyond necessity.

Intent-Code Divergence

Medium
Confidence
94% confidence
Finding
The skill encourages storing highly sensitive material such as API keys while also performing usage logging and stats collection. Even if the logs are intended not to contain secrets, retaining secrets in a general-purpose memory store materially increases the chance of accidental disclosure through debugging, export, archive, or future code changes.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The skill directs the agent to perform write, update, forget, export, and purge operations on persistent user data, but the description does not prominently warn about these modifying and destructive capabilities. Users may enable or rely on the skill without understanding that it can materially alter or expose stored data.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The skill says forget requests are deleted immediately, but elsewhere states forgotten items are soft-deleted and retained for 30 days. That inconsistency can cause unauthorized retention of data the user explicitly asked to erase, creating privacy, compliance, and trust risks.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Ensure jq is available
require_jq() {
    command -v jq >/dev/null 2>&1 || die "jq is required but not installed. Install it: sudo apt install jq"
}

# ─── Init ────────────────────────────────────────────────────────────────────
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The export command prints the full memory store, including all persisted conversation-derived facts and preferences, directly to stdout with no confirmation, redaction, or warning. In agent workflows, stdout is commonly logged, piped, or exposed to calling processes, so this can unintentionally disclose sensitive user data even though the feature appears intentionally designed for backup/export.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
This script prints raw memory values, top accessed memory entries, date ranges, and the absolute storage path directly to stdout. In the context of a persistent-memory skill, those fields can contain sensitive personal facts, inferred preferences, or internal filesystem details, so running the report can expose data to logs, screenshots, terminal history, or other local observers even though no explicit warning or redaction is applied.

Static analysis

No suspicious patterns detected.