T06 · System Persistence
- Location
SKILL.md:32- Finding
Recurring Cron Jobs Create Cross-Session Persistence
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This memory skill is partly purpose-aligned, but it needs review because it installs persistent scheduled execution and can run unrelated mutable workspace scripts while writing conversation-derived content into long-term memory.
Review carefully before installing. Only use this if you want recurring local automation that writes conversation-derived summaries into OpenClaw memory. Avoid enabling the cron jobs until the unrelated script handlers are removed or constrained, metadata declares command execution, and there are clear controls for opt-in, review, deletion, and disabling scheduled runs.
SKILL.md:32Recurring Cron Jobs Create Cross-Session Persistence
scripts/daily-evolution.py:66Untrusted Daily Memory Content Is Promoted into Persistent Agent Memory
scripts/heartbeat-check.py:104Event Handlers Execute Unverified Scripts from a Mutable Workspace
_meta.json:9Skill Metadata Omits Subprocess and Scheduled-Execution Capabilities
A second behavior mismatch exists around automation and orchestration: heartbeat polling, idle monitoring, persistent state tracking, and external script execution go beyond a simple summarization skill. Hidden automation increases the risk of unexpected data collection, persistence, and background execution in a user environment.
A second behavior mismatch exists around automation and orchestration: heartbeat polling, idle monitoring, persistent state tracking, and external script execution go beyond a simple summarization skill. Hidden automation increases the risk of unexpected data collection, persistence, and background execution in a user environment.
The skill lacks a prominent warning that it will automatically write conversation-derived summaries to persistent files and may trigger on idle conditions. Users may unknowingly expose sensitive discussions to long-term local storage without informed consent.
The skill uses subprocess-based execution of multiple unrelated Node.js scripts, creating a broad and unnecessary execution surface not justified by the skill description. In this context, that is particularly dangerous because users or reviewers may enable the skill expecting note organization, while it can actually trigger arbitrary maintenance scripts from the workspace.
The skill describes behavior that requires shell execution and file writes, but it declares no explicit tool scope or permissions. This creates a capability-transparency gap: operators or automated systems may invoke it without understanding that it can persist data and run scripts on a schedule.
The 'when to use' conditions are broad and ambiguous, including automatic and idle-triggered behavior, which can cause the skill to be invoked in situations where the user did not clearly request persistent storage. Ambiguous triggers are especially risky for a skill that writes conversation-derived data to disk.
The skill is explicitly designed to persist discussion summaries into a long-term workspace MEMORY.md file and to trigger saves based on inactivity. Even if intended, this creates a real privacy and retention risk because sensitive session content can be stored beyond the active conversation lifecycle.
Run daily-evolution.py to:
- Read memory files from `~/.openclaw/workspace/memory/`
- Extract discussion topics from markdown files
- Write summaries to `~/.openclaw/workspace/MEMORY.md`
### 2. Heartbeat Check Script
The skill is configured to run on broad automatic triggers ('cron' and 'heartbeat') while also holding both file read and file write permissions. In the context of an auto-memory updater, this means the skill could modify memory files without an explicit user action or clear scoping, increasing the risk of unintended, excessive, or repeated writes.
The module docstring states that the script runs daily to automatically summarize that day's discussion content and update memory. In practice, the only active path in generate_report() reads the current memory file, extracts headings/bullets, and writes summaries; the functions documented as fetching today's messages and session history are unused. This is an active contradiction between the file-level intent statement and the implemented behavior.
This file contains natural-language instructions and status output exclusively in Chinese, beginning with the module docstring that describes the script’s behavior. Under the language/locale policy, forcing a specific language without user opt-in is a policy concern unless the locale limitation is explicitly justified.
The manifest describes automatically summarizing daily discussions and updating memory files. However, although the script defines functions to fetch today's chat and session history via CLI subprocesses, generate_report() never calls them; instead it reads the existing daily memory file, summarizes that file's headings, and writes the result back to memory and reports. This means the actual behavior is memory-file reformatting/rollup rather than discussion ingestion and summarization as described.
The skill includes code to access chat and session data through external CLI commands even though that capability is broader than its stated purpose of organizing memory files. In a memory-management context, hidden or unnecessary access to conversation history increases privacy risk and expands the blast radius if the code is later wired into execution or repurposed.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
"""获取飞书今日消息"""
try:
# 使用 OpenClaw CLI 获取今日会话消息
result = subprocess.run(
["openclaw", "chat", "history", "--today", "--limit", "100", "--format", "json"],
capture_output=True,
text=True,
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
"""获取当前session的历史消息"""
try:
# 尝试从 sessions 获取历史
result = subprocess.run(
["openclaw", "sessions", "list", "--active", "--message-limit", "50"],
capture_output=True,
text=True,
This Python file contains its primary docstring and operational user-facing output in Chinese, and there is no indication that the skill is intended only for Chinese-speaking users or that language selection is configurable. That creates a natural-language locale policy issue because the skill effectively imposes a specific language without user opt-in.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
"""触发每日进化脚本"""
script = WORKSPACE / "scripts" / "daily-evolution.py"
if script.exists():
result = subprocess.run(
["python3", str(script)],
capture_output=True,
text=True,
The progress output reports emergency checks, memory organization, log cleanup, and daily maintenance as successful even though those functions are not actually called at that point. Misleading status output undermines operator trust and can conceal skipped checks or failures, which is dangerous in automation because it creates false assurance about system state.
The heartbeat script includes operational behaviors beyond automatic memory summarization, such as skill learning, model health checks, growth reports, and mission review routing. Scope expansion is dangerous in agent skills because it hides privileged capabilities behind an innocuous description, increasing the chance of unauthorized or unexpected code execution.
The skill launches an external Node.js maintenance script unrelated to the stated memory-summarization purpose, expanding the executable surface of the skill. In an agent-skill context, hidden or loosely related subprocess execution is dangerous because a modified script in the workspace can run arbitrary code under the agent's privileges.
"""技能学习"""
script = WORKSPACE / "scripts" / "skill-learning.js"
if script.exists():
result = subprocess.run(["node", str(script)], capture_output=True, text=True)
print(result.stdout)
return True
This function executes a separate Node.js script for model health checks, which is outside the advertised scope of automatic memory organization. In a workspace-based agent environment, any subprocess hook to auxiliary scripts can become an arbitrary-code-execution vector if those files are replaced or tampered with.
"""模型健康检查"""
script = WORKSPACE / "scripts" / "model-health-check.js"
if script.exists():
result = subprocess.run(["node", str(script)], capture_output=True, text=True)
print(result.stdout)
return True
This subprocess runs another Node.js script for daily growth reporting, again exceeding the narrow memory-maintenance purpose of the skill. Such extra execution paths increase the blast radius of the skill and can be abused to run attacker-supplied code if the referenced file is altered.
"""每日成长报告"""
script = WORKSPACE / "scripts" / "daily-growth-report.js"
if script.exists():
result = subprocess.run(["node", str(script)], capture_output=True, text=True)
print(result.stdout)
return True
The description is written entirely in Chinese and presents the skill as a Chinese-language experience without any indication that users can choose another language or that the locale is intentionally region-specific. This can conflict with language or locale policy expectations when no opt-in or justification is provided.
No suspicious patterns detected.