Back to skill

Security audit

Feishu Speaker

Security checks for vulnerabilities and agentic risk

Overview

This Feishu voice skill is not clearly malicious, but it can send audio to Feishu using a local app secret and an embedded default recipient without clear user confirmation.

Review before installing. Use only with a Feishu app and recipient IDs you control, remove the embedded default recipient and app ID, require explicit recipients and files, fix the python3 -c interpolation, avoid putting secrets in process arguments, and pin dependencies before use.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/send_voice_feishu.sh:6
Finding
Python Code Injection Through the Recipient Identifier<![CDATA[ ## Vulnerability Details **File Location**: `scripts/send_voice_feishu.sh`, lines 6 and 52 **Vulnerability Type**: Command injection caused by embedding untrusted input in dynamically generated Python source **Risk Level**: High ### Vulnerable Code ```bash RECEIVER_ID="${3:-ou_94f3936f1896b5378404f377da3fae6f}" ``` ```bash local json_payload=$(python3 -c "import json; print(json.dumps({\"receive_id\": \"$RECEIVER_ID\", \"msg_type\": \"audio\", \"content\": json.dumps({\"file_key\": \"$file_key\"})}))") ``` ### Technical Analysis The script accepts the recipient identifier from its third positional argument and interpolates it directly into a string passed to `python3 -c`. The recipient is therefore treated as part of executable Python source rather than strictly as data. An attacker who can control the third argument can supply characters that terminate the intended Python string or expression and introduce additional Python statements or expressions. Those statements execute with the same operating-system privileges and environment access as the Skill process. Shell quoting does not adequately protect this operation because the injection occurs when Python parses the generated source. The same construction also risks malformed JSON or failed delivery when the identifier contains unexpected characters. ### Attack Path 1. The attacker obtains the ability to invoke the script or influence the recipient argument passed by an Agent or wrapper. 2. The attacker supplies a crafted third argument containing Python syntax that escapes the intended string context. 3. Bash interpolates that value into the source provided to `python3 -c`. 4. Python parses and executes the injected code while constructing the JSON payload. 5. The injected code can invoke local commands, read accessible files, or transmit data using the privileges of the Skill process. ### Impact Assessment Successful exploitation provides arbitrary code execution under the account runnin ...[truncated 470 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Never interpolate recipient identifiers or other data into executable Python source. Pass the values as positional arguments and read them through `sys.argv`, for example: ```bash json_payload="$( python3 - "$RECEIVER_ID" "$file_key" <<'PY' import json import sys receiver_id = sys.argv[1] file_key = sys.argv[2] print(json.dumps({ "receive_id": receiver_id, "msg_type": "audio", "content": json.dumps({"file_key": file_key}), })) PY )" ``` Additionally: 1. Validate the recipient against the expected Feishu open-ID syntax before use. 2. Reject control characters, newlines, and empty identifiers. 3. Prefer a dedicated JSON builder such as `jq --arg` where available. 4. Add tests with quotes, backslashes, newlines, and code-like input. 5. Ensure all variables are consistently quoted and use `set -euo pipefail` to stop on unexpected failures. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/send_voice_feishu.sh:4
Finding
Audio Can Be Sent to a Hard-Coded Opaque Recipient<![CDATA[ ## Vulnerability Details **File Location**: `scripts/send_voice_feishu.sh`, lines 4–6 and 38–57 **Related Location**: `config/voice-config.json`, lines 7–8 **Vulnerability Type**: Unsafe default destination and unintended data disclosure **Risk Level**: High ### Vulnerable Code ```bash APP_ID="cli_a9037acd2ba19bb5" APP_SECRET_FILE="${HOME}/.openclaw/.credentials/feishu-app-secret.txt" RECEIVER_ID="${3:-ou_94f3936f1896b5378404f377da3fae6f}" ``` ```bash local response=$(curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/files" \ -H "Authorization: Bearer $token" \ -F "file_type=opus" \ -F "file_name=voice.ogg" \ -F "duration=$duration" \ -F "file=@$file_path") ``` ```bash local json_payload=$(python3 -c "import json; print(json.dumps({\"receive_id\": \"$RECEIVER_ID\", \"msg_type\": \"audio\", \"content\": json.dumps({\"file_key\": \"$file_key\"})}))") local response=$(curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id" \ -H "Authorization: Bearer $token" \ -H "Content-Type: application/json" \ -d "$json_payload") ``` The same package-specific identifiers are also present in configuration: ```json "app_id": "cli_a9037acd2ba19bb5", "receiver_id": "ou_94f3936f1896b5378404f377da3fae6f" ``` ### Technical Analysis If the caller omits the third argument, the script silently selects a package-defined Feishu open ID. It then uploads the caller-selected audio file and sends the resulting file key to that recipient. A recipient is necessary for the declared messaging functionality, but silently defaulting to an opaque identity embedded in the distributed package is not necessary. The destination is not derived from the active conversation, explicitly approved by the user, or checked against an administrator-managed allowlist. This design can cause sensitive recordings to be delivered to an unintended account. The risk is amplified by the default file path, `/tmp/test_voice.ogg`, ...[truncated 1364 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the hard-coded recipient from both the script and distributed configuration. 2. Require the recipient as an explicit argument and terminate if it is absent: ```bash if [[ $# -lt 3 || -z "$3" ]]; then echo "Error: an explicit recipient ID is required" >&2 exit 1 fi RECEIVER_ID="$3" ``` 3. Validate the recipient ID against the expected Feishu format. 4. Where practical, derive the destination from authenticated conversation context rather than free-form model output. 5. Support an administrator-controlled allowlist for permitted recipients. 6. Display or log the destination before transmission without exposing credentials. 7. Require explicit confirmation for sensitive or user-selected recordings. 8. Do not default to `/tmp/test_voice.ogg`; require an explicit file and verify that it is a regular file owned or approved by the caller. 9. Move application and recipient configuration to user-controlled deployment settings rather than shipping package-specific identifiers. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:32
Finding
Unpinned Third-Party Packages Are Downloaded and Executed<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 32–39 and 251–252 **Vulnerability Type**: Unpinned dependency installation and immediate registry package execution **Risk Level**: Medium ### Vulnerable Code ```bash # 1. Install Whisper (speech to text) pip install openai-whisper # 2. Install Edge-TTS (text to speech) npm install -g edge-tts # 3. Install FFmpeg (audio conversion) # macOS: brew install ffmpeg # Ubuntu: apt-get install ffmpeg ``` The troubleshooting instructions also recommend immediate execution through `npx`: ```bash npx edge-tts "test" --voice zh-CN-YunxiNeural --write-media output.mp3 ``` ### Technical Analysis The installation instructions do not pin exact dependency versions, provide hashes, include lockfiles, or document integrity and publisher verification. The effective code installed can therefore change after the Skill has been reviewed. The global npm installation increases the package's reach within the user environment. The `npx` command can resolve, download, and execute registry content immediately when an appropriate local package is unavailable. This is not evidence that the named packages are currently malicious. The vulnerability is the absence of reproducible and authenticated dependency controls, which exposes users to compromised releases, account takeover of a publisher, dependency confusion, or unexpected upstream changes. ### Attack Path 1. A user follows the documented installation or troubleshooting instructions. 2. The package manager resolves the dependency from a public package registry without an exact reviewed version and integrity policy. 3. A compromised, replaced, or unexpectedly changed release is downloaded. 4. Installation hooks or package code execute under the installing user's privileges. 5. Malicious dependency code can access local files, credentials, and network resources available to that user. For `npx`, downloading and execution may occur as part of a single comman ...[truncated 596 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin every dependency to an exact reviewed version. 2. For Python, provide a locked requirements file with verified hashes and install into an isolated virtual environment: ```text openai-whisper==<reviewed-version> --hash=sha256:<verified-hash> ``` 3. For Node.js, provide `package.json` and a committed lockfile, then use `npm ci` instead of global installation. 4. Avoid `npm install -g` and ad hoc `npx` execution. 5. If `npx` is unavoidable, specify an exact reviewed version and disable prompts, while recognizing that this remains weaker than a locked local installation. 6. Document the verified package publisher and canonical source repository. 7. Use automated dependency scanning and review updates before changing pinned versions. 8. Recommend installation in a minimally privileged environment or container. 9. Pin or document trusted operating-system package sources for FFmpeg. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/send_voice_feishu.sh:17
Finding
Feishu App Secret Is Exposed Through Process Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/send_voice_feishu.sh`, lines 17 and 24–26 **Vulnerability Type**: Sensitive credential placed in a command-line argument **Risk Level**: Medium ### Vulnerable Code ```bash APP_SECRET=$(cat "$APP_SECRET_FILE" | tr -d '\n') ``` ```bash local response=$(curl -s -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\"}") ``` ### Technical Analysis The App Secret is expanded into the argument supplied to curl through `-d`. On operating systems where process command lines are visible, the resulting JSON—including the secret—may be observable through process inspection while curl is running. Visibility depends on the host's process isolation settings and the observer's privileges. At minimum, processes running as the same user or privileged monitoring and diagnostic software may be able to capture the argument. The secret is also inserted into JSON through string interpolation rather than a JSON serializer. Although the secret file is expected to be locally controlled, quotes, backslashes, or control characters could corrupt the request body. ### Attack Path 1. The Skill reads the Feishu App Secret from the credential file. 2. Bash expands the secret into curl's `-d` command-line argument. 3. While curl is running, a local observer or monitoring component captures the process argument vector. 4. The observer extracts the App Secret from the JSON request body. 5. The exposed App ID and App Secret can be used to request tenant access tokens, subject to Feishu's authentication controls. 6. Those tokens can be used for API operations permitted to the Feishu application. ### Impact Assessment Credential compromise can allow unauthorized use of the Feishu application within the scope of its granted permissions. Potential effects include: - Obtaining tenant access tokens. ...[truncated 365 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Construct the JSON using a serializer and stream it to curl through standard input so the secret is not included in curl's argument vector: ```bash response="$( APP_ID="$APP_ID" APP_SECRET="$APP_SECRET" \ python3 - <<'PY' | import json import os print(json.dumps({ "app_id": os.environ["APP_ID"], "app_secret": os.environ["APP_SECRET"], })) PY curl --silent --show-error --fail-with-body \ -X POST \ "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal" \ -H "Content-Type: application/json" \ --data-binary @- )" ``` Further hardening should include: 1. Restrict the credential file to the owning user, such as mode `0600`. 2. Avoid exporting the secret globally or logging request bodies. 3. Unset sensitive shell variables after token acquisition where practical. 4. Use short-lived access tokens and the minimum Feishu application scopes. 5. Rotate the App Secret if process-monitoring systems may have captured historical command lines. 6. Check curl failures and API error codes without printing secrets. ]]>
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (16)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The documented behavior claims a bidirectional voice workflow, but the finding indicates the actual capability includes undeclared local credential access and omits major advertised functions. This mismatch is dangerous because users and reviewers may consent to a harmless-looking media utility while it performs sensitive actions such as reading secrets or sending data.

Credential Access

High
Category
Privilege Escalation
Content
### 1. 配置飞书API凭证

创建文件 `~/.openclaw/.credentials/feishu-app-secret.txt`:

```
你的飞书App Secret
Confidence
93% confidence
Finding
The skill instructs storage and use of a Feishu App Secret from a local credential file, which is sensitive authentication material. Accessing such a secret is inherently high-risk in an agent skill because compromise or misuse could enable unauthorized API actions, impersonation, or message sending through the linked Feishu application.

Credential Access

High
Category
Privilege Escalation
Content
# 用法: send_voice_feishu.sh <音频文件.ogg> [时长毫秒] [接收者ID]

APP_ID="cli_a9037acd2ba19bb5"
APP_SECRET_FILE="${HOME}/.openclaw/.credentials/feishu-app-secret.txt"
RECEIVER_ID="${3:-ou_94f3936f1896b5378404f377da3fae6f}"

# 读取App Secret
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
FILE_PATH="${1:-/tmp/test_voice.ogg}"
DURATION="${2:-4650}"

# 获取access token
get_token() {
    local response=$(curl -s -X POST "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal" \
        -H "Content-Type: application/json" \
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
FILE_PATH="${1:-/tmp/test_voice.ogg}"
DURATION="${2:-4650}"

# 获取access token
get_token() {
    local response=$(curl -s -X POST "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal" \
        -H "Content-Type: application/json" \
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
# 获取access token
get_token() {
    local response=$(curl -s -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\"}")
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
local file_path="$2"
    local duration="$3"
    
    local response=$(curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/files" \
        -H "Authorization: Bearer $token" \
        -F "file_type=opus" \
        -F "file_name=voice.ogg" \
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
# 使用Python构造正确的JSON
    local json_payload=$(python3 -c "import json; print(json.dumps({\"receive_id\": \"$RECEIVER_ID\", \"msg_type\": \"audio\", \"content\": json.dumps({\"file_key\": \"$file_key\"})}))")
    
    local response=$(curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id" \
        -H "Authorization: Bearer $token" \
        -H "Content-Type: application/json" \
        -d "$json_payload")
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 documents multiple shell-based operations (pip, npm, apt/brew, ffmpeg, CLI execution) but does not declare any explicit tool scope or permissions. This creates a trust and review gap: an agent may execute shell commands the user did not clearly authorize, including package installation or message-sending actions.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding
Using 'npx edge-tts' without a pinned version allows execution of whatever package version is currently resolved at runtime. If the upstream package is compromised or a breaking version is published, the skill could run untrusted code on the host.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The default voice is hard-coded to "zh-CN-YunxiNeural", which sets a specific language/locale by default. Under the policy, locale constraints should either offer user choice or be clearly documented and justified; this JSON file shows neither.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The script uploads a caller-supplied audio file to Feishu and can send it to a hard-coded default recipient without any confirmation, warning, or visibility into where the data is going. In an agent-skill context, this increases the risk of unintended exfiltration of sensitive voice content because a user may omit the recipient argument and still transmit private data externally.

External Transmission

Medium
Category
Data Exfiltration
Content
# 获取access token
get_token() {
    local response=$(curl -s -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\"}")
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
# 使用Python构造正确的JSON
    local json_payload=$(python3 -c "import json; print(json.dumps({\"receive_id\": \"$RECEIVER_ID\", \"msg_type\": \"audio\", \"content\": json.dumps({\"file_key\": \"$file_key\"})}))")
    
    local response=$(curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id" \
        -H "Authorization: Bearer $token" \
        -H "Content-Type: application/json" \
        -d "$json_payload")
Confidence
84% confidence
Finding
This request sends a message to Feishu using a recipient that defaults to a preconfigured open_id, which can cause silent transmission to an unintended party if the caller does not override it. In a skill context, outbound messaging is expected, but the hidden default recipient makes accidental data disclosure materially more dangerous.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
The command help states the `--language` option defaults to `zh`, and elsewhere the documentation repeatedly frames the tool around Chinese-only speech/text behavior. Because the skill does not present this as an explicit user choice or a justified region-specific constraint, it appears to impose a locale default in natural-language documentation.

Natural-Language Policy Violations

Low
Confidence
97% confidence
Finding
The script's comments, usage text, and runtime status/error messages are all in Chinese, which imposes a specific language on users. There is no indication that this is a region-specific tool or that users can opt into another language, so it appears to violate the language/locale policy criterion.

Static analysis

No suspicious patterns detected.