Back to skill

Security audit

feishuAgentAdd

Security checks for vulnerabilities and agentic risk

Overview

The skill appears intended to configure Feishu agents for OpenClaw, but it handles secrets and user-supplied agent instructions in ways that deserve review before installation.

Review this skill before installing. Prefer the interactive prompt path for the App Secret, avoid pasting secrets into command lines or shared chats, run --dry-run first, inspect the generated SOUL.md and BOOTSTRAP.md before using the new agent, and disable agent-to-agent access unless you specifically need it.

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

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:104
Finding
Shell Command Injection Through Interpolated Skill Arguments<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 104-115 **Vulnerability Type**: Shell command injection **Risk Level**: High ### Vulnerable Code ```bash python3 scripts/add_feishu_agent.py \ --agent-id <agent-id> \ --agent-name "<agent-name>" \ --purpose "<purpose>" \ --app-id <app-id> \ --app-secret <app-secret> \ --json-output \ --yes ``` The same unsafe command-generation pattern is repeated in `SKILL.md`, lines 132-140: ```bash python3 scripts/add_feishu_agent.py \ --agent-id trader \ --agent-name "交易小助手" \ --purpose "股票和 ETF 分析" \ --app-id cli_xxx \ --app-secret secret_xxx \ --yes ``` ### Technical Analysis The skill instructs the agent to interpolate conversationally supplied values into a shell command. Double quotes around `agent_name` and `purpose` do not make this safe: an input containing a double quote can terminate the quoted argument and introduce shell syntax. The `agent_id`, `app_id`, and `app_secret` placeholders are not quoted at all. Although `add_feishu_agent.py` uses an argument parser and safely constructs its own subsequent `subprocess.run()` argument list, that protection applies only after the shell has parsed the command. If the agent executes the documented command through a shell tool, command substitution, redirection, separators, or quote termination can execute before Python starts. The Python validation of `agent_id` also occurs too late to prevent shell injection because shell interpretation precedes `validate_request()`. ### Attack Path 1. An attacker asks the agent to create a Feishu agent. 2. The attacker supplies a crafted field, such as an agent name resembling: ```text example"; touch /tmp/skill-command-injection; # ``` 3. The skill follows its documented execution pattern and constructs: ```bash python3 scripts/add_feishu_agent.py \ --agent-name "example"; touch /tmp/skill-command-injection; #" \ ... ``` 4. The shell terminates the ...[truncated 797 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Do not ask the agent to construct a shell command by interpolating user input. - Invoke the script through a structured process API with a discrete argument array and with shell execution disabled. For example: ```python subprocess.run( [ sys.executable, "scripts/add_feishu_agent.py", "--agent-id", agent_id, "--agent-name", agent_name, "--purpose", purpose, "--app-id", app_id, "--app-secret-stdin", "--json-output", "--yes", ], input=app_secret, text=True, check=True, shell=False, ) ``` - If the skill runtime only exposes a shell interface, generate a temporary argument file with restrictive permissions or apply a proven platform-specific shell-escaping function to every argument. Manual quote replacement is not sufficient. - Validate all fields before invoking any shell or process tool. Apply strict formats to IDs and reasonable length and character restrictions to display fields. - Add adversarial tests covering double quotes, single quotes, semicolons, newlines, command substitution, backticks, redirection, and shell metacharacters. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:104
Finding
Feishu App Secret Is Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 104-115; `scripts/add_feishu_agent.py`, lines 417 and 493-494 **Vulnerability Type**: Sensitive information exposure through process arguments **Risk Level**: Medium ### Vulnerable Code The skill explicitly directs callers to provide the secret as a command-line argument: ```bash python3 scripts/add_feishu_agent.py \ --agent-id <agent-id> \ --agent-name "<agent-name>" \ --purpose "<purpose>" \ --app-id <app-id> \ --app-secret <app-secret> \ --json-output \ --yes ``` The script registers and reads that argument directly: ```python parser.add_argument("--app-secret", help="Feishu App Secret") ``` ```python app_id = args.app_id or prompt_text("Feishu App ID(飞书应用 ID)") app_secret = args.app_secret or prompt_text("Feishu App Secret(飞书应用密钥)", secret=True) ``` The returned JSON masks the secret, but masking output does not remove it from the original process command line: ```python "request": asdict(request) | {"app_secret": "***hidden***"}, ``` ### Technical Analysis Secrets supplied through command-line arguments can be retained in shell history, terminal logging, automation transcripts, OpenClaw tool-call records, debugging output, and process-monitoring systems. Depending on operating-system policy, other local processes or users may also be able to inspect the process argument vector while the configurator is running. The interactive path correctly uses `getpass`, but the skill's recommended non-interactive path always uses `--app-secret`, making the less secure mechanism the normal automated workflow. ### Attack Path 1. A user provides a Feishu App Secret to the skill. 2. The skill executes the documented command with the secret in its argument vector. 3. The plaintext value is recorded in one or more of: - shell history; - agent tool-call history or telemetry; - process inspection output; - terminal/session logs; - CI or orchestration logs. 4. A loca ...[truncated 753 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove `--app-secret <value>` from the recommended workflow. - Support reading the secret from standard input, for example `--app-secret-stdin`, and ensure prompts and logs never echo it. - Alternatively, support a credential-store reference or a narrowly scoped environment variable. Standard input or an operating-system credential store is preferable because environment variables may also be exposed through diagnostics. - If a secret file must be supported, require restrictive permissions, reject symbolic links where practical, and delete temporary files securely after use. - Redact secrets from agent tool-call telemetry, error reports, process diagnostics, and audit logs. - Preserve the current masking in JSON output, but treat it as defense in depth rather than the primary protection. - Document credential rotation procedures because secrets previously passed through the command line may already exist in histories or logs. ]]>

