Back to skill

Security audit

Bw Openclaw Boost

Security checks for vulnerabilities and agentic risk

Overview

The skill is not clearly malicious, but its memory, compaction, and permission features can affect future agent behavior without enough trust-boundary controls.

Review this skill carefully before installing. Its cost/status tools appear ordinary, but the memory, compaction, and permission components can persist information and influence future agent context. Install only if you are comfortable auditing the local memory files and permission rules, and avoid using the compaction or memory-injection features until they add clear trust boundaries, sanitization, and user approval.

Vulnerability Patterns
  • 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
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (3)

T01 · Skill Instruction Hijacking

Error
Location
tools/compaction_manager.py:239
Finding
Untrusted conversation content is promoted to system-level authority during compaction<![CDATA[ ## Vulnerability Details **File Location**: `tools/compaction_manager.py:239-250, 274-291` **Vulnerability Type**: Trust-boundary violation and prompt-injection privilege escalation **Risk Level**: Critical ### Vulnerable Code ```python # 保留最近 N 条消息 recent = messages[-PRESERVE["recent_messages"]:] older = messages[:-PRESERVE["recent_messages"]] # 生成旧消息的摘要 older_summary = self._summarize_messages(older) # 构建压缩后的消息列表 compacted = [ { "type": "system", "role": "system", "content": f"[早期对话已压缩为摘要,共 {len(older)} 条消息,约 {self.estimate_tokens(''.join(m.get('content','') for m in older))} tokens]\n\n摘要:{older_summary}", "_compact": "auto" } ] + recent ``` The summary is generated by copying excerpts from every message without considering its original trust level: ```python def _summarize_messages(self, messages: List[Dict], max_length: int = 2000) -> str: """生成消息摘要""" if not messages: return "无" # 提取关键信息 topics = [] for msg in messages: content = msg.get("content", "")[:200] # 每条取前200字符 if content: # 提取前几个字作为主题 first_line = content.split('\n')[0][:50] if first_line: topics.append(first_line) summary = f"讨论了 {len(messages)} 条消息,主题包括:{';'.join(topics[:5])}" if len(summary) > max_length: summary = summary[:max_length] + "..." return summary ``` ### Technical Analysis The compaction mechanism does not distinguish between trusted system instructions and untrusted user or tool-result content when generating its summary. `_summarize_messages()` copies the first line of each old message, including user-controlled messages, into `older_summary`. `auto_compact()` then assigns that summary both `"type": "system"` and `"role": "system"`. This crosses a fundamental instruction trust boundary: text originally supplied at user authority can reappear in a system-authority message. The summary algorithm is extra ...[truncated 1760 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Never convert user or tool content into a system-role message. Retain the original trust level or represent summaries in a dedicated non-authoritative data structure. 2. Keep the actual system prompt separate and immutable during compaction. 3. If a summary must be inserted as a message, use a non-system role and explicitly state that the content is untrusted historical data, not instructions. 4. Generate structured summaries containing facts, decisions, and unresolved tasks rather than copying raw first-line excerpts. 5. Exclude or neutralize imperative phrases, role declarations, tool directives, and instruction-like content originating from users or tool outputs. 6. Track provenance for each summary element, including the original role and message identifier. 7. Add tests proving that user content such as “ignore previous instructions” can never appear in a system-role message after compaction. 8. Require downstream consumers to treat compacted summaries as data and prevent them from overriding active system or developer instructions. ]]>

T02 · Agent Memory Poisoning

Error
Location
tools/dream_consolidation.py:112
Finding
Unsanitized log content can poison persistent memory and be reinjected into future Agent contexts<![CDATA[ ## Vulnerability Details **File Location**: `tools/dream_consolidation.py:112-133, 151-201`; `tools/memory_relevance.py:225-268` **Vulnerability Type**: Persistent memory poisoning and indirect prompt injection **Risk Level**: High ### Vulnerable Code The consolidation process extracts headings, list items, and short code blocks directly from Markdown logs: ```python def extract_key_info(self, content: str) -> List[str]: """ 从内容中提取关键信息 """ key_points = [] # 提取标题(## 开头的) titles = re.findall(r'^#{1,3}\s+(.+)$', content, re.MULTILINE) key_points.extend(titles) # 提取列表项 list_items = re.findall(r'^[-*]\s+(.+)$', content, re.MULTILINE) key_points.extend(list_items) # 提取代码块(可能是重要配置) code_blocks = re.findall(r'```[\s\S]*?```', content) for block in code_blocks[:2]: # 最多2个 if len(block) < 200: key_points.append(block[:100]) return key_points[:20] # 最多20条 ``` Those values are written without instruction filtering into long-term memory: ```python key_points = self.extract_key_info(log["content"]) new_entry = f""" --- ## 来自 {log['date']} 日志的更新 来源: `{log['file']}` ### 关键信息 """ for point in key_points[:10]: if len(point) > 200: point = point[:200] + "..." new_entry += f"- {point}\n" new_entry += f"\n_整理时间: {update_time}_" # 追加或创建 if existing: # 找到最后一个 --- 分隔符,在那之前插入 last_sep = existing.rfind('\n---\n') if last_sep > 0: updated = existing[:last_sep] + new_entry + existing[last_sep:] else: updated = existing + new_entry else: updated = f"""# {rule.target_file.replace('-', ' ').title()} {new_entry} """ target_file.write_text(updated, encoding='utf-8') ``` The retrieval layer later injects the full memory content into context without a trust boundary: ```python def get_memory_content(m: MemoryHeader) -> str: """读取记忆文件的完整内容""" path = MEMORY_ROOT / m.path try: content = path.read_text(encoding='utf-8') ...[truncated 3281 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Treat all log content as untrusted, regardless of its local filesystem location. 2. Do not copy raw headings, list entries, or code blocks into long-term memory. 3. Convert candidate content into a structured schema containing factual fields, provenance, confidence, creation time, and originating role. 4. Detect and reject instruction-like content, including role changes, requests to ignore safeguards, tool commands, and directives addressed to the Agent. 5. Require explicit user approval before promoting log-derived content into persistent user, project, feedback, or reference memory. 6. Preserve the source file and original trust classification with every stored fact. 7. Wrap retrieved memory in a clear non-authoritative boundary stating that it is untrusted reference data and must not override active instructions. 8. Remove the behavior that returns unrelated memories merely to satisfy a minimum count; only inject memories above a meaningful relevance threshold. 9. Limit the size and number of injected memories and consider returning structured facts instead of full files. 10. Add regression tests using malicious Markdown headings and list items to verify that directives cannot survive consolidation and influence later sessions. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
tools/permission_manager.py:61
Finding
Substring-based command allowlisting permits permission-check bypass through composed commands<![CDATA[ ## Vulnerability Details **File Location**: `tools/permission_manager.py:61-77, 162-176, 200-231`; `tools/check_permission.sh:15-20` **Vulnerability Type**: Authorization bypass caused by unsafe command classification **Risk Level**: High ### Vulnerable Code The default allowlist includes generic command names and arbitrary interpreter entry points: ```python ToolPermission( tool="exec", permissions=["execute", "network"], description="执行 shell 命令", safe_commands=[ "ls", "pwd", "echo", "cat", "head", "tail", "grep", "rg", "find", "wc", "cut", "tr", "sort", "uniq", "jq", "git status", "git log", "git diff", "git show", "python3 -c", "python3 -m", "curl -s", "curl -X GET", "wget -q", "openclaw status", "openclaw cron list", "date", "whoami", "hostname", ], dangerous_patterns=[ r"rm\s+-rf\s+/", r"rm\s+-rf\s+\*", r"dd\s+if=.*of=/dev/", r":\(\)\{.*:\|:&\};:", r"curl.*\|.*sh", r"wget.*\|.*sh", r"shutdown", r"reboot", r"mkfs", r"dd.*bs=", ] ) ``` Safety is decided using a substring search rather than command parsing: ```python def check_command_safety(command: str, tool_perm: ToolPermission) -> RuleEffect: """ 检查命令安全性 返回: "allow" | "ask" | "deny" """ # 检查危险模式 for pattern in tool_perm.dangerous_patterns: if re.search(pattern, command, re.IGNORECASE): return "deny" # 检查安全命令白名单 for safe in tool_perm.safe_commands: if safe == "*": return "allow" if safe in command: return "allow" # 默认需要询问 return "ask" ``` The result is used as the final authorization result: ```python # 1. 先检查危险模式 if tool_perm and command: safety = check_command_safety(command, tool_perm) if safety == "deny": return "deny" # 2. 检查用户自定义规则(按优先级) rules = perms.get("rules", []) for rule in rules: if check_rule_m ...[truncated 3166 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace substring checks with exact matching of a parsed executable and validated argument list. 2. Avoid passing auto-approved commands through a shell. Execute fixed argument vectors with `shell=False`. 3. Reject semicolons, newlines, pipes, redirects, boolean operators, command substitution, and other shell metacharacters in automatically approved requests. 4. Remove `python3 -c`, `python3 -m`, and equivalent interpreter entry points from the automatic allowlist because they provide arbitrary code execution. 5. Do not automatically approve `curl` or `wget` solely based on options. Apply explicit URL, protocol, destination, redirect, and response-size policies, or require confirmation. 6. Anchor every allowlist rule to the complete command structure rather than allowing trailing unvalidated content. 7. Use a default-deny policy for unknown executables, subcommands, and arguments. 8. Treat blocklists only as defense in depth, not as the primary authorization mechanism. 9. Return a machine-readable result with an exact status value. The shell wrapper should compare the complete result rather than searching for the substring `ALLOW`. 10. Add bypass tests covering command chaining, newlines, substitutions, redirects, nested shells, interpreters, and safe command names embedded in arguments. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (45)

Direct Prompt Extraction

High
Category
System Prompt Leakage
Content
"""
        for rule in CONSOLIDATION_RULES:
            if re.search(rule.pattern, content, re.IGNORECASE):
                return rule
        return None
    
    def consolidate_log(self, log: Dict[str, Any]) -> bool:
Confidence
85% confidence
Finding
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Content
"""
        for rule in CONSOLIDATION_RULES:
            if re.search(rule.pattern, content, re.IGNORECASE):
                return rule
        return None
    
    def consolidate_log(self, log: Dict[str, Any]) -> bool:
Confidence
85% confidence
Finding
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Content
print("监控 Token 使用情况(Ctrl+C 退出)...")
            try:
                while True:
                    os.system('clear')
                    print(monitor.get_report())
                    time.sleep(10)
            except KeyboardInterrupt:
Confidence
85% confidence
Finding
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The comments and all user-facing help text are presented only in Chinese, including the usage and command descriptions. This creates a language/locale policy concern because the skill does not offer an opt-in choice or explain that it is intentionally restricted to a Chinese-speaking context.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The script includes Chinese-only natural-language comments and a Chinese denial message, and there is no indication that the user can choose a language or that the skill is intentionally limited to a Chinese-speaking context. The policy explicitly disallows forcing a specific language or locale without opt-in or clear justification.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The module docstring and all user-facing descriptive text are written only in Chinese, with no indication that users may select another language or that the tool is region-specific. Under the policy, forcing a specific language without user opt-in is a natural-language locale violation.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
This code file contains natural-language documentation and interface text entirely in Chinese, beginning with the module docstring and continuing through user-visible CLI messages. Under the policy rules, forcing a specific language without user opt-in is a locale-policy violation unless the regional constraint is explicitly justified, which is not present here.

Intent-Code Divergence

Medium
Confidence
92% confidence
Finding
The module docstring states that the skill receives tasks, routes them to agents, and collects results for return to the user. In practice, the code analyzes keywords, writes tasks to a JSON log, and marks them as pending with a placeholder result, without any result collection or aggregation logic.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The docstring describes '分发任务到目标 Agent' while the function body merely updates local task status/result and explicitly does not transmit anything. This is an intent-level contradiction because the documented operation suggests real dispatch behavior that the code does not perform.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The file’s natural-language docstring and user-facing report strings are written exclusively in Chinese, indicating a fixed language choice for the skill's interface. Under the policy, forcing a specific language without opt-in or documented regional justification is a locale-policy violation.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
With no manifest available, the skill's intended scope is unknown, so invoking an external command-line tool is an unjustified capability relative to documented purpose. The module documentation describes a cost tracking system, but this implementation depends on spawning `openclaw status`, which expands capability beyond simple local aggregation/reporting.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def poll_sessions(self) -> List[SessionSnapshot]:
        try:
            result = subprocess.run(["openclaw", "status"], capture_output=True, text=True, timeout=30)
            output = result.stdout + result.stderr
        except Exception as e:
            print(f"Failed to get openclaw status: {e}")
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The module documentation states '清理已处理的短期记忆' at L010, implying processed logs will be removed. In code, LOGS_DIR is annotated as read-only at L029 and the consolidation loop comments '日志保留,不删除' at L230, with no deletion logic anywhere, so the documented behavior contradicts the actual implementation.

Ssd 3

Medium
Confidence
96% confidence
Finding
The consolidation rules explicitly classify identity-related content such as '用户|角色|身份|我是' into persistent user memory. In this skill context, that is more dangerous because the tool scans conversational/log data and can silently retain personal or profile information long-term, increasing privacy and disclosure risk.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The tool automatically copies extracted content from recent logs into long-term memory files without any consent, review gate, or sensitivity filtering. Because logs may contain secrets, personal data, or sensitive operational details, this increases data retention and exposure risk by persisting information beyond its original context.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The function assembles full memory file contents and returns them for direct injection into agent context without any consent gate, redaction step, or user-visible disclosure that stored data may be surfaced. In an agent setting, this can expose sensitive prior notes, personal data, or secrets from the memory store to prompts, tools, or downstream model outputs when a broad or attacker-influenced query triggers retrieval.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
This code embeds user-facing documentation and command-line messages entirely in Chinese, including usage help and status output, with no indication that the skill is region-specific or that users can opt into another language. That creates a natural-language policy concern under the language/locale rule because the skill effectively enforces one language by default.

Session Persistence

Medium
Category
Rogue Agent
Content
权限类型:
- read      — 读文件/数据
- write     — 写/创建文件
- execute   — 执行命令
- network   — 网络访问
- elevated  — 提升权限
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Session Persistence

Medium
Category
Rogue Agent
Content
权限类型:
- read      — 读文件/数据
- write     — 写/创建文件
- execute   — 执行命令
- network   — 网络访问
- elevated  — 提升权限
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The module docstring and all user-facing command descriptions are presented in Chinese only, indicating a fixed language choice. There is no indication that users can opt into another language or locale, which conflicts with the policy against forcing a specific language without user choice.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def cmd_cost(self, args: str) -> str:
        """成本统计"""
        try:
            result = subprocess.run(
                ["python3", str(TOOLS_DIR / "cost_tracker.py")],
                capture_output=True, text=True, timeout=10
            )
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def cmd_status(self, args: str) -> str:
        """系统状态"""
        try:
            result = subprocess.run(
                ["openclaw", "status"],
                capture_output=True, text=True, timeout=10
            )
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def cmd_memory(self, args: str) -> str:
        """记忆状态"""
        try:
            result = subprocess.run(
                ["python3", str(TOOLS_DIR / "memory_relevance.py"), "scan"],
                capture_output=True, text=True, timeout=10
            )
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def cmd_tasks(self, args: str) -> str:
        """定时任务"""
        try:
            result = subprocess.run(
                ["openclaw", "cron", "list", "--json"],
                capture_output=True, text=True, timeout=10
            )
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The /clear command performs irreversible deletion of cache directories immediately, with no confirmation, dry-run mode, or user warning. In an agent-command context, a mistyped or unintended invocation can cause loss of useful state and disrupt execution, even though the deletion scope is limited to predefined local directories.

Static analysis

No suspicious patterns detected.