Back to skill

Security audit

Feishu Audio Message

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly does what it says, but it can use stored Feishu credentials to send data externally and includes under-documented modes that can upload local files or post transcripts.

Install only if you trust the Feishu bot credentials and the agents/users who can invoke this skill. Treat it as able to send content to Feishu using the configured account, and avoid using or exposing the --file and transcript modes unless they are explicitly needed and constrained.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/send_audio.sh:31
Finding

Predictable Temporary File Enables Local Symlink Attacks

Content
View full analysis
[voice]}" CHAT_ID="${2:?chat_id required}" VOICE="${3:-zh-CN-XiaoyiNeural}" TMP_FILE="/tmp/feishu_audio_$$.mp3" fi ``` The predictable path is subsequently written to and removed: ```bash "$TTS_BIN" -t "$TEXT" -f "$TMP_FILE" -v "$VOICE" -l "$(echo $VOICE | cut -d- -f1-2)" 2>&1 ``` ```bash if [[ "$FILE_MODE" == false ]]; then rm -f "$TMP_FILE"; fi ``` ### Technical Analysis The script creates a temporary filename in the shared `/tmp` directory using only its process ID. Process IDs are predictable, and the script does not securely create the file before passing its path to `node-edge-tts`. A local attacker may create a symbolic link at the anticipated pathname before the TTS process writes its output. The exact consequences depend on how `node-edge-tts` opens the output path. If it follows symbolic links and truncates the destination, the script can overwrite a file selected by the attacker with the privileges of the user executing the Skill. The cleanup command is quoted and does not itself contain shell-injection behavior, but it does not mitigate the prior unsafe write. ### Attack Path 1. A local attacker monitors or predicts the PID of a future Skill process. 2. The attacker creates `/tmp/feishu_audio_.mp3` a ...[truncated 1022 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/send_audio.sh:85
Finding

Feishu Application Secret Is Exposed Through Process Arguments

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/send_audio.sh:32
Finding

Undocumented File Mode Can Transmit Arbitrary Readable Local Files

Content
View full analysis
&2; exit 1; } fi ``` The selected pathname is then transmitted in a multipart request to Feishu: ```bash UPLOAD_RESP=$(curl -sf -X POST "https://open.feishu.cn/open-apis/im/v1/files" \ -H "Authorization: Bearer $TOKEN" \ -F "file_type=opus" \ -F "file_name=voice.opus" \ -F "file=@$TMP_FILE") ``` ### Technical Analysis The documented Skill purpose is to generate TTS and send it as a Feishu audio message. `SKILL.md` documents only text-based quick usage, while the script contains an additional `--file` mode capable of reading a caller-selected local pathname. The implementation does not: - Restrict files to an approved media directory. - Resolve and validate canonical paths. - Reject symbolic links. - Enforce file ownership or permissions. - Verify the actual media type. - Limit file size. - Require explicit confirmation before transmitting an existing local file. The `-F "file=@$TMP_FILE"` operation causes `curl` to read the selected file and transmit its bytes to the Feishu file-upload endpoint. Declaring `file_type=opus` and `file_name=voice.opus` does not validate or convert the source data. Feishu may reject unsupported content or prevent it from being sent as an audio message, but the bytes are still presented to the remote upload service during the request. This behavior exc ...[truncated 1743 chars]
Remediation
View remediation
&2 exit 1 ;; esac [[ -f "$SOURCE_PATH" && ! -L "$SOURCE_PATH" ]] || { echo "Source must be a regular, non-symlink file" >&2 exit 1 } ``` ]]>
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
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (15)

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/send_audio.sh (reported line 72)May include surrounding context.

sh
[[ -f "$TMP_FILE" ]] || { echo "❌ File not found: $TMP_FILE" >&2; exit 1; }
fi

