Back to skill

Security audit

Smart Memory

Security checks for vulnerabilities and agentic risk

Overview

This skill is not clearly malicious, but it needs review because it sets up long-lived memory and automatic session trimming that can change or lose agent conversation state.

Install only if you explicitly want this agent to maintain persistent memory and alter session-management files. Before enabling it, disable or replace FORCE-TRIM and tail -60 behavior, require user approval for auto-trim and cron/heartbeat changes, add backups and locking for any session rewrite, and avoid storing secrets or untrusted instruction-like text in startup-loaded memory.

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

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:274
Finding
Unsafe Hard-Cut Logic Can Corrupt or Destroy Active Session State<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:207-225`, `SKILL.md:274-291`, and `tools/safe-trim.py:86-116` **Vulnerability Type**: Unsafe destructive file handling and session-state corruption **Risk Level**: High ### Vulnerable Code `SKILL.md:274-291`: ```text # 1. Lese <workspace>/.openclaw/agents/main/sessions/sessions.json # 2. Finde alle Keys die ":channel:" enthalten UND KEIN ":thread:" haben # 3. Für jeden solchen Key: prüfe Zeilenanzahl der sessionFile (wc -l) # 4. Wenn > 500 Zeilen UND updatedAt > 2h her: # a. Generiere Hash: TRIM_READY_<4 random chars> # b. sessions_send(sessionKey=<key>, timeoutSeconds=90, # message="[WARTUNG] Schreibe jetzt alle offenen Themen und wichtigen Kontext # in memory/active-context.md. Füge danach exakt diese Zeile am Ende ein: # TRIM_HASH: <hash> # Antworte ausschließlich mit NO_REPLY.") # c. Lese memory/active-context.md → suche nach "TRIM_HASH: <hash>" # d. Hash gefunden: # - tail -60 <sessionFile> > /tmp/trim.jsonl && mv /tmp/trim.jsonl <sessionFile> # - Entferne TRIM_HASH-Zeile aus active-context.md # - Log: "<ISO> | <key> | TRIMMED" → memory/trim-log.txt # e. Hash nicht gefunden (Timeout): # - tail -60 <sessionFile> > /tmp/trim.jsonl && mv /tmp/trim.jsonl <sessionFile> # - Log: "<ISO> | <key> | FORCE-TRIM" → memory/trim-log.txt ``` `tools/safe-trim.py:86-116`: ```python # Find safe cutpoints: assistant turns with no pending toolCall candidates = [] for i, line in enumerate(lines): try: entry = json.loads(line) msg = entry.get("message", {}) if msg.get("role") != "assistant": continue content = msg.get("content", []) has_tool_call = any( isinstance(c, dict) and c.get("type") == "toolCall" for c in content ) if not has_tool_call: candidates.append(i) except Exception: continue # Pick the last candidate that s ...[truncated 3614 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove every raw `tail -60` truncation instruction and invoke one validated trimming implementation instead. 2. Never hard-cut when no safe boundary exists. Abort the operation, log the condition, and retry after the session reaches a valid completed turn. 3. Validate complete protocol relationships, including tool-call identifiers and corresponding tool results, rather than checking only whether an assistant message contains a `toolCall`. 4. Acquire an exclusive lock before reading and rewriting a session file. Recheck its inode, size, and modification time while holding the lock. 5. Write to a uniquely named temporary file in the same directory as the target, flush it with `fsync`, validate every retained JSONL record, and use an atomic replacement operation. 6. Avoid a predictable shared path such as `/tmp/trim.jsonl`. Use `tempfile.NamedTemporaryFile` or `mkstemp` with restrictive permissions. 7. Require both inactivity and a successful hash handshake before trimming. A timeout should postpone trimming rather than authorize destructive force trimming. 8. Preserve versioned backups and implement automatic rollback if the retained session fails JSON parsing or tool-exchange validation. 9. Restrict accepted session paths to the expected session directory after canonicalization, and reject symbolic links and non-regular files. 10. Add tests for concurrent writes, unmatched tool calls, unmatched tool results, malformed JSON lines, sessions without safe cut points, and simultaneous trim operations. ]]>

T02 · Agent Memory Poisoning

