Back to skill

Security audit

Self Reflection

Security checks for vulnerabilities and agentic risk

Overview

This skill is purpose-aligned self-reflection, but it can automatically read private session transcripts and persist derived guidance into high-trust agent instruction and memory files.

Install only if you explicitly want an unattended reflection agent that can read recent OpenClaw conversations and update persistent agent memory/instructions. Before using it, require a dry-run/review workflow, restrict eligible sessions, disable raw transcript output in cron logs, redact sensitive content, and do not allow automatic edits to AGENTS.md, TOOLS.md, MEMORY.md, or other skills without owner approval.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (3)

T02 · Agent Memory Poisoning

Error
Location
SKILL.md:22
Finding
Untrusted Session Content Can Poison Persistent Agent Instructions<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:22-35, 64-90` **Vulnerability Type**: Persistent memory and instruction poisoning **Risk Level**: High ### Vulnerable Code ```markdown ## Step 2: Read Session History For each interesting session from Step 1, read the JSONL transcript: ```bash # Read the last ~50 lines of each session file (keep it bounded!) tail -50 ~/.openclaw/agents/main/sessions/<sessionId>.jsonl ``` Parse the JSONL to understand what happened. Look for: - `type: "user"` or `type: "human"` — what was asked - `type: "assistant"` — what you responded - `type: "tool_use"` / `type: "tool_result"` — what tools were called and results - Error patterns, retries, confusion ``` ```markdown ## Step 4: Route Insights to the Right Files Each insight belongs somewhere specific. Route them: ### → `AGENTS.md` - Process improvements (how to handle sessions, memory, etc.) - New conventions or workflow rules - Safety lessons ### → `TOOLS.md` - Tool-specific gotchas ("gog needs --json flag for parsing") - Environment details (paths, configs, quirks) - New tool patterns discovered ### → `memory/YYYY-MM-DD.md` (today's date) - Session-specific context ("Brenner asked about X project") - Temporary facts that matter today but not forever - What happened today (events, decisions, requests) ### → `memory/about-user.md` - New preferences discovered - Communication style observations - Project/interest updates ### → `skills/<skill-name>/SKILL.md` - Improvements to specific skill instructions - Bug fixes in skill workflows - New parameters or approaches for a skill ### → `MEMORY.md` - Updates to the memory index if new memory files are created ``` ### Technical Analysis The Skill treats user-controlled transcript content as source material for persistent operational rules. It then directs the Agent to write derived insights into high-trust files such as `AGENTS.md`, `TOOLS.md`, `MEMORY.md`, and other `SKILL.md` files. The documented qualit ...[truncated 1947 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Treat every session transcript as untrusted data, regardless of whether it came from a direct or group conversation. 2. Prohibit automatic modifications to `AGENTS.md`, `TOOLS.md`, `MEMORY.md`, and all `SKILL.md` files based solely on transcript content. 3. Write proposed insights to a dedicated quarantine or review file that is never loaded as Agent instructions. 4. Require explicit workspace-owner approval before promoting any proposed insight into persistent instruction files. 5. Attach provenance metadata to every proposal, including the session key, message identifier, author type, timestamp, and exact supporting excerpt. 6. Reject proposals that contain behavioral directives, safety-policy changes, commands, URLs, credential material, requests to weaken validation, or instructions to modify tools and Skills. 7. Allow automatic persistence only for narrowly structured, non-executable factual notes after sensitive-data filtering. 8. Separate group-session and external-user content from owner-authorized content, and deny group participants the ability to influence persistent rules. 9. Add a security review step that evaluates whether an insight expands permissions, changes trust boundaries, or affects future tool execution. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/summarize-sessions.sh:11
Finding
Private Session Content May Be Exposed Through Reflection Output and Persistent Memory<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:11-35, 75-86`; `scripts/summarize-sessions.sh:11-17, 54-104` **Vulnerability Type**: Excessive access to and persistence of private conversation data **Risk Level**: Medium ### Vulnerable Code ```markdown ## Step 1: Gather Recent Sessions ```bash # List sessions active in the last 2 hours openclaw sessions --active 120 --json ``` Parse the output to get session keys and IDs. Skip subagent sessions (they're task workers, not interesting for reflection). Focus on: - Telegram group/topic sessions (real user interactions) - Direct sessions (1:1 with Brenner) - Cron-triggered sessions (how did automated tasks go?) ``` ```markdown ### → `memory/YYYY-MM-DD.md` (today's date) - Session-specific context ("Brenner asked about X project") - Temporary facts that matter today but not forever - What happened today (events, decisions, requests) ### → `memory/about-user.md` - New preferences discovered - Communication style observations - Project/interest updates ``` ```bash SESSIONS_DIR="$HOME/.openclaw/agents/main/sessions" MAX_LINES=50 # tail this many lines per session # Get active sessions as JSON sessions_json=$(openclaw sessions --active "$ACTIVE_MINUTES" --json 2>/dev/null) ``` ```python # Read last N lines try: result = subprocess.run(['tail', '-n', str(max_lines), jsonl_path], capture_output=True, text=True, timeout=5) lines = result.stdout.strip().split('\n') except Exception: continue # Extract meaningful exchanges exchanges = [] for line in lines: try: entry = json.loads(line) except json.JSONDecodeError: continue etype = entry.get('type', '') if etype in ('user', 'human'): # User message content = entry.get('content', '') if isinstance(content, list): content = ' '.join( p.get('text', '') for p in content if isinstance(p, dict) and p.get('type') == 't ...[truncated 3373 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Use an explicit session allowlist rather than processing all recently active direct, group, and cron sessions. 2. Require workspace-owner opt-in before processing direct or group conversations. 3. Exclude group sessions and sensitive channels by default. 4. Avoid printing raw user and assistant messages to standard output. Emit only aggregate metadata or redacted summaries. 5. Apply secret and personal-data detection before any content is printed or persisted. 6. Redact credentials, tokens, private keys, email addresses, phone numbers, financial information, and other sensitive identifiers. 7. Configure cron jobs so their output is not retained, emailed, or forwarded to centralized logs unless necessary and appropriately protected. 8. Restrict permissions on session transcripts, generated memory files, and any reflection logs. 9. Define retention limits and deletion procedures for derived memory and logs. 10. Record only the minimum information necessary for reflection and avoid durable user profiling unless explicitly authorized. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/summarize-sessions.sh:11
Finding
Shell Environment Value Is Unsafely Interpolated into Python Source<![CDATA[ ## Vulnerability Details **File Location**: `scripts/summarize-sessions.sh:11, 19-28` **Vulnerability Type**: Python code injection through an environment-derived path **Risk Level**: Medium ### Vulnerable Code ```bash SESSIONS_DIR="$HOME/.openclaw/agents/main/sessions" MAX_LINES=50 # tail this many lines per session # Get active sessions as JSON sessions_json=$(openclaw sessions --active "$ACTIVE_MINUTES" --json 2>/dev/null) # Parse session list echo "$sessions_json" | python3 -c " import json, sys, os, subprocess data = json.load(sys.stdin) sessions = data.get('sessions', []) sessions_dir = '$SESSIONS_DIR' max_lines = $MAX_LINES ``` ### Technical Analysis `SESSIONS_DIR` is derived from the `HOME` environment variable and expanded by the shell inside the source text passed to `python3 -c`. The expanded value is placed between Python single quotes, but it is not encoded or escaped as a Python string literal. A malicious `HOME` value containing a single quote and Python syntax can terminate the intended string and introduce additional statements into the generated Python program. Shell quoting around the original variable assignment does not make the value safe for interpolation into another programming language. For example, an attacker who controls the script environment could supply a value conceptually structured as: ```text /tmp/x'; __import__('os').system('ATTACKER_COMMAND'); # ``` This changes the effective Python source rather than merely changing the filesystem path. Exploitation depends on the attacker being able to influence `HOME` or the execution environment used by the cron or job runner. ### Attack Path 1. An attacker gains control over the `HOME` environment variable supplied to the script, such as through an unsafe job configuration, wrapper, or invocation environment. 2. The attacker sets `HOME` to a value containing a quote, injected Python statements, and a comment marker. 3. Bash expands `SESSIONS_DIR` inside the doub ...[truncated 853 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Do not interpolate shell values into Python source. Pass the path as a positional argument or environment variable. A positional-argument pattern is: ```bash python3 - "$SESSIONS_DIR" "$MAX_LINES" <<'PY' import json import os import subprocess import sys sessions_dir = sys.argv[1] max_lines = int(sys.argv[2]) # Continue with processing here. PY ``` Alternatively, export the value and retrieve it as data: ```bash export SESSIONS_DIR MAX_LINES python3 <<'PY' import os sessions_dir = os.environ["SESSIONS_DIR"] max_lines = int(os.environ["MAX_LINES"]) PY ``` Additional hardening should include: 1. Move the embedded Python program into a standalone, version-controlled `.py` file. 2. Validate that the resolved session directory is within the expected OpenClaw data directory. 3. Reject unexpected control characters in environment-derived paths. 4. Use a minimal, explicitly configured environment for scheduled execution. 5. Ensure untrusted users cannot modify cron definitions, wrappers, service environment files, or job-runner variables. 6. Preserve argument-array subprocess execution, as already used for `tail`, rather than introducing shell-based command construction. ]]>
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (6)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The documented purpose is reflective insight writing, but the behavior includes enumerating recent sessions and reading transcript files from a user home directory. A description/behavior mismatch is dangerous because it can hide sensitive-data access behind an innocuous label, reducing operator scrutiny and increasing the likelihood of unintended transcript collection or disclosure.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill uses shell access and file reads (`openclaw sessions`, `tail ~/.openclaw/...`) but declares no tool scope or permission boundary. That makes the skill over-privileged by default and increases the chance it will be executed with broader capabilities than intended, especially in an automated cron context.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The skill is framed to run hourly via cron with broad reflection over recent sessions, but lacks strict trigger constraints and clear exclusions beyond a few narrative notes. In an automated setting, vague activation criteria can cause repeated access to sensitive conversations, unnecessary file modifications, or reflection on sessions that should be excluded.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill directs the agent to append or edit several workspace files (`AGENTS.md`, `TOOLS.md`, memory files, and other skills) without an upfront warning or confirmation before modifying user data. Because it runs as a cron job, these writes may occur silently and persist potentially incorrect, privacy-sensitive, or prompt-influencing content across the workspace.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
The script enumerates active sessions and reads their transcript files from the user's session store without any minimization, consent prompt, or warning that sensitive conversation content will be surfaced. In a cron-driven self-reflection skill, this creates a real confidentiality risk because secrets, personal data, or proprietary prompts from unrelated sessions may be exposed in logs or downstream workspace files.

Ssd 3

Medium
Confidence
96% confidence
Finding
The summarizer extracts and prints raw USER and ASST message content, plus tool error text, directly from recent session transcripts. Because this skill is designed to run periodically as a cron job, the exposed plaintext can be captured by logs, monitoring systems, or other automation, amplifying the chance of unintended disclosure of sensitive data.

Static analysis

No suspicious patterns detected.