# --- 3. Get tenant access token ---
echo "🔑 Getting Feishu token..."
TOKEN=$(curl -sf -X POST "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal" \
  -H "Content-Type: application/json" \

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/send_audio.sh (reported line 74)May include surrounding context.

sh
# --- 3. Get tenant access token ---
echo "🔑 Getting Feishu token..."
TOKEN=$(curl -sf -X POST "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 sys,json; r=json.load(sys.stdin); print(r['tenant_access_token']) if r.get('code')==0 else sys.exit(r.get('msg','auth failed'))")

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/send_audio.sh (reported line 81)May include surrounding context.

sh
# --- 4. Upload file (file_type=opus is required for audio messages) ---
echo "📤 Uploading to Feishu..."
UPLOAD_RESP=$(curl -sf -X POST "https://open.feishu.cn/open-apis/im/v1/files" \
  -H "Authorization: Bearer $TOKEN" \
  -F "file_type=opus" \
  -F "file_name=voice.opus" \

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/send_audio.sh (reported line 92)May include surrounding context.

sh
# --- 5. Send audio message (msg_type=audio) ---
echo "📨 Sending audio message..."
SEND_RESP=$(curl -sf -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"receive_id\": \"$CHAT_ID\", \"msg_type\": \"audio\", \"content\": \"{\\\"file_key\\\": \\\"$FILE_KEY\\\"}\"}")

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/send_audio.sh (reported line 122)May include surrounding context.

sh
print(json.dumps(json.dumps(card)))
" "$TRANSCRIPT")

  THREAD_RESP=$(curl -sf -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id" \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d "{

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill documents use of a shell script but does not declare any tool scope or allowed-tools boundary. That omission weakens least-privilege controls and can let the agent invoke shell capability without an explicit user-visible restriction, which is risky for a skill that can read local credentials and send external messages.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The activation description is broad enough to match many ordinary requests involving Feishu, audio, announcements, or voice messaging. Over-broad triggers can cause unintended invocation of a credential-using shell-based skill, increasing the chance of accidental external transmission or message sending without sufficiently specific user intent.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

L25 states that receive_id_type is always chat_id, but the same sentence says DMs should use a user open_id (ou_xxx). For Feishu messaging, sending to an open_id requires receive_id_type=open_id, so this documentation is internally contradictory and misstates how the skill should be used.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill states that Feishu credentials are automatically read from a local configuration and used without any user-facing warning. In a skill that sends messages externally, silent credential access plus automatic transmission can lead to unauthorized messaging, privacy issues, and surprise use of privileged accounts.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

The documented workflow explicitly uploads audio content and then sends a message to Feishu, which is an external transmission channel. In context, this behavior is the skill's purpose, but it remains security-relevant because it can exfiltrate user-provided or generated content to an external service using bearer-token authentication.

Content

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

bash
# Step 1: Upload (file_type=opus is required regardless of actual format)
curl -X POST "https://open.feishu.cn/open-apis/im/v1/files" \
  -H "Authorization: Bearer $TOKEN" \
  -F "file_type=opus" -F "file_name=voice.opus" -F "file=@audio.mp3"
# → returns file_key

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script reads Feishu app credentials from a local OpenClaw config file when environment variables are absent, expanding the skill's access beyond explicitly supplied inputs. This creates a confused-deputy risk: anyone who can invoke the skill may cause it to use locally stored secrets and send messages with the configured Feishu account, even if they were not directly granted those credentials.

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/send_audio.sh (reported line 74)May include surrounding context.

sh
# --- 3. Get tenant access token ---
echo "🔑 Getting Feishu token..."
TOKEN=$(curl -sf -X POST "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 sys,json; r=json.load(sys.stdin); print(r['tenant_access_token']) if r.get('code')==0 else sys.exit(r.get('msg','auth failed'))")

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/send_audio.sh (reported line 92)May include surrounding context.

sh
# --- 5. Send audio message (msg_type=audio) ---
echo "📨 Sending audio message..."
SEND_RESP=$(curl -sf -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"receive_id\": \"$CHAT_ID\", \"msg_type\": \"audio\", \"content\": \"{\\\"file_key\\\": \\\"$FILE_KEY\\\"}\"}")

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

This additional outbound request sends a transcript message in thread, creating a second data transmission channel not strictly necessary to deliver the audio. In context, the extra post can expose sensitive spoken content as searchable text and may surprise users who only requested a voice message.

Content

Scanner excerpt · scripts/send_audio.sh (reported line 122)May include surrounding context.

sh
print(json.dumps(json.dumps(card)))
" "$TRANSCRIPT")

  THREAD_RESP=$(curl -sf -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id" \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d "{

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill can send an additional transcript message/thread reply besides the requested audio, which increases data disclosure beyond the primary action. If sensitive text is converted to speech, the full transcript is also persisted in chat as readable text, potentially broadening exposure and retention.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.