Back to skill

Security audit

Auto Agent Router

Security checks for vulnerabilities and agentic risk

Overview

The skill is a plausible agent router, but it uses broad automatic routing, forwards chat content to sub-agents, and persists/logs user data with weak controls.

Install only if you want an automatic DingTalk/OpenClaw router that may inspect group messages, delegate them to local sub-agents, and retain message-derived data. Before use, disable automatic keyword routing unless explicitly desired, restrict allowed agents, require clear command triggers or confirmation for sensitive agents like devops/researcher, turn off automatic bot-name learning, and move/redact logs from /tmp with clear retention controls.

Vulnerability Patterns
  • 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
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T02 · Agent Memory Poisoning

Warning
Location
dingtalk-command.py:72
Finding
Unauthenticated Persistent Mutation of Bot-Name Configuration<![CDATA[ ## Vulnerability Details **File Location**: `dingtalk-command.py:72-101` and `dingtalk-command.py:128-130` **Vulnerability Type**: Untrusted persistent state mutation **Risk Level**: Medium ### Vulnerable Code ```python def save_bot_name(new_name: str) -> bool: config_file = Path(__file__).parent / "config.json" if not config_file.exists(): return False try: with open(config_file, 'r', encoding='utf-8') as f: config = json.load(f) bot_names = config.get('bot_names', []) if new_name in bot_names: return False bot_names.append(new_name) config['bot_names'] = bot_names with open(config_file, 'w', encoding='utf-8') as f: json.dump(config, f, indent=2, ensure_ascii=False) print(f"✅ Automatically saved new name: {new_name}") return True except Exception as e: print(f"❌ Failed to save name: {e}") return False ``` The persistence operation is invoked automatically while parsing messages: ```python extracted_name = extract_bot_name(message) if extracted_name and auto_save: save_bot_name(extracted_name) ``` ### Technical Analysis The command parser extracts an arbitrary mention from each incoming message and persists it into the skill's `config.json` file. The operation does not verify that the sender is an administrator, that the mentioned name belongs to the deployed bot, or that configuration learning has been explicitly approved. The value is only constrained by the mention extraction expression: ```python match = re.search(r'@([^\s,,]+)', message) ``` Consequently, an untrusted sender can supply a large number of unique names. Each value is appended to `bot_names`, written to persistent storage, and later incorporated into the regular expression used to remove bot mentions from future messages. Although names are escaped before being incorporated into that expression, preventing direct regular-e ...[truncated 1876 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Disable automatic bot-name persistence by default. 2. Maintain an explicit administrator-controlled allowlist instead of learning names from arbitrary messages. 3. Require authenticated administrative authorization before modifying persistent configuration. 4. Validate names using a restrictive character policy and reject control characters or unexpected punctuation. 5. Enforce strict limits on: - Individual name length. - Total number of names. - Configuration file size. - Update frequency per user or conversation. 6. Store runtime observations separately from trusted routing configuration. 7. Use an atomic write process: - Write validated JSON to a securely created temporary file in the same directory. - Flush and synchronize the file. - Atomically replace the original configuration. 8. Apply file locking or another concurrency-control mechanism during read-modify-write operations. 9. Record the authenticated actor and reason for every approved configuration change. 10. Provide a review and rollback mechanism for learned state. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
auto-route-handler.py:35
Finding
Private Message Data Logged Through a Predictable Shared Temporary File<![CDATA[ ## Vulnerability Details **File Location**: `auto-route-handler.py:35,45-56,107`; `message-handler.py:26-36,51`; `logger.py:8,20-35` **Vulnerability Type**: Unsafe temporary-file logging and plaintext sensitive-data exposure **Risk Level**: Medium ### Vulnerable Code In `auto-route-handler.py`: ```python self.log_file = Path("/tmp/auto-route-handler.log") ``` ```python def _log(self, message: str): from datetime import datetime timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") log_entry = f"[{timestamp}] {message}\n" with open(self.log_file, 'a', encoding='utf-8') as f: f.write(log_entry) print(log_entry.strip()) ``` ```python self._log( f"Received message: {message[:50]}... " f"(from: {from_user}, type: {chat_type})" ) ``` In `message-handler.py`: ```python LOG_FILE = Path("/tmp/auto-route-handler.log") def log(message: str): timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") log_entry = f"[{timestamp}] {message}\n" with open(LOG_FILE, 'a', encoding='utf-8') as f: f.write(log_entry) print(log_entry.strip()) ``` ```python log( f"Received DingTalk message: {message[:50]}... " f"(from: {from_user}, conv: {conversation_id})" ) ``` In `logger.py`: ```python LOG_FILE = Path("/tmp/auto-route-handler.log") def log(message: str, level: str = "INFO"): timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") log_entry = f"[{timestamp}] [{level}] {message}\n" try: with open(LOG_FILE, 'a', encoding='utf-8') as f: f.write(log_entry) except Exception as e: pass color_map = { "INFO": Colors.BLUE, "DEBUG": Colors.CYAN, "ERROR": Colors.RED, "SUCCESS": Colors.GREEN, "WARNING": Colors.YELLOW } color = color_map.get(level, Colors.NC) print(f"{color}[{timestamp}] [{level}] {message}{Colors.NC}") ``` ### Technical Analysis Three modules append logs to the same predictable ...[truncated 3422 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the shared `/tmp` path with an application-owned logging directory. 2. Create that directory with mode `0700` and verify its ownership before use. 3. Create the log file with mode `0600`. 4. Use secure low-level file creation with appropriate platform protections, including: - `O_APPEND` - `O_CREAT` - `O_NOFOLLOW` where supported - `O_CLOEXEC` 5. Verify with `lstat` or `fstat` that the destination is a regular file owned by the expected service account. 6. Refuse to write if the path is a symbolic link, hard-linked unexpectedly, or has unsafe permissions. 7. Avoid logging message bodies by default. When operationally necessary, redact or hash sensitive fields and minimize the retained fragment. 8. Treat sender names and conversation IDs as sensitive data and avoid storing them unless required. 9. Escape newline characters, carriage returns, ANSI escape sequences, and other control characters before writing or printing untrusted fields. 10. Use a standard logging framework with: - Rotation and maximum-size limits. - Retention and deletion policies. - Restricted file permissions. - Structured records. - Centralized redaction. 11. Avoid silently discarding logging exceptions; report failures through a safe fallback channel without exposing sensitive content. 12. Run the handler under a dedicated, least-privileged service account to restrict the scope of any filesystem abuse. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (35)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The finding describes significantly expanded behavior: keyword-based classification, complexity-based auto-routing, local configuration access, and reading agent configuration files such as SOUL.md, despite the skill presenting itself as simple explicit-command routing. That broadens the trust boundary from deterministic command dispatch to content inspection and local file access, which can leak data, misroute sensitive prompts, or cause unauthorized child-agent delegation.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The finding describes significantly expanded behavior: keyword-based classification, complexity-based auto-routing, local configuration access, and reading agent configuration files such as SOUL.md, despite the skill presenting itself as simple explicit-command routing. That broadens the trust boundary from deterministic command dispatch to content inspection and local file access, which can leak data, misroute sensitive prompts, or cause unauthorized child-agent delegation.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The finding describes significantly expanded behavior: keyword-based classification, complexity-based auto-routing, local configuration access, and reading agent configuration files such as SOUL.md, despite the skill presenting itself as simple explicit-command routing. That broadens the trust boundary from deterministic command dispatch to content inspection and local file access, which can leak data, misroute sensitive prompts, or cause unauthorized child-agent delegation.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding
The finding describes significantly expanded behavior: keyword-based classification, complexity-based auto-routing, local configuration access, and reading agent configuration files such as SOUL.md, despite the skill presenting itself as simple explicit-command routing. That broadens the trust boundary from deterministic command dispatch to content inspection and local file access, which can leak data, misroute sensitive prompts, or cause unauthorized child-agent delegation.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The finding describes significantly expanded behavior: keyword-based classification, complexity-based auto-routing, local configuration access, and reading agent configuration files such as SOUL.md, despite the skill presenting itself as simple explicit-command routing. That broadens the trust boundary from deterministic command dispatch to content inspection and local file access, which can leak data, misroute sensitive prompts, or cause unauthorized child-agent delegation.

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Content
---
name: auto-agent-router
description: "根据消息命令自动路由到子 Agent。**Agent 应该:收到消息时首先检查是否包含 /coder、/writer 等命令,如果是则调用 sessions_spawn 启动对应子 Agent。**"
metadata:
  openclaw:
    emoji: "🤖"
    requires:
      bins: ["python3"]
---

# Auto Agent Router - 自动子 Agent 路由

根据消息中的命令自动路由到合适的子 Agent,实现并发处理和专业化分工。

---

## 🎯 When to Use

### Agent 行为准则

**收到每条消息时,首先检查是否包含命令**:

✅ **USE this skill when:**

- 消息开头是 `/
Confidence
80% confidence
Finding
The manifest contains behavioral directives aimed at controlling the host agent ('收到消息时首先检查...调用 sessions_spawn'), which is consistent with tool/metadata poisoning concerns because the skill is trying to alter high-priority agent behavior through descriptive metadata. In this context, the risk is amplified because the skill seeks automatic interception and delegation of incoming messages, potentially causing unreviewed spawning of sub-agents or priority inversion between system policy and skill text.

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Content
��映射
COMMAND_MAP = {
    '/coder': 'coder',
    '/code': 'coder',
    '/writer': 'writer',
    '/write': 'writer',
    '/analyze': 'analyst',
    '/analysis': 'analyst',
    '/research': 'researcher',
    '/review': 'reviewer',
    '/review-code': 'reviewer',
    '/devops': 'devops',
    '/ops': 'devops',
    '/auto': 'auto'  # 自动判断
}

# 命令帮助
COMMAND_HELP = {
    'coder': '🧑‍💻 代码专家 - 写代码、调试、重构',
    'writer': '✍️ 写作专家 - 文档、周报、文章',
    'analyst': '📊 数据专家 - 数据分析、图表、统计',
    'researcher': '🔍 调研专家 - 搜索、调研、竞品分析',
    'reviewer': '👀 审查专家 - 代码审查、优化建议',
    'devops': '🤖 运维专家 - 部署、服务器、日志',
    'auto': '🤖 自动判断 - 根据内容智能路由'
}

def get_bot_names() -> list:
    """获取机器人名字列表"""
    config_file = Path(__file__).parent / "config.json"
    if config_file.exists
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
The skill metadata requires explicit slash-command routing first, but the implementation performs implicit keyword and length-based routing. This can cause user messages to be sent to a different agent/model than intended, creating confused-deputy behavior, privacy leakage to unintended sub-agents, and bypass of user control over delegation.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill manifest advertises executable behaviors and shell-based testing commands but does not declare any explicit tool scope such as allowed-tools or permissions. That creates an authorization gap where a reviewer or runtime may not clearly understand the skill's file and shell capabilities, increasing the chance of over-privileged execution or unsafe adoption.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The manifest description is written as an instruction to the agent in Chinese and does not indicate that language selection depends on user preference. Under the policy, forcing a specific language or locale without opt-in is a natural-language policy violation.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The manifest says the agent should first check whether the message contains commands like /coder or /writer and then call sessions_spawn for the corresponding child agent. In this file, routing decisions are driven by config flags, chat type, and route_message/analyze_message logic, with no command-prefix check visible before spawning an agent.

Description-Behavior Mismatch

Medium
Confidence
92% confidence
Finding
Automatically routing all group messages greatly expands the trigger surface beyond explicit user opt-in. In an agent system, this can cause unintended delegation of arbitrary group content to sub-agents, increasing the chance of prompt-injection propagation, unnecessary privilege use, and accidental handling of sensitive content by secondary processes.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The code logs message content and sender identifiers to /tmp, which can expose potentially sensitive user data to other local users, support personnel, or later processes on the same host. Because /tmp is a shared, commonly accessible location on many systems, this creates a concrete privacy and data-leakage risk.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The handler forwards the full original message and sender information to a spawned sub-agent without explicit user awareness or minimization. In agent architectures, cross-process or cross-agent forwarding broadens access to potentially sensitive content and can magnify prompt-injection and data-handling risks, especially if sub-agents use different tools, models, or permissions.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The module docstring describes the skill exclusively in Chinese and targets DingTalk message handling, but it does not indicate that the language/locale constraint is optional or limited to a justified region-specific deployment. Under the policy, forcing a specific language without user opt-in is a natural-language policy concern.

Vague Triggers

Medium
Confidence
95% confidence
Finding
Bot trigger names such as "assistant", "bot", and generic Chinese equivalents are common conversational words and may match benign references rather than direct invocation. That can cause accidental activation of the router and downstream agent spawning, making the system susceptible to prompt-trigger confusion and unintended workflow execution.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The skill metadata says routing should first check explicit slash commands like /coder or /writer, but the configuration instead enables automatic keyword-based dispatch across many categories. This creates a behavior/manifest mismatch that can silently invoke sub-agents without clear user intent, increasing the chance of unintended delegation and misuse of more capable downstream agents.

Vague Triggers

Medium
Confidence
91% confidence
Finding
Many keywords are highly generic, such as terms for writing, analysis, optimization, configuration, or implementation, and they lack scope constraints or disambiguation. In an auto-routing skill, this can misclassify ordinary discussion and dispatch to the wrong sub-agent, potentially escalating to sensitive agents like reviewer or devops based on ambiguous text alone.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The configured routing expands beyond the described /coder and /writer examples to automatically dispatch to analyst, researcher, reviewer, and devops agents. In an agent system, broadening dispatch scope can expose users to unintended actions or access patterns, especially for sensitive roles like devops, without an explicit command indicating consent.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The module docstring and usage examples are entirely in Chinese and present the skill as operating only through Chinese command patterns such as '@小牛马 /coder 写个脚本'. There is no indication that users may choose another language or that the Chinese-only behavior is a justified regional constraint, which matches the locale-policy violation criteria.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The router silently persists any newly mentioned @name into local configuration, which expands trusted bot identifiers based on untrusted chat input. In an agent-routing skill, this creates stateful behavior beyond simple command parsing and can let users poison configuration, cause future messages to be misparsed, or create unintended trust relationships.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The logger writes arbitrary messages to disk without user notice, and other functions pass user messages, tasks, and outputs into this sink. In a routing skill, users would not reasonably expect their full content to be persisted, which creates a confidentiality and privacy risk if prompts contain credentials, personal data, or internal instructions.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The logger records routed message content, tasks, and agent results to persistent storage even though the stated skill purpose is only command routing. In an agent router, these fields can contain sensitive user prompts, secrets, or generated outputs, so storing them to /tmp creates unnecessary data retention and expands the attack surface beyond the advertised function.

Ssd 3

Medium
Confidence
92% confidence
Finding
The code logs user/task content in plain text and provides a function to retrieve recent log lines, creating a straightforward natural-language leakage channel. In the context of an auto-router that processes arbitrary user requests, this is more dangerous because sensitive prompts and downstream agent results may be captured and later exposed to anyone with access to the file or retrieval function.

Context-Inappropriate Capability

Medium
Confidence
87% confidence
Finding
The file exposes helper functions to read recent logs and delete logs, which are capabilities unrelated to basic message routing. When combined with sensitive content being logged, log retrieval becomes a data exposure path and deletion can hinder auditing or be abused to remove traces of misuse.

Static analysis

No suspicious patterns detected.