Error
Location
SKILL.md:59
Finding
Untrusted Conversation Content Can Be Promoted into Persistent Agent Instructions<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:59-76`, `SKILL.md:121-127`, `SKILL.md:147-151`, and `SKILL.md:336-338` **Vulnerability Type**: Persistent agent-memory poisoning **Risk Level**: High ### Vulnerable Instructions `SKILL.md:59-76`: ```markdown Befülle die Datei mit allem was aktuell offen ist (aus MEMORY.md, Tages-Logs, Kontext). Format pro Eintrag: ```markdown ## [OPEN] <Thema> — <Kurzbeschreibung> <Inhaltlicher Kontext: Was wurde erklärt, entschieden, vereinbart?> <Relevante Regeln oder Hintergründe die der Agent kennen muss> --- ``` Besonders wichtig: Kritische Regeln die oft vergessen werden → als `[OPEN]`-Block aufnehmen (auch wenn sie "immer" gelten — das ist der Punkt, sie bleiben sichtbar bis sie wirklich verinnerlicht sind). ``` `SKILL.md:121-127`: ```markdown ## Every Session Before doing anything else: 1. Read `SOUL.md` — this is who you are 2. Read `USER.md` — this is who you're helping 3. **If in MAIN SESSION:** Read `MEMORY.md` + `memory/active-context.md` 4. Read `memory/YYYY-MM-DD.md` (today + yesterday) for recent raw context ``` `SKILL.md:147-151`: ```text # TASK: Daily-Log automatisch schreiben (einmal täglich, abends) # Prüfe ob memory/YYYY-MM-DD.md für heute existiert. # Wenn NICHT: Lese memory/chat-YYYY-MM-DD.md → destilliere strukturelle Änderungen. # Schreibe Ergebnis nach memory/YYYY-MM-DD.md (max. 30 Zeilen). ``` `SKILL.md:336-338`: ```markdown | User erklärt etwas Wichtiges | → `[OPEN]`-Block in active-context.md mit vollem Kontext | | Strukturelle Änderung (Channel, Projekt, Regel) | → active-context.md **SOFORT in derselben Antwort** | | Technische Erkenntnis bei Coding | → CONTEXT.md **SOFORT** (nicht am Task-Ende) | ``` ### Technical Analysis The Skill directs the agent to copy or summarize content from conversations, daily logs, existing memory, and project context into persistent Markdown files. It specifically encourages important user statements and purported rules to be written immedi ...[truncated 3426 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Treat all conversation text, chat logs, external documents, and imported memory as untrusted data rather than agent instructions. 2. Require explicit, informed user approval before promoting any statement into a persistent rule or startup-loaded memory. 3. Store persistent entries in a structured schema with separate fields for content, source, author, timestamp, trust level, and approval status. 4. Delimit quoted material clearly and add a fixed instruction that quoted memory content must never override system, developer, safety, or current user instructions. 5. Detect and quarantine instruction-like phrases before persistence, especially requests to ignore safeguards, invoke tools, disclose data, modify memory policy, or change authority. 6. Limit automatic daily-log generation to factual summaries. Do not automatically convert chat statements into policies, credentials, commands, or behavioral rules. 7. Load only approved and validated rule fields during session startup. Keep unreviewed notes in a non-instructional retrieval store and expose them only when relevant. 8. Apply role-based write controls so lower-trust channel participants cannot create durable global rules. 9. Maintain an append-only audit trail and support review, expiration, revocation, and rollback of persistent memory entries. 10. Prevent recursive propagation: content originating from untrusted or unapproved memory must not be copied into another persistent layer without a fresh approval step. 11. Add adversarial tests covering quoted prompt injections, malicious project constraints, poisoned chat logs, and attempts to convert untrusted content into cross-project rules. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared purpose is memory architecture setup, but the body also introduces hidden operational behavior for heartbeat-driven session inspection, trimming, and direct modification of internal OpenClaw session files. That mismatch is dangerous because users and orchestrators may approve the skill for benign memory organization while unknowingly granting it authority to alter runtime infrastructure and conversation state.

Intent-Code Divergence

High
Confidence
98% confidence
Finding
The document explicitly warns that naive tail-based trimming can leave sessions in an invalid state, then provides a heartbeat template that does exactly that with tail -60 and in-place replacement. This contradiction is dangerous because it normalizes a known-unsafe maintenance action that can silently break session integrity or lose structured tool exchange context.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill clearly instructs file reads and writes across the workspace, but it declares no explicit tool scope or allowed-tools boundary. That creates an authorization ambiguity where an agent may perform broader filesystem operations than a user expects, especially because the document later expands into maintenance of internal session files.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The file begins its operational instructions in German ('Was dieses Skill tut') and continues primarily in German for the rest of the skill. This imposes a specific language on users and agents without documenting a locale requirement or offering an alternative language option.

Ssd 3

Medium
Confidence
89% confidence
Finding
The skill repeatedly instructs the agent to persist detailed user-provided context, rules, and project information across multiple files and sessions. Without minimization, classification, or retention controls, this creates a durable data-retention surface that can leak sensitive information to later prompts, other agents, or anyone with workspace access.

Ssd 3

Medium
Confidence
91% confidence
Finding
The startup flow instructs sub-agents to inject agent and project context on demand, enabling broad propagation of stored user and project data across agent boundaries. In a multi-agent system, that increases the chance of oversharing, least-privilege violations, and accidental disclosure of information irrelevant to the spawned task.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
A skill presented as setup guidance extends into ongoing automated trimming and lifecycle management of sessions, which is a materially different operational function. This increases danger because the agent is instructed to keep acting on future sessions, not just perform a one-time initialization, expanding the persistence and blast radius of the skill.

Ssd 3

Medium
Confidence
93% confidence
Finding
The auto-trim handshake tells sessions to write all open topics and important context into shared memory before maintenance, encouraging indiscriminate capture of conversation contents. Because it is tied to automated maintenance and hidden via NO_REPLY, it can silently promote excessive retention of potentially sensitive chat data without meaningful human review.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The procedure reads and rewrites internal OpenClaw session infrastructure, including sessions.json and session files, which goes beyond normal memory management and touches platform state directly. Modifying internal session artifacts can corrupt agent state, destroy auditability, or interfere with active conversations if the assumptions in the document are wrong.

Unbounded Output

Medium
Category
Output Handling
Content
#!/usr/bin/env python3
"""
safe-trim.py — Trim an OpenClaw session file without cutting mid-tool-call.

Usage:
  python3 safe-trim.py <session_file> [--keep 60]
Confidence
60% confidence
Finding
Output size or generation rate is not bounded. Unbounded output enables denial-of-service through resource exhaustion, log flooding, or context-window stuffing.

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

Medium
Category
Data Flow
Content
print(f"OK: safe cut at line {cutpoint} (assistant turn, no pending tool calls)")

    trimmed = lines[cutpoint:]
    path.write_text("".join(trimmed))
    print(f"Trimmed: {len(lines)} → {len(trimmed)} lines. Backup: {backup.name}")
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.

Static analysis

No suspicious patterns detected.