T02 · Agent Memory Poisoning

Error
Location
scripts/add_feishu_agent.py:382
Finding
Untrusted Purpose Text Is Persisted as Future Agent Instructions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/add_feishu_agent.py`, lines 382-400 **Vulnerability Type**: Persistent prompt injection and agent memory poisoning **Risk Level**: High ### Vulnerable Code The script places the conversationally supplied `purpose` value into template variables without validation or an instruction/data boundary: ```python template_dir = self.script_dir.parent / "templates" variables = { "agent_id": self.request.agent_id, "agent_name": self.request.agent_name, "purpose": self.request.purpose or "待补充", "workspace_path": str(self.workspace_path), "created_at": datetime.now().isoformat(timespec="seconds"), } for src_name, dest_name in [ ("SOUL.template.md", "SOUL.md"), ("BOOTSTRAP.template.md", "BOOTSTRAP.md"), ]: src_path = template_dir / src_name dest_path = self.workspace_path / dest_name if dest_path.exists(): self.summary["warnings"].append(f"Template skipped because file exists: {dest_path}") continue content = Template(src_path.read_text(encoding="utf-8")).safe_substitute(variables) ``` The resulting value is embedded directly into instruction-bearing content in `templates/SOUL.template.md`, lines 7-14: ```markdown ## Identity You are ${agent_name}. Your main job is: ${purpose}. ## Working Style - Stay focused on the agent purpose. - Prefer concrete steps and clear output. - Escalate when information is missing or decisions are risky. ``` It is also written into `BOOTSTRAP.md` through `templates/BOOTSTRAP.template.md`, lines 5-8: ```markdown ## Purpose ${purpose} ``` ### Technical Analysis The `purpose` field originates from a conversational request and is treated as trusted agent instruction text. `Template.safe_substitute()` only performs string substitution; it does not sanitize Markdown, distinguish data from instructions, or prevent prompt injection. A crafted purpose can introduce new headings and imperative instructions into `SOUL.md`. ...[truncated 2100 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Treat `agent_name` and `purpose` as untrusted descriptive data rather than executable agent policy. - Do not interpolate free-form conversational text directly into `SOUL.md` or other instruction-bearing files. - Store user descriptions in a clearly delimited data file, such as JSON, and use a fixed, reviewed `SOUL.md` that instructs the agent not to interpret description fields as higher-priority policy. - If free-form content must appear in Markdown, normalize it to a restricted single-paragraph representation and reject headings, code blocks, control characters, embedded directives, links, and excessive length. Markdown escaping alone does not fully prevent prompt injection. - Show the exact generated `SOUL.md` content in the confirmation preview, not merely the raw field values. - Require explicit operator confirmation before persisting identity instructions. - Disable agent-to-agent access by default for newly generated agents and grant it only after review. - Introduce tests using malicious multiline purposes, instruction-like headings, prompt delimiters, and requests to disclose secrets. ]]>
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 Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (11)

Ae1

High
Category
analysis-evasion
Content
This skill is the conversational front end for the local script `scripts/add_feishu_agent.py`.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
This skill is the conversational front end for the local script `scripts/add_feishu_agent.py`.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
This skill is the conversational front end for the local script `scripts/add_feishu_agent.py`.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
This skill is the conversational front end for the local script `scripts/add_feishu_agent.py`.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Vague Triggers

Medium
Confidence
93% confidence
Finding
The README suggests broad natural-language trigger phrases for invoking the skill, which can cause accidental activation during ordinary conversation. In an agent environment where skill routing may rely on fuzzy matching, unintended invocation could prompt users for secrets or initiate configuration changes they did not explicitly mean to perform.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The direct usage guidance again uses ambiguous activation phrases without defining strict boundaries for when the skill should run. Because this skill performs configuration changes and requests sensitive Feishu credentials, accidental triggering increases the chance of unwanted secret collection or unintended modification workflows.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The documentation instructs users to provide a Feishu App Secret but does not include any warning about secure handling, redaction, storage, or disclosure risks. In a chat-driven skill context, this omission is more dangerous because users may paste long-lived credentials into logs, transcripts, screenshots, or shared terminals without realizing the exposure.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The command examples place the Feishu App Secret directly on the command line, which commonly exposes it through shell history, process listings, terminal scrollback, and audit tooling. This is especially risky because the README presents the pattern as normal usage without caution, making credential leakage likely in real environments.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill instructs the agent to run a local Python script that can read environment data, modify configuration files, and invoke the shell, but it declares no explicit tool scope or permission boundaries. This creates an unnecessary trust gap: a consumer of the skill cannot tell in advance that it may execute commands and write files, increasing the risk of unintended command execution or config changes if the skill is invoked in the wrong context.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The skill tells users to pass the Feishu App Secret directly as a command-line argument. Secrets provided on the command line are commonly exposed through shell history, process listings, audit logs, and telemetry, so this can leak long-lived credentials to other local users or monitoring systems.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
self.summary["changes"].append(f"Dry run only: would run {' '.join(command)}")
            return
        try:
            completed = subprocess.run(
                command,
                check=True,
                capture_output=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Static analysis

No suspicious patterns detected.