Back to skill

Security audit

User Growth Coach

Security checks for vulnerabilities and agentic risk

Overview

This is a real reflection/journaling skill, but it broadly reads and stores OpenClaw conversation history for behavioral analysis without tight consent, scoping, or retention controls.

Install only if you want a Chinese-language coach that records reflections and can mine your OpenClaw session history. Before enabling cron or deep mode, restrict the sessions directory, avoid broad transcript ingestion, review where memory files are stored, and set your own retention/deletion process for daily digests and growth records.

Vulnerability Patterns
  • 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
  • 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
Findings (2)

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/extract-raw-inputs.py:84
Finding
Overbroad Collection and Persistent Retention of Private Session Transcripts<![CDATA[ ## Vulnerability Details **File Location**: `scripts/extract-raw-inputs.py:84-145`; `scripts/extract-daily-digest.py:269-302` **Vulnerability Type**: Overbroad access to private conversation history **Risk Level**: Medium ### Complete Vulnerable Code From `scripts/extract-raw-inputs.py:84-145`: ```python def main(): target_date = parse_args() events = [] session_files = glob.glob(os.path.join(SESSIONS_DIR, "*.jsonl")) for sf in session_files: basename = os.path.basename(sf) if ".lock" in basename or ".deleted" in basename or ".reset" in basename: continue try: with open(sf, "r", encoding="utf-8") as f: for line in f: line = line.strip() if not line: continue try: obj = json.loads(line) except json.JSONDecodeError: continue if obj.get("type") != "message": continue msg = obj.get("message", {}) if msg.get("role") != "user": continue ts_str = obj.get("timestamp", "") if not ts_str: continue try: ts = datetime.fromisoformat(ts_str.replace("Z", "+00:00")) ts_local = ts.astimezone(TZ) except (ValueError, TypeError): continue if ts_local.date() != target_date: continue user_text = extract_user_text(msg.get("content", "")) if user_text and len(user_text) > 2: # Filter cron/heartbeat/system/session-startup messages skip_patterns = [ "HEARTBEAT", "heartbeat", "[cron:", ...[truncated 4600 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require explicit opt-in before reading any session transcript. 2. Accept an explicit list of session IDs or transcript paths rather than enumerating every `*.jsonl` file. 3. Default to the active review session and require separate consent to include other conversations. 4. Add configurable exclusions for sensitive sessions, message categories, and content patterns. 5. Minimize retained data by storing summaries rather than verbatim messages whenever possible. 6. Implement a documented retention period and automatic deletion of expired daily digests. 7. Create output files with restrictive permissions, such as mode `0600`, and verify that parent directories are not accessible to unrelated users. 8. Avoid printing raw transcripts to shared temporary files or logs. 9. Document exactly which conversations are accessed and provide a preview before collection. 10. Record access provenance so users can identify which sessions contributed to a digest. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/extract-raw-inputs.py:136
Finding
Indirect Prompt Injection Through Untrusted Transcript Content<![CDATA[ ## Vulnerability Details **File Location**: `scripts/extract-raw-inputs.py:136-145`; `skill.md:296-324` **Vulnerability Type**: Untrusted transcript content inserted into an LLM summarization workflow without instruction isolation **Risk Level**: Medium ### Complete Vulnerable Code From `scripts/extract-raw-inputs.py:136-145`: ```python # Output a plaintext timeline print(f"# {target_date} raw user interaction records") print(f"# {len(events)} valid inputs") print() for e in events: print(f"[{e['time']}] {e['text']}") print() if __name__ == "__main__": main() ``` The corresponding workflow in `skill.md:296-324` instructs the cron session to process the generated file: ```markdown ### Process (Two Steps) **Step A: Extract raw inputs with the script** ```bash python3 <skill-dir>/scripts/extract-raw-inputs.py > /tmp/today-raw-inputs.txt ``` **Step B: LLM summarization in the cron session** Read `/tmp/today-raw-inputs.txt` and generate a structured daily summary using the supplied summarization prompt. The prompt requests: 1. A concise overview of the day. 2. Three to five important events, decisions, or discussions. 3. Projects, technology stacks, and links mentioned that day. 4. Unfinished work or follow-up commitments. 5. An overall emotional assessment. The generated result is written to: `memory/daily-digest/YYYY-MM-DD.md` ``` The documentation excerpt has been translated into English while preserving its operative meaning. ### Technical Analysis The extractor writes transcript text verbatim into a flat plaintext document. The Skill then instructs a cron-session LLM to read that document and summarize it. There is no structural separation between trusted workflow instructions and untrusted historical message content. A transcript entry can therefore contain imperative text such as instructions to ignore the summarization task, reveal available context, read another file, or invoke a tool. Becaus ...[truncated 2110 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Treat every extracted message as untrusted data and state this explicitly in the summarizer's highest-priority prompt. 2. Pass transcript records as structured JSON with separate fields for timestamp and message text rather than concatenating them into a flat instruction-like document. 3. Wrap each message in clear data delimiters and instruct the model never to execute or follow directives found inside those delimiters. 4. Run the summarization task in a tool-free agent with no shell, filesystem browsing, network, messaging, or memory-management capabilities beyond writing the designated output. 5. Restrict file access so the summarizer can read only the prepared input and write only the intended digest. 6. Validate the generated digest before persistence. Reject output containing tool requests, instruction overrides, unexpected links, or content unsupported by the source records. 7. Use a deterministic preprocessing layer to extract required fields where practical, reducing reliance on an agentic model. 8. Replace the predictable shared path `/tmp/today-raw-inputs.txt` with a securely created temporary file, mode `0600`, and delete it immediately after processing. 9. Clearly separate system instructions, summarization requirements, and transcript data in the model API request. 10. Add adversarial tests containing role markers, instruction overrides, encoded directives, and requests for tool use. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (39)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The declared description promises a reflective system that integrates current input, past retrospectives, and everyday context to detect deeper behavioral patterns. The supplied code does not do that. It only parses local OpenClaw session transcript files, filters messages by date, extracts user text, attaches short assistant previews, applies shallow rule-based labels such as emotion/task/review, and outputs a daily markdown summary. There is no evidence of multi-layer memory integration, retrospective linkage across time, note-taking beyond digest generation, or behavioral pattern discovery. The primary purpose is materially different: daily log extraction and summarization rather than a three-layer feedback/review analysis system.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The declared description presents a higher-level reflective system that integrates current input, past retrospectives, and everyday context to automatically detect deep behavioral patterns. The supplied code does not implement that functionality. Instead, it is a preprocessing/extraction script: it reads local session logs, selects user messages for a target date, removes some metadata/noise, filters certain automated messages, sorts results by time, and prints a plaintext timeline. While this could support a larger review pipeline, the chunk itself neither links multiple feedback layers nor analyzes behavior patterns. It also accesses local session transcript files, which is a concrete capability/resource use not reflected in the description. Therefore the code's actual behavior is materially narrower and different from the declared purpose.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description presents an analytical memory/feedback skill focused on linking inputs, historical reflections, and contextual notes to identify deep behavior patterns. The supplied code does not implement such analysis or pattern recognition. Instead, it performs a file migration utility: it reads a markdown file, extracts structured fields with regex, emits JSONL, deduplicates by id, and renames the original file as a backup. This is a materially different primary purpose and includes undeclared file conversion and backup behavior. Therefore the description does not accurately represent the code.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The declared description promises a higher-level analytical system that integrates current input, past reviews, and everyday context to infer deep behavior patterns. The supplied code only performs lightweight keyword detection on command-line input, selects a predefined route/mode/dimension mapping, and returns a template reference. This is a materially different primary purpose: routing into review templates rather than performing the described multi-layer analysis or note integration. There are no undeclared sensitive permissions or resource accesses, but the implemented behavior is substantially narrower and different from the declared description.

Missing User Warnings

High
Confidence
96% confidence
Finding
The skill is designed to collect, persist, correlate, and summarize large amounts of user interaction data, but it does not present a clear user-facing privacy warning or consent mechanism at the point of use. This is dangerous because highly sensitive behavioral, emotional, and contextual data may be stored and reused without informed consent.

Vague Triggers

High
Confidence
96% confidence
Finding
These trigger phrases are common everyday words such as '情绪', '目标', '回顾', and '帮助', so normal conversation can unintentionally activate storage, analysis, deletion, or history functions. In a skill that persistently logs and correlates user data, accidental triggering is dangerous because it can cause collection or destructive actions without clear user intent.

Ssd 3

High
Confidence
97% confidence
Finding
The daily digest process summarizes all user interactions, including projects, links, follow-ups, and emotional state, into a persistent structured file. This creates a concentrated, highly sensitive dossier that is more valuable to attackers and more harmful if exposed than the original fragmented interactions.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README explicitly promotes connecting all user inputs, historical reviews, and daily context, but it does not prominently warn users that their conversations and behavioral data may be persistently collected, correlated, and analyzed. This creates a meaningful privacy risk because users may disclose sensitive personal, emotional, or behavioral information without informed consent or clear understanding of retention and reuse.

Ssd 3

Medium
Confidence
96% confidence
Finding
The README markets the skill as connecting all inputs and automatically identifying deep behavioral patterns across time, implying persistent logging and cross-session profiling of user data. In the context of reflective journaling and emotional analysis, this is especially sensitive because the stored material may include mental state, habits, commitments, and personal narratives.

Natural-Language Policy Violations

Medium
Confidence
86% confidence
Finding
The README instructs users to invoke the skill using Chinese trigger phrases such as `复盘`, `周盘`, and `帮助`, and all operational guidance is presented only in Chinese. This effectively forces a specific language/locale without stating that the skill is Chinese-only by design or offering alternatives, which matches the language-policy violation criteria.

Ssd 3

Medium
Confidence
95% confidence
Finding
The Cron-based daily digest workflow directs automated extraction of content from session transcripts into memory files on an ongoing basis. This creates a standing data collection pipeline that can silently accumulate sensitive conversation data over time, especially if users are unaware that transcripts are being mined and re-materialized into separate persistent artifacts.

Ssd 3

Medium
Confidence
94% confidence
Finding
The deep mode description states that the skill will inject same-day conversation summaries and correlate them with user actions, which broadens collection beyond the immediate user prompt into wider interaction history. This increases the chance that unrelated, sensitive, or confidential content is reused in analysis without clear scoping, minimization, or consent.

Lp3

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding
Without declared permissions the skill's intent is opaque and cannot be validated.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
The file is written entirely in Chinese and the message examples and operational guidance assume Chinese output without indicating any user choice or localization fallback. This can cause the skill to respond in an unexpected language, reducing user understanding and increasing the chance of mistaken confirmations or missed warnings in reminder-driven flows.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The reminder system suggests sending only a bare trigger word such as “复盘”, which is a common conversational term and can easily appear in ordinary chat. If the skill auto-expands on that trigger, unrelated user messages or scheduled reminders may unintentionally invoke the full workflow, causing unintended processing and confusing or intrusive behavior.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
This markdown file presents all user-facing trigger labels, prompts, and output templates exclusively in Chinese, with no indication that users may choose another language. Per the policy scope, a skill that effectively requires a specific language without opt-in is a natural-language policy violation.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The file's natural-language interface and generated output are written in Chinese, and the script does not provide any user opt-in or configurable language selection. Under the stated policy, forcing a specific language or locale without choice is a natural-language policy concern unless clearly justified as region-specific.

Ssd 3

Medium
Confidence
91% confidence
Finding
The script is explicitly designed to collect, summarize, and retain users' daily messages in a long-lived digest file, including a complete timeline. Given the skill's context of analyzing deep behavior patterns and daily context, these records may contain highly sensitive personal data, making the retention itself a meaningful privacy and data-exposure risk if the workspace is accessed by other tools, users, or backup systems.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The script persists transcript-derived user messages into a plaintext markdown file without any consent prompt, retention control, or warning about sensitive content. In the context of a memory/behavior-coaching skill that processes reflective personal conversations, this increases the chance of privacy leakage through local compromise, backup sync, or unintended reuse by other tools.

Tainted flow: 'output_path' from os.environ.get (line 298, credential/environment) → open (file write)

Medium
Category
Data Flow
Content
# 写入文件
    os.makedirs(OUTPUT_DIR, exist_ok=True)
    output_path = os.path.join(OUTPUT_DIR, f"{target_date}.md")
    with open(output_path, "w", encoding="utf-8") as f:
        f.write(digest)

    print(f"✅ 摘要已写入: {output_path}", file=sys.stderr)
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.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The script aggregates raw user messages from local session transcripts and prints them to stdout specifically for downstream LLM processing, which creates a privacy and data-handling risk because sensitive personal content may be forwarded, logged, or consumed without explicit user consent or notice. In the context of a 'user-growth-coach' skill that correlates current input, historical reflections, and daily context to infer deep behavior patterns, the extracted data is especially sensitive and can reveal intimate behavioral or psychological information.

Intent-Code Divergence

Medium
Confidence
91% confidence
Finding
The module docstring states that the script migrates user-growth markdown records to JSONL format. However, the implementation also performs a filesystem mutation by renaming the input markdown file to a .bak file, which materially changes the source file state beyond simple conversion.

Tainted flow: 'OUTPUT' from os.environ.get (line 15, credential/environment) → open (file write)

Medium
Category
Data Flow
Content
records = parse_md(INPUT)
    print(f"解析出 {len(records)} 条记录")

    with open(OUTPUT, "w", encoding="utf-8") as f:
        for r in records:
            f.write(json.dumps(r, ensure_ascii=False) + "\n")
Confidence
89% confidence
Finding
The output path is taken directly from an environment variable and then opened for writing without validation. If an attacker or untrusted wrapper controls the runtime environment, they can redirect output to an arbitrary file path, causing unintended file overwrite or clobbering within the permissions of the executing user.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The file docstring says the script migrates markdown records to JSONL format, which implies reading one format and producing another. In addition to writing the JSONL output, the code renames the original input file to a .bak backup, changing the source data on disk in a way not conveyed by the stated behavior.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The skill only recognizes Chinese mode terms (快速/标准/深度) and Chinese trigger words such as 复盘 and 决策. This imposes a specific language requirement in the skill logic without any visible opt-in, alternative locale support, or documented justification in the file.

Static analysis

No suspicious patterns detected.