Back to skill

Security audit

Feishu Reaction

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it says, but its reaction script has unsafe input handling that can turn message or emoji arguments into local Python code execution.

Review before installing. The skill is not showing clear malicious intent, but it grants an agent the ability to send Feishu reactions using local app credentials and its script has code-injection bugs. Install only if you trust the author, restrict who can trigger it, avoid proactive mode unless explicitly wanted, and require fixes for input validation and safe JSON/config parsing before use in a shared or production 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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/feishu-reaction.sh:11
Finding
Arbitrary Python Code Execution Through OPENCLAW_CONFIG Path Injection## Vulnerability Details **File Location**: `scripts/feishu-reaction.sh`, lines 11–19 **Vulnerability Type**: Python source injection through unsafe shell-variable interpolation **Risk Level**: High ### Vulnerable Code ```bash # Locate openclaw config CONFIG="${OPENCLAW_CONFIG:-$HOME/.openclaw/openclaw.json}" if [ ! -f "$CONFIG" ]; then echo "Error: openclaw.json not found at $CONFIG" >&2 exit 1 fi # Extract Feishu credentials APP_ID=$(python3 -c "import json;print(json.load(open('$CONFIG'))['channels']['feishu']['appId'])") APP_SECRET=$(python3 -c "import json;print(json.load(open('$CONFIG'))['channels']['feishu']['appSecret'])") ``` ### Technical Analysis The value of `OPENCLAW_CONFIG`, stored in `CONFIG`, is interpolated directly into Python source passed to `python3 -c`. Shell quoting protects the shell command structurally, but it does not encode the value as a safe Python string literal. An attacker-controlled configuration path containing a single quote and valid Python syntax can terminate the intended `open('...')` expression and inject additional Python statements or expressions. The file-existence check does not eliminate the issue because Unix filenames can contain quotes and other characters usable in a Python injection sequence. If an attacker can create a correspondingly named file and control `OPENCLAW_CONFIG`, the injected Python executes with the privileges of the user running the Skill. The unsafe value is evaluated twice, once while extracting `appId` and again while extracting `appSecret`. ### Attack Path 1. An attacker gains influence over the environment used to invoke the Skill, particularly `OPENCLAW_CONFIG`. 2. The attacker creates a file whose path both passes the `-f` check and contains characters that terminate the Python string literal. 3. The attacker sets `OPENCLAW_CONFIG` to that crafted path. 4. The script interpolates the path into the `python3 -c` program without ...[truncated 1002 chars]
Remediation
## Remediation Suggestions Never embed a dynamic path directly in Python source. Pass it as a positional argument: ```bash APP_ID=$(python3 - "$CONFIG" <<'PY' import json import sys with open(sys.argv[1], encoding="utf-8") as config_file: config = json.load(config_file) print(config["channels"]["feishu"]["appId"]) PY ) APP_SECRET=$(python3 - "$CONFIG" <<'PY' import json import sys with open(sys.argv[1], encoding="utf-8") as config_file: config = json.load(config_file) print(config["channels"]["feishu"]["appSecret"]) PY ) ``` Additional hardening should include: - Resolve the path to a canonical absolute path before use. - Restrict custom configuration paths to explicitly trusted directories where feasible. - Verify that the configuration is a regular file and is not unexpectedly writable by other users. - Parse the configuration once rather than invoking Python separately for each credential. - Ensure errors never print `appSecret` or tenant tokens. - Apply restrictive filesystem permissions to the OpenClaw configuration.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/feishu-reaction.sh:32
Finding
Arbitrary Python Code Execution Through Emoji Type Injection## Vulnerability Details **File Location**: `scripts/feishu-reaction.sh`, lines 32–39 **Vulnerability Type**: Python source injection through an untrusted command-line argument **Risk Level**: High ### Vulnerable Code ```bash REACTION_ID=$(curl -sf "https://open.feishu.cn/open-apis/im/v1/messages/${MSG_ID}/reactions?reaction_type=${EMOJI_TYPE}" \ -H "Authorization: Bearer $TOKEN" \ | python3 -c " import json,sys d=json.load(sys.stdin) for item in d.get('data',{}).get('items',[]): if item.get('reaction_type',{}).get('emoji_type')=='${EMOJI_TYPE}': if item.get('operator',{}).get('operator_type')=='app': print(item['reaction_id']); break " 2>/dev/null) ``` ### Technical Analysis `EMOJI_TYPE` comes from the second command-line argument and is inserted directly into a multiline Python program. It appears between single quotes in the generated source, but the script does not escape quotes, backslashes, newlines, or Python syntax. A malicious emoji value can terminate the intended string literal and introduce executable Python syntax. This vulnerable Python block is reached when the third argument is `remove`. The response from Feishu is supplied through standard input, but the attacker-controlled program is parsed before normal reaction filtering occurs. This exceeds the privileges required for adding or removing reactions. The declared functionality only requires treating the emoji type as data and sending it to the Feishu API; it does not require evaluating the emoji type as local source code. ### Attack Path 1. An attacker influences a Skill invocation or causes an agent to invoke the script with an attacker-selected emoji type. 2. The invocation uses the `remove` action, causing execution to enter the vulnerable branch. 3. The attacker supplies an emoji argument containing a quote followed by syntactically valid Python content. 4. The script obtains a Feishu tenant token and requ ...[truncated 1279 chars]
Remediation
## Remediation Suggestions Pass the emoji value as data through a positional argument rather than interpolating it into Python source: ```bash REACTION_ID=$( curl -sf \ "https://open.feishu.cn/open-apis/im/v1/messages/${MSG_ID}/reactions?reaction_type=${EMOJI_TYPE}" \ -H "Authorization: Bearer $TOKEN" | python3 - "$EMOJI_TYPE" <<'PY' import json import sys emoji_type = sys.argv[1] data = json.load(sys.stdin) for item in data.get("data", {}).get("items", []): if item.get("reaction_type", {}).get("emoji_type") == emoji_type: if item.get("operator", {}).get("operator_type") == "app": print(item["reaction_id"]) break PY ) ``` Because a here-document would otherwise occupy standard input, production code should either pass the API response through a temporary variable or file descriptor, or implement the complete HTTP request and JSON processing in one language. Additional hardening should include: - Validate `EMOJI_TYPE` against an explicit allowlist of supported Feishu emoji identifiers. - Validate `ACTION` against exactly `add` and `remove`; reject all other values. - Validate `MSG_ID` against the expected Feishu message-ID format. - URL-encode all query and path parameters rather than directly concatenating them. - Generate request bodies with a JSON serializer instead of string interpolation. - Avoid suppressing all Python errors with `2>/dev/null`, as this can conceal exploitation attempts and malformed responses. - Log validation failures without recording credentials or bearer tokens.
Vulnerability Patterns
  • 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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (13)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The documented purpose focuses on message reactions, but the detected behavior includes event handling and access to local configuration credentials/auth token retrieval that are not transparently declared. Hidden or underspecified credential access materially raises the risk of privilege misuse, secret exposure, or broader Feishu API actions than users expect.

