Back to skill

Security audit

Feishu Agent Provision

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed Feishu/OpenClaw agent admin tool, but its scripts contain unsafe file-write and command-generation behavior that could affect a user's local OpenClaw setup.

Install only if you intentionally want this skill to administer local OpenClaw agents, Feishu group bindings, scheduled jobs, and persistent memory. Review or patch the path validation and cron command generation before using it with untrusted input, and confirm that deletion cleanup works in your environment before relying on it for removing agents.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/create_agent.py:88
Finding

Unvalidated workspace paths allow path traversal and arbitrary file overwrite

Content
View full analysis

Vulnerability Details

File Location: scripts/create_agent.py:88-95, 166-176, 196-203; scripts/clone_agent.py:175-183, 489-502, 619
Vulnerability Type: Path traversal and arbitrary file overwrite
Risk Level: High

Vulnerable Code

scripts/create_agent.py:88-95

python
if workspace_dir:
    ws_base = Path(workspace_dir)
else:
    ws_base = DEFAULT_WORKSPACE_BASE / agent_id / "workspace"

ws_base.mkdir(parents=True, exist_ok=True)
(ws_base / "memory").mkdir(exist_ok=True)

scripts/create_agent.py:166-176

python
for filename, content in [
    ("SOUL.md", soul_content),
    ("USER.md", user_content),
    ("AGENTS.md", agents_content),
    ("HEARTBEAT.md", "# 定期检查任务\n# (按需添加心跳任务)\n"),
]:
    (ws_base / filename).write_text(content, encoding="utf-8")

return ws_base

scripts/create_agent.py:196-203

python
parser = argparse.ArgumentParser(description="创建飞书群专属 Agent")
parser.add_argument("--agent-id", required=True, help="Agent ID(英文,字母+数字+短横线)")
parser.add_argument("--agent-name", required=True, help="Agent 中文显示名")
parser.add_argument("--group-id", required=True, help="飞书群 ID(oc_xxx)")
parser.add_argument("--duty", required=True, help="Agent 职责描述")
parser.add_argument("--data-file", help="数据文件绝对路径(可选)")
parser.add_argument("--daily-time", default="17:00", help="每日汇报时间(默认 17:00)")
parser.add_argument("--weekly-time", default="周五 17:00", help="每周汇报时间")
parser.add_argument("--workspace-dir", help="自定义 workspace 路径(可选)")

scripts/clone_agent.py:175-183

