Back to skill

Security audit

Feishu Cron Delivery

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly coherent for Feishu cron delivery, but its smoke-test helper can generate unsafe shell commands from crafted input, so it needs review before use.

Review the helper script before installing or using it. Only run generated commands with trusted values, avoid copying output produced from untrusted input into a shell, and prefer a fixed or safely quoted command for Feishu cron setup. Also replace the Chinese example text, recipient placeholders, account IDs, and schedule details with values appropriate to your workspace.

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 (1)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/create_smoke_test.py:7
Finding

Shell Command Injection in Generated OpenClaw Command

Content
View full analysis

Vulnerability Details

File Location: scripts/create_smoke_test.py, lines 7–11 and 17–26
Vulnerability Type: Shell command injection through unsafe command construction
Risk Level: High

Vulnerable Code

python
parser.add_argument('--open-id', required=True, help='Feishu open_id without the user: prefix')
parser.add_argument('--account', default='default', help='OpenClaw channel account id')
parser.add_argument('--minutes', type=int, default=2, help='How many minutes from now to schedule the smoke test')
parser.add_argument('--tz', default='Asia/Shanghai', help='Timezone for the cron add command')
parser.add_argument('--name', default='Feishu delivery smoke test', help='Cron job name')
args = parser.parse_args()

run_at = datetime.now() + timedelta(minutes=args.minutes)
iso_local = run_at.strftime('%Y-%m-%dT%H:%M:%S')
message = '在本轮只输出这一句话:主动消息链路测试:如果你看到这条,说明 Feishu cron 外发成功。'
cmd = f'''openclaw cron add \\
  --name "{args.name}" \\
  --at "{iso_local}" \\
  --tz "{args.tz}" \\
  --session isolated \\
  --message "{message}" \\
  --announce \\
  --channel feishu \\
  --account {args.account} \\
  --to "user:{args.open_id}" \\
  --delete-after-run'''
print(cmd)

Technical Analysis

The script places user-controlled values directly into shell command text without shell-safe escaping or restrictive validation:

  • args.account is inserted without any quoting.
  • args.name, args.tz, and args.open_id are enclosed in double quotes, but embedded double quotes, command substitutions, backticks, and other shell-sensitive content are not escaped.
  • Double quotes do not prevent shell command substitution such as $(...).
  • Shell metacharacters in the unquoted account value can terminate or alter the intended command.

The script prints rather than directly executes the command. Nevertheless, its stated purpose is to generate a command for subsequent execution, and the project documentation instructs users to use this generator for sm ...[truncated 1771 chars]

Remediation
View remediation

Remediation Suggestions

  1. Prefer direct process execution with an argument list rather than generating shell syntax:
python
import subprocess

command = [
    "openclaw", "cron", "add",
    "--name", args.name,
    "--at", iso_local,
    "--tz", args.tz,
    "--session", "isolated",
    "--message", message,
    "--announce",
    "--channel", "feishu",
    "--account", args.account,
    "--to", f"user:{args.open_id}",
    "--delete-after-run",
]

subprocess.run(command, check=True)

This avoids shell parsing and treats every dynamic value as a single argument.

  1. If producing textual shell commands is an explicit requirement, apply shlex.quote() separately to every dynamic value:
python
import shlex

safe_name = shlex.quote(args.name)
safe_at = shlex.quote(iso_local)
safe_tz = shlex.quote(args.tz)
safe_message = shlex.quote(message)
safe_account = shlex.quote(args.account)
safe_to = shlex.quote(f"user:{args.open_id}")
  1. Apply allowlist validation in addition to safe argument handling:

    • Restrict account IDs and Feishu open IDs to their documented character sets and length limits.
    • Validate the timezone against available IANA timezone identifiers.
    • Enforce a reasonable maximum length for job names.
    • Reject control characters, especially newlines and null bytes.
  2. Avoid recommending eval, bash -c, or equivalent shell evaluation for generated output.

  3. Add automated tests containing spaces, quotes, semicolons, backticks, command substitutions, newlines, and leading hyphens to verify that inputs remain inert arguments.

  4. If the generator remains print-only, clearly warn that its output must not be executed when arguments originate from untrusted sources.

Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (2)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The example commands instruct the agent to produce output in Chinese using hardcoded Chinese prompts such as '只输出这一句话' and '请输出一份发给老姚的中文进度报告'. This imposes a specific language/locale behavior in the skill documentation without any opt-in, alternative language option, or justification that the skill is region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The string literal instructs the generated smoke test to output only a Chinese sentence, which enforces a specific language without any user opt-in or configurable locale. This is a natural-language policy issue because the file is code and the language constraint is neither optional nor justified in the script.

Content

No source excerpt is available for this finding.