Credential Access

High
Category
Privilege Escalation
Content
APP_ID=$(python3 -c "import json;print(json.load(open('$CONFIG'))['channels']['feishu']['appId'])")
APP_SECRET=$(python3 -c "import json;print(json.load(open('$CONFIG'))['channels']['feishu']['appSecret'])")

# Get tenant access token
TOKEN=$(curl -sf 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal' \
  -H 'Content-Type: application/json' \
  -d "{\"app_id\":\"$APP_ID\",\"app_secret\":\"$APP_SECRET\"}" \
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

External Script Fetching

High
Category
Supply Chain
Content
APP_SECRET=$(python3 -c "import json;print(json.load(open('$CONFIG'))['channels']['feishu']['appSecret'])")

# Get tenant access token
TOKEN=$(curl -sf 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal' \
  -H 'Content-Type: application/json' \
  -d "{\"app_id\":\"$APP_ID\",\"app_secret\":\"$APP_SECRET\"}" \
  | python3 -c "import json,sys;print(json.load(sys.stdin)['tenant_access_token'])")
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
if [ "$ACTION" = "remove" ]; then
  # Find the bot's reaction_id for this emoji, then delete it
  REACTION_ID=$(curl -sf "https://open.feishu.cn/open-apis/im/v1/messages/${MSG_ID}/reactions?reaction_type=${EMOJI_TYPE}" \
    -H "Authorization: Bearer $TOKEN" \
    | python3 -c "
import json,sys
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
" 2>/dev/null)

  if [ -n "$REACTION_ID" ]; then
    curl -sf -X DELETE "https://open.feishu.cn/open-apis/im/v1/messages/${MSG_ID}/reactions/${REACTION_ID}" \
      -H "Authorization: Bearer $TOKEN" \
      | python3 -c "import json,sys;d=json.load(sys.stdin);print(f'code={d[\"code\"]}, msg={d[\"msg\"]}')"
  else
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
fi
else
  # Add reaction
  curl -sf -X POST "https://open.feishu.cn/open-apis/im/v1/messages/${MSG_ID}/reactions" \
    -H "Authorization: Bearer $TOKEN" \
    -H 'Content-Type: application/json' \
    -d "{\"reaction_type\":{\"emoji_type\":\"${EMOJI_TYPE}\"}}" \
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill explicitly instructs use of a shell script but does not declare any tool scope or allowed-tools restrictions. That creates an authorization gap where an agent may invoke shell capability without an auditable permission boundary, increasing risk of unintended command execution or expansion beyond the stated task.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The activation guidance is broad enough to trigger on many ordinary conversational situations, including the agent deciding on its own to react 'naturally' or proactively. Overbroad triggering can cause unauthorized external actions, message spam, or privacy-sensitive signaling without a clear user request.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill advertises proactive reactions to incoming messages but does not prominently warn that it may send automatic reactions without an explicit per-message request. This weakens user consent and predictability, making accidental or unwanted outbound actions more likely in a messaging environment.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The script reads appId and appSecret from the user's OpenClaw config and uses them for API authentication, but there is no user-facing warning, prompt, or explicit disclosure beyond an internal comment. For code files, access to sensitive credentials should have some visible disclosure unless already clearly communicated elsewhere in the skill description, which is not present in this file.

External Transmission

Medium
Category
Data Exfiltration
Content
APP_SECRET=$(python3 -c "import json;print(json.load(open('$CONFIG'))['channels']['feishu']['appSecret'])")

# Get tenant access token
TOKEN=$(curl -sf 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal' \
  -H 'Content-Type: application/json' \
  -d "{\"app_id\":\"$APP_ID\",\"app_secret\":\"$APP_SECRET\"}" \
  | python3 -c "import json,sys;print(json.load(sys.stdin)['tenant_access_token'])")
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The script sends authentication data to Feishu and later sends message-related identifiers and reaction operations over the network, but provides no visible disclosure to the user except code comments. For code files, network transmissions that send user or system data should include some warning, logging, or explicit documentation unless the disclosure is already clear to the user.

External Transmission

Medium
Category
Data Exfiltration
Content
fi
else
  # Add reaction
  curl -sf -X POST "https://open.feishu.cn/open-apis/im/v1/messages/${MSG_ID}/reactions" \
    -H "Authorization: Bearer $TOKEN" \
    -H 'Content-Type: application/json' \
    -d "{\"reaction_type\":{\"emoji_type\":\"${EMOJI_TYPE}\"}}" \
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

No suspicious patterns detected.