Back to skill

Security audit

Chat History

Security checks for vulnerabilities and agentic risk

Overview

This chat-history skill has a clear purpose, but it archives sensitive conversations through persistent scheduled jobs and ships conflicting, under-scoped code that needs review before use.

Install only if you intentionally want local copies of your OpenClaw conversations to be retained and searchable. Prefer explicit commands or manual archiving, review and remove any cron/OpenClaw cron tasks you do not want, and avoid the legacy main.py path unless it is fixed or removed.

Vulnerability Patterns
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • 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 (4)

T06 · System Persistence

Error
Location
main_v3.py:78
Finding

Persistent Scheduled Execution Through System and OpenClaw Cron

Content
View full analysis
> {LOG_FILE} 2>&1 """) os.chmod(script_path, 0o755) cron_line = "55 3 * * * {0}".format(script_path) try: existing = os.popen("crontab -l 2>/dev/null").read() except: existing = "" lines = [line for line in existing.split("\n") if "chat-history" not in line and line.strip()] base_cron = "\n".join(lines) + "\n" new_cron = base_cron + "\n" + cron_line + "\n" import tempfile with tempfile.NamedTemporaryFile(mode='w', delete=False) as f: f.write(new_cron) temp_file = f.name os.system(f"crontab {temp_file}") os.unlink(temp_file) ``` ```python # main_v3.py:78-101 def setup_cron(): """设置 OpenClaw 定时任务""" try: skill_dir = os.path.dirname(os.path.abspath(__file__)) main_py_path = os.path.join(skill_dir, "main_v3.py") if check_cron_setup(): return True, "定时任务已存在" result = subprocess.run( [ "openclaw", "cron", "add", "--name", "chat-history-archive", "--cron", "59 23 * * *", "--system-event", f"Chat History: 请运行 python3 {main_py_path} --archive", "--session", "main" ], capture_output=True, text=True, timeout=15 ) if result.returncode == 0: log_message("成功设置 OpenClaw cron 任务") return True, "suc ...[truncated 1987 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
archive_from_jsonl.py:70
Finding

Path Traversal and Arbitrary File Overwrite Through Unvalidated Channel Metadata

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
main.py:63
Finding

Shell Command Injection in Generated Persistent Archive Script

Content
View full analysis
> {LOG_FILE} 2>&1 """) os.chmod(script_path, 0o755) ``` ```python # main.py:159-194 skill_dir = os.path.dirname(os.path.abspath(__file__)) script_path = os.path.join(skill_dir, "archive-daily.sh") main_py_path = os.path.join(skill_dir, "main.py") cron_line = f"{minute} {hour} * * * {script_path}" new_cron = base_cron + "\n" + cron_line + "\n" with tempfile.NamedTemporaryFile(mode='w', delete=False) as f: f.write(new_cron) temp_file = f.name os.system(f"crontab {temp_file}") os.unlink(temp_file) with open(script_path, "w") as f: f.write(f"""#!/bin/bash cd {skill_dir} python3 {main_py_path} --archive >> {LOG_FILE} 2>&1 """) os.chmod(script_path, 0o755) ``` ### Technical Analysis The generated shell script interpolates `skill_dir`, `main_py_path`, and `LOG_FILE` directly into shell command text without quoting. `LOG_FILE` is derived from `OPENCLAW_WORKSPACE` or `OPENCLAW_DIR`, which are environment-controlled values. The package installation path can also contain whitespace or shell metacharacters. When cron executes the generated file, Bash parses those values as shell syntax rather than as opaque paths. Shell operators, substitutions, redirections, or whitespace embedded in a path can therefore alter the intended command. The crontab line also embeds `script_path` without quoting, creating an additional parsing problem when the Skill path contains spaces or shel ...[truncated 969 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
main_v3.py:111
Finding

Overbroad Scheduled-Task Deletion Based on Substring Matching

