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

Content
View full analysis

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
View 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

Content
View full analysis

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
View 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.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/feishu-reaction.sh (reported line 23)May include surrounding context.

sh
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\"}" \

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/feishu-reaction.sh (reported line 24)May include surrounding context.

sh
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'])")

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/feishu-reaction.sh (reported line 31)May include surrounding context.

sh
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

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/feishu-reaction.sh (reported line 43)May include surrounding context.

sh
" 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

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/feishu-reaction.sh (reported line 51)May include surrounding context.

sh
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}\"}}" \

Undeclared Tool Scope

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.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/feishu-reaction.sh (reported line 24)May include surrounding context.

sh
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'])")

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/feishu-reaction.sh (reported line 51)May include surrounding context.

sh
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}\"}}" \