python
def create_new_workspace(new_id: str, files: dict[str, str]) -> Path:
    new_ws = AGENTS_BASE / new_id / "workspace"
    new_ws.mkdir(parents=True, exist_ok=True)
    (new_ws / "memory").mkdir(exist_ok=True)

    for fname in ["SOUL.md", "USER.md", "AGENTS.md", "HEARTBEAT.md"]:
        if fname in files:
            (new_ws / fname).write_text(files[fname], encoding="utf-8
...[truncated 3059 chars]
Remediation
View remediation

Remediation Suggestions

  1. Enforce the documented agent-ID syntax in both creation and cloning:
    python
    import re
    
    AGENT_ID_PATTERN = re.compile(r"^[a-z0-9]+(?:-[a-z0-9]+)*$")
    
    def validate_agent_id(value: str) -> str:
        if not AGENT_ID_PATTERN.fullmatch(value):
            raise ValueError("Invalid agent ID")
        return value
    
  2. Resolve every generated workspace path and verify containment with Path.is_relative_to():
    python
    base = DEFAULT_WORKSPACE_BASE.resolve()
    destination = (base / agent_id / "workspace").resolve()
    
    if not destination.is_relative_to(base):
        raise ValueError("Workspace path escapes the agent directory")
    
  3. Remove --workspace-dir unless arbitrary workspace roots are essential. If it must remain, restrict it to an explicit allowlist of trusted roots and require additional confirmation.
  4. Reject absolute agent IDs, path separators, . components, and .. components before any filesystem operation.
  5. Detect existing destination files and fail safely. If overwriting is required, display the exact affected paths and require a separate explicit confirmation.
  6. Add tests for absolute paths, ../ traversal, nested traversal, symlink-based escapes, existing files, and valid agent IDs.
  7. Validate the resolved destination again immediately before each write to reduce time-of-check/time-of-use and symlink risks.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/create_agent.py:42
Finding

Unescaped values in generated cron commands enable shell command injection

Content
View full analysis

Vulnerability Details

File Location: scripts/create_agent.py:42-81, 256-266
Vulnerability Type: Shell command injection through generated executable commands
Risk Level: High

Vulnerable Code

scripts/create_agent.py:42-81

python
CRON_HINT = """
Cron 创建命令(由 agent 执行,{agent_id} 的 cron 由 {agent_id} 自己执行):

【日报 Cron — 周一至周五 {daily_time}】
openclaw cron add \\
  --name "{agent_id}-daily-report" \\
  --cron "0 {daily_hour} * * 1-5" \\
  --tz "Asia/Shanghai" \\
  --agent "{agent_id}" \\
  --session "session:{agent_id}" \\
  --message "📋 {agent_name}定时报告时间到!

【记忆恢复】先读 ~/.openclaw/agents/{agent_id}/workspace/memory/backup.md,了解当前状态。

【执行任务】<具体任务内容>

【结束备份】完成后把本次结果追加写入 backup.md。" \\
  --announce \\
  --channel "feishu" \\
  --to "{group_id}" \\
  --timeout-seconds 120

【周报 Cron — 周五 {weekly_time}】(周五与日报合并,不单独发)
openclaw cron add \\
  --name "{agent_id}-weekly-report" \\
  --cron "0 {weekly_hour} * * 5" \\
  --tz "Asia/Shanghai" \\
  --agent "{agent_id}" \\
  --session "session:{agent_id}" \\
  --message "📋 {agent_name}周报时间到!

【记忆恢复】先读 backup.md。

【执行任务】本周总结 + 下周计划(周五合并到日报,不单独发)。

【结束备份】完成后追加写入 backup.md。" \\
  --announce \\
  --channel "feishu" \\
  --to "{group_id}" \\
  --timeout-seconds 120
"""

scripts/create_agent.py:256-266

python
print(CRON_HINT.format(
    agent_id=args.agent_id,
    agent_name=args.agent_name,
    group_id=args.group_id,
    daily_time=args.daily_time,
    daily_hour=f"{daily_hour}",
    daily_min=f"{daily_min:02d}",
    weekly_time=args.weekly_time,
    weekly_hour=f"{weekly_hour}",
    weekly_min=f"{weekly_min:02d}",
))

Technical Analysis

User-controlled values are inserted directly into a multiline shell command. Double quotes do not neutralize shell command substitution such as $(...) or backticks. Embedded double quotes can also terminate the intended argument and introduce shell ...[truncated 1988 chars]

Remediation
View remediation

Remediation Suggestions

  1. Do not generate shell commands containing raw user input. Prefer invoking openclaw directly through subprocess.run() with an argument list and shell=False:
    python
    subprocess.run(
        [
            "openclaw", "cron", "add",
            "--name", cron_name,
            "--cron", schedule,
            "--tz", "Asia/Shanghai",
            "--agent", agent_id,
            "--session", f"session:{agent_id}",
            "--message", message,
            "--announce",
            "--channel", "feishu",
            "--to", group_id,
            "--timeout-seconds", "120",
        ],
        check=True,
        shell=False,
    )
    
  2. If displaying a shell command remains necessary, quote every dynamic argument with shlex.quote() and clearly label the output as a preview.
  3. Strictly validate structured values:
    • Agent ID: lowercase letters, digits, and hyphens only.
    • Group ID: expected Feishu group-ID format.
    • Times: valid hour and minute ranges.
  4. Treat names, duties, and message content as data passed through an argument array, not as shell source code.
  5. Add tests using quotes, semicolons, newlines, backticks, $(), pipes, redirection operators, and Unicode control characters.
  6. Require an explicit preview and confirmation before creating each scheduled task.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/delete_agent.py:203
Finding

Missing regular-expression import causes the deletion safety workflow to fail

Content
View full analysis

Vulnerability Details

File Location: scripts/delete_agent.py:20-26, 203-209, 268
Vulnerability Type: Fail-stop denial of service caused by an undefined dependency
Risk Level: Low

Vulnerable Code

scripts/delete_agent.py:20-26

python
import argparse
import json
import os
import shutil
import subprocess
import sys
from pathlib import Path

scripts/delete_agent.py:203-209

python
def validate_agent_id(agent_id: str) -> bool:
    """校验 agent_id 格式,防止路径穿越。只允许小写字母、数字、短横线。"""
    if not re.match(r'^[a-z0-9-]+$', agent_id):
        return False
    if '..' in agent_id or '/' in agent_id or '\\' in agent_id:
        return False
    return True

scripts/delete_agent.py:268

python
if not validate_agent_id(agent_id):

Technical Analysis

validate_agent_id() calls re.match(), but the re module is not imported. Python resolves re when the function executes and raises a NameError.

Every normal deletion invocation reaches this validation before checking registrations, active sessions, confirmation, cron jobs, bindings, or workspaces. Consequently, the script terminates before performing either standard deletion or residual cleanup.

This is primarily an availability and lifecycle-management defect. It also undermines the intended security controls because stale scheduled jobs, bindings, and persistent workspace data cannot be removed using the documented tool.

Attack Path

  1. A user invokes delete_agent.py with any agent ID.
  2. The script calls validate_agent_id(agent_id).
  3. Python evaluates re.match(...).
  4. Because re is undefined, Python raises NameError.
  5. The process exits before displaying confirmation or performing cleanup.
  6. Existing cron tasks, bindings, registrations, sessions, and workspace files remain in place.

This issue does not provide direct code execution. An attacker who benefits from an already- ...[truncated 673 chars]

Remediation
View remediation

Remediation Suggestions

  1. Add the missing import:
    python
    import re
    
  2. Add an automated smoke test that invokes the script with a valid agent ID and verifies that it reaches the existence check without an exception.
  3. Add unit tests for valid IDs, invalid characters, absolute paths, path traversal, empty values, and mixed-case IDs.
  4. Run a static analyzer or linter such as Ruff, Pyflakes, or Pylint in continuous integration to detect undefined names.
  5. Add integration tests for registered-agent deletion, residual-only cleanup, active-session handling, trash failures, and cancellation paths.
  6. Ensure unexpected exceptions produce a safe diagnostic and leave configuration unchanged.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (29)

Vague Triggers

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The delete trigger list includes the broad phrase "删除 ", making a destructive admin action match casual language. In this skill context, deletion affects cron jobs, bindings, registration, and workspaces, so broad matching creates a real risk of accidental destructive operations even though later confirmation exists.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/clone_agent.py <SOURCE_AGENT_ID>

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The create trigger example "创建项目 agent" is not specific enough to Feishu-agent provisioning and can plausibly match normal planning or brainstorming requests. Since this skill creates files, modifies gateway configuration, and provisions scheduled tasks, ambiguous creation triggers increase the chance of unintended privileged setup actions.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

Several clone triggers omit a clear agent-specific qualifier or skill prefix, such as "克隆 " and similar shorthand forms. Because cloning creates new workspaces, bindings, and possibly cron jobs, loose matching can cause unintended provisioning from everyday discussion about copying or duplicating something else.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

Status-query examples such as "space 的状态" are broad enough to overlap with ordinary conversation about a project, workspace, or general status. Since the skill can inspect registered agents, bindings, cron tasks, backups, and sessions, ambiguous triggers can expose internal system information when the user did not clearly intend to invoke this administrative skill.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The cron payload text says the agent should not auto-post to the group and should wait for DM confirmation, but the configured delivery uses announce mode directly to the Feishu group. This mismatch can cause the system to deliver messages automatically despite the natural-language instruction, leading to unintended disclosures or spam in a group context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The daily report schedule hard-codes the timezone to "Asia/Shanghai", which imposes a locale-specific behavior on all users. The document does not present this as optional, ask the user to choose a timezone, or justify that the skill is limited to a China-specific deployment context.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The scheduled workflow explicitly instructs the agent to restore prior state from backup files and append new execution results on every run, creating persistent memory across sessions. In this skill context, those backups can accumulate sensitive operational details, user-provided data, project status, and possibly message content without any minimization, retention limit, or access-control guidance.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Like the daily template, the weekly schedule fixes the timezone to "Asia/Shanghai" for all users. This is a natural-language policy issue because it enforces a locale-specific default without offering the user a language/locale choice or clearly documenting a justified region restriction.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The weekly report path repeats the same pattern of reading historical memory and writing results back, reinforcing an ongoing retention mechanism. Repeated scheduled persistence increases the chance that sensitive information accumulates indefinitely and is later exposed through status queries, cloning mistakes, workspace access, or accidental group reporting.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The later deletion trigger list reintroduces the bare phrase "删除 ", which directly conflicts with the earlier safer rule requiring an "agent" qualifier or skill prefix. Because this skill performs destructive actions against agent registrations, bindings, cron jobs, and workspaces, an overly broad trigger materially increases the chance of accidental activation from ordinary conversation.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The embedded message explicitly instructs the agent to first send a Feishu DM for confirmation and '不要自动直接发群' (do not automatically send directly to the group). However, the surrounding cron template configures delivery.mode: "announce", channel: "feishu", and a group to target, which sets up direct group delivery behavior. This is an intent-level contradiction between the documented instruction and the actual template configuration.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The message template explicitly requires a Chinese-named report and uses fixed Chinese-language instructions, which imposes a language choice on the skill output. Under the policy, language constraints should either be optional for the user or clearly justified as region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This weekly message template is written entirely in Chinese and specifies a Chinese report format, again enforcing a specific language by default. No opt-in, alternative locale, or justification is provided in the file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This code file contains natural-language strings that force a specific language/locale for the entire interaction, including the module docstring and command-line prompts. Under the policy, locale constraints should either be optional for the user or clearly documented as a justified region-specific requirement, which is not present here.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/clone_agent.py (reported line 56)May include surrounding context.

python
def get_source_crons(source_id: str) -> list[dict]:
    try:
        result = subprocess.run(["openclaw", "cron", "list"], capture_output=True, text=True, timeout=10)
        if result.returncode != 0:
            return []
    except Exception:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/clone_agent.py (reported line 90)May include surrounding context.

python
# ── SOUL.md / USER.md auto-generation ──────────────────────

def generate_soul_minimal(new_id: str, new_name: str) -> str:
    date_str = subprocess.run(["date", "+%Y-%m-%d"], capture_output=True, text=True).stdout.strip()
    return f"""# {new_name}

## 基本信息

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/clone_agent.py (reported line 128)May include surrounding context.

python
# ── SOUL.md / USER.md auto-generation ──────────────────────

def generate_soul_minimal(new_id: str, new_name: str) -> str:
    date_str = subprocess.run(["date", "+%Y-%m-%d"], capture_output=True, text=True).stdout.strip()
    return f"""# {new_name}

## 基本信息

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/clone_agent.py (reported line 185)May include surrounding context.

python
# ── SOUL.md / USER.md auto-generation ──────────────────────

def generate_soul_minimal(new_id: str, new_name: str) -> str:
    date_str = subprocess.run(["date", "+%Y-%m-%d"], capture_output=True, text=True).stdout.strip()
    return f"""# {new_name}

## 基本信息

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/clone_agent.py (reported line 266)May include surrounding context.

python
"--message", f"📋 {new_id} 定时任务时间到!请执行对应任务。"
        ]
        try:
            r = subprocess.run(cmd, capture_output=True, text=True, timeout=15)
            results.append(f"✅ {new_name}  ({schedule_str})" if r.returncode == 0 else f"⚠️ {new_name}: {r.stderr}")
        except Exception as e:
            results.append(f"⚠️ {new_name}: {e}")

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/clone_agent.py (reported line 276)May include surrounding context.

python
def restart_gateway() -> tuple[bool, str]:
    try:
        r = subprocess.run(["openclaw", "gateway", "restart"], capture_output=True, text=True, timeout=30)
        return (True, "重启成功") if r.returncode == 0 else (False, f"重启失败: {r.stderr}")
    except Exception as e:
        return False, f"异常: {e}"

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/clone_agent.py (reported line 284)May include surrounding context.

python
def send_test_message(group_id: str, new_id: str) -> tuple[bool, str]:
    try:
        r = subprocess.run(
            ["openclaw", "message", "send",
             "--channel", "feishu", "--to", group_id,
             "--message", f"✅ Agent「{new_id}」已上线!请确认收到此消息。"],

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The generated SOUL.md instructs the agent to use a fixed communication style and explicitly avoid greetings like '您好!', which imposes a specific language/register preference. The file does not indicate that this style is optional or based on user choice, so it can violate language/locale policy requirements for user opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The file’s natural-language instructions and runtime prompts require users to enter specific Chinese phrases such as 「确认删除」 and 「强制删除」 to proceed. This imposes a specific language/locale on all users without any opt-in or alternative, which matches the policy-violation category for language or locale constraints.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/delete_agent.py (reported line 64)May include surrounding context.

python
"""检查是否有活跃的 Agent session"""
    # 通过 openclaw sessions list 获取
    try:
        result = subprocess.run(
            ["openclaw", "sessions", "list", "--json"],
            capture_output=True, text=True, timeout=10
        )

Static analysis

No suspicious patterns detected.