Content
View full analysis
/dev/null").read() except: existing = "" lines = existing.split("\n") new_lines = [line for line in lines if "chat-history" not in line and line.strip()] new_cron = "\n".join(new_lines) + "\n" with tempfile.NamedTemporaryFile(mode='w', delete=False) as f: f.write(new_cron) temp_file = f.name os.system(f"crontab {temp_file}") os.unlink(temp_file) ``` ```python # main_v3.py:111-132 def remove_cron(): """移除 OpenClaw 定时任务""" try: result = subprocess.run( ["openclaw", "cron", "list"], capture_output=True, text=True, timeout=10 ) for line in result.stdout.split("\n"): if "chat-history" in line: parts = line.split() if parts: task_id = parts[0] subprocess.run( ["openclaw", "cron", "remove", task_id], capture_output=True, text=True, timeout=10 ) log_message(f"已移除 cron 任务: {task_id}") ``` ### Technical Analysis Both removal implementations identify owned tasks by searching for the substring `chat-history`. They do not persist the identifier returned when the task is created, verify the complete task name, or validate the registered command. Consequently, any unrelated system or OpenClaw task whose displayed line contains the same substring is treated as belonging to this Skill. The v3 implementation additionally assumes that the first whitespace-delimited field is ...[truncated 994 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (101)

Vague Triggers

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The trigger list includes very broad, everyday phrases such as 'archive', 'backup', 'I forgot', and common Chinese equivalents, which can cause the skill to activate unintentionally during normal conversation. In a skill that archives and searches conversation history, accidental activation can expose or process sensitive prior chats without sufficiently explicit user intent.

Content

No source excerpt is available for this finding.

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · SECURITY-NOTICE-v3.md (reported line 21)May include surrounding context.

md
��(2026-03-10)

### ✅ 移除所有系统命令

**问题**:v2.0 使用 `os.popen()` 和 `os.system()` 执行系统命令(crontab),被安全扫描标记为可疑。

**修复**:**完全移除所有系统命令**,改用 OpenClaw 原生 cron API。

**对比**:

| 功能 | v2.0(不安全) | v3.0(安全) |
|------|---------------|-------------|
| 定时任务 | `os.system("crontab ...")` | `openclaw cron add` |
| 检查任务 | `os.popen("crontab -l")` | `openclaw cron list` |
| 删除任务 | `os.system("crontab ...")` | `openclaw cron remove` |
| Windows 兼容 | ❌ 不支持 | ✅ 完全支持 |
| macOS 兼容 | ⚠️ 需要权限 | ✅ 无需权限 |

---

### ✅ 完全跨平台兼容

**问题**:v2.0 使用 Linux/macOS 特有的 crontab,Windows 不支持。

**修复**:使用 OpenClaw CLI,支持所有平台:
- ✅ macOS
- ✅ Windows
- ✅ Linux

**无需任何系统权限!**

---

### ✅ 归档时间调整

**问题**:v2.0 默认归档时

Vague Triggers

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill defines broad natural-language triggers that map ordinary user utterances to archive/search actions, creating a high risk of unintended activation. In a chat-history skill, accidental triggering is especially dangerous because it can cause sensitive historical conversations to be searched, surfaced, or stored without a clear, explicit user command at the time of access.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The keyword lists include everyday phrases such as forgetting, asking for help, or mentioning history, which are likely to appear in normal conversation unrelated to archival operations. Because the skill handles retention and retrieval of prior chats, these generic triggers materially increase the chance of unauthorized or surprising disclosure of archived content.

Content

No source excerpt is available for this finding.

Context Leakage

High
Category
Data Exfiltration
Confidence
85% confidence
Finding

Code or instructions that leak agent conversation context to external services, potentially exposing sensitive user interactions.

Content

Scanner excerpt · SKILL.md (reported line 464)May include surrounding context.

text
chat history
conversation history
chat log
conversation log
search history
find chat

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Confidence
85% confidence
Finding

os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.

Content

Scanner excerpt · main.py (reported line 58)May include surrounding context.

python
def check_cron_setup():
    """检查定时任务是否已设置"""
    try:
        result = os.popen("crontab -l 2>/dev/null | grep chat-history").read()
        return "chat-history" in result
    except:
        return False

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Confidence
85% confidence
Finding

os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.

Content

Scanner excerpt · main.py (reported line 83)May include surrounding context.

python
# 读取现有crontab
    try:
        existing = os.popen("crontab -l 2>/dev/null").read()
    except:
        existing = ""

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Confidence
85% confidence
Finding

os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.

Content

Scanner excerpt · main.py (reported line 110)May include surrounding context.

python
# 读取现有crontab
    try:
        existing = os.popen("crontab -l 2>/dev/null").read()
    except:
        existing = ""

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Confidence
85% confidence
Finding

os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.

Content

Scanner excerpt · main.py (reported line 165)May include surrounding context.

python
# 读取现有crontab
    try:
        existing = os.popen("crontab -l 2>/dev/null").read()
    except:
        existing = ""

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Confidence
85% confidence
Finding

os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.

Content

Scanner excerpt · main.py (reported line 100)May include surrounding context.

python
f.write(new_cron)
        temp_file = f.name

    os.system(f"crontab {temp_file}")
    os.unlink(temp_file)

    return True, "success"

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Confidence
85% confidence
Finding

os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.

Content

Scanner excerpt · main.py (reported line 125)May include surrounding context.

python
f.write(new_cron)
        temp_file = f.name

    os.system(f"crontab {temp_file}")
    os.unlink(temp_file)

    return True, "success"

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Confidence
85% confidence
Finding

os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.

Content

Scanner excerpt · main.py (reported line 184)May include surrounding context.

python
f.write(new_cron)
        temp_file = f.name

    os.system(f"crontab {temp_file}")
    os.unlink(temp_file)

    return True, "success"

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This markdown file uses Chinese throughout for core usage and migration information, but does not state that the skill is Chinese-only or offer an alternative language. Under the policy rule, forcing a specific language without user opt-in is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The file describes automatic daily archiving, incremental archiving, multi-channel support, and cross-device querying of conversation records without any notice about consent, retention, access controls, or privacy implications. In context, this is more dangerous because the feature concerns potentially sensitive communications across channels and devices, creating real risk of unauthorized retention or unexpected exposure of private data.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The changelog advertises 'natural language triggering' with 30+ keywords but does not document the actual activation phrases, scope boundaries, or safeguards. This can cause unintended invocation, surprise data handling behavior, and broaden the chance that ordinary user text triggers archival or query actions without clear user intent.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
80% confidence
Finding

The document is primarily written in Chinese and presents natural-language triggers and usage examples centered on Chinese interaction, while not stating that users may choose their preferred language. Although some English triggers are listed, the skill behavior and documentation appear to assume a Chinese-language operating mode without explicit opt-in or language selection.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

At the top of the document, archive-related scripts are labeled as still pending migration. Elsewhere, the document describes working daily archiving, searchable archives, and command support as if those components already exist, creating an active contradiction between documentation sections.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The document presents key capabilities such as automatic archiving and conversation search as already completed, including concrete commands and examples. However, later it explicitly says the archive and search scripts still need to be migrated and integrated, which directly contradicts the earlier implementation claims and could mislead reviewers about the skill's actual behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The installation and usage description encourages archiving past chats but does not clearly warn that archived conversations may contain sensitive personal, credential, business, or security-related content. Without a prominent warning and consent flow, users may enable broad retention of sensitive data without understanding the privacy implications.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The workflow states that any trigger keyword match leads to action selection and script invocation, which is too permissive for a skill handling archived conversations and evaluations. Keyword-only activation increases the risk of unintended searches, enumeration of stored history, or enabling archival behavior when the user did not clearly request it.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

The document instructs users to install a cron job for daily archiving, establishing persistent automated collection of conversation data. Persistence is more sensitive here because the skill handles chat history, so unattended background operation increases the risk of continuous retention of sensitive content beyond user expectations.

Content

Scanner excerpt · DELIVERY.md (reported line 361)May include surrounding context.

修改方法:

bash
# 查看定时任务
crontab -l

# 编辑定时任务
crontab -e

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

The explicit cron editing instructions reinforce creation of persistent background behavior for archiving. In the context of conversation history storage, this can silently expand the quantity and sensitivity of retained data over time if users do not fully understand or remember the scheduled task.

Content

Scanner excerpt · DELIVERY.md (reported line 364)May include surrounding context.

md
crontab -l

# 编辑定时任务
crontab -e

# 找到这一行:
59 23 * * * /path/to/archive-daily.sh

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% confidence
Finding

Troubleshooting guidance that normalizes checking and maintaining cron persistence supports continued unattended operation of the archival system. While not malware-like persistence, it is still security-relevant because it encourages durable collection of potentially sensitive chat logs.

Content

Scanner excerpt · DELIVERY.md (reported line 448)May include surrounding context.

检查方法:

bash
# 查看定时任务
crontab -l

# 查看日志
tail -f /var/log/chat-archive.log

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
80% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

Scanner excerpt · DELIVERY.md (reported line 614)May include surrounding context.

md
**文档**:
- 使用指南:`skills/chat_history/README.md`
- Skill定义:`skills/chat_history/SKILL.md`

---

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This markdown file contains user-facing operational instructions exclusively in Chinese, including publishing steps and safety notes. Under the policy rule for language or locale constraints, forcing a single language without opt-in or justification can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.