Back to skill

Security audit

hello-honey

Security checks for vulnerabilities and agentic risk

Overview

The skill’s main behavior is disclosed, but it needs Review because it automates outbound messaging with cloned voice audio, persistent scheduling, plaintext credentials, and weak safety controls.

Install only after reviewing the script and intended recipients. Do not run it as root, do not store live Feishu secrets in the script, use only voice samples you have consent to clone, pin the TTS dependency, restrict file permissions, and add an easy way to disable the scheduled job before enabling automatic sends.

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/flirt_cron.sh:58
Finding
Python Source Injection Through Attacker-Controlled State and Message Data<![CDATA[ ## Vulnerability Details **File Location**: `scripts/flirt_cron.sh:58-80` and `scripts/flirt_cron.sh:232-241` **Vulnerability Type**: Data-to-code injection **Risk Level**: High ### Complete Vulnerable Code ```bash calc_time_diff() { local last_file="$1" local default_time="2026-03-15 01:35:00" if [ -f "$last_file" ]; then LAST_CHAT=$(cat "$last_file") else LAST_CHAT="$default_time" echo "$default_time" > "$last_file" fi python3 -c " from datetime import datetime last = datetime.strptime('$LAST_CHAT', '%Y-%m-%d %H:%M:%S') now = datetime.now() diff = now - last hours = diff.total_seconds() / 3600 if hours < 1: mins = int(diff.total_seconds() / 60) print(f'{mins}分钟') elif hours < 24: print(f'{int(hours)}小时') else: days = int(hours / 24) print(f'{days}天{int(hours%24)}小时') " 2>/dev/null || echo "一会儿" } ``` A second injection sink embeds the selected library entry in Python source: ```bash # 更新状态 python3 -c " import json with open('$FLIRT_STATE', 'r+') as f: d = json.load(f) d['sent_flirts'].append('$SELECTED_FLAIR') d['last_flirt_date'] = '$(date +%Y-%m-%d)' f.seek(0) json.dump(d, f, ensure_ascii=False) f.truncate() " 2>/dev/null ``` ### Technical Analysis The script reads `LAST_CHAT` from a state file and `SELECTED_FLAIR` from the customizable flirt library, then inserts both values directly into source code supplied to `python3 -c`. Shell quoting around the command does not make the resulting Python source safe. A value containing a single quote followed by valid Python statements can terminate the intended string literal and inject additional Python operations. Python can import `os` or `subprocess`, so successful injection can execute arbitrary operating-system commands with the privileges of the scheduled script. The documented cron example uses a path under `/root`, indicating that the script may be scheduled by root. In that deployment, th ...[truncated 1246 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Never interpolate file or message content into Python source code. - Pass values as positional arguments or environment variables and read them through `sys.argv` or `os.environ`. - Move state handling into a dedicated Python file that parses JSON and timestamps strictly as data. - Validate timestamps with an allowlisted format before processing them. - Serialize flirt entries through a JSON encoder rather than constructing Python string literals. - Restrict the library, state files, and containing directories to the service account, using permissions such as `0700` for directories and `0600` for files. - Execute the cron job under a dedicated unprivileged account rather than root. - Add tests using quotes, backslashes, newlines, and Python syntax to verify that content cannot alter program structure. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/flirt_cron.sh:169
Finding
Predictable Temporary Files in a Shared Directory<![CDATA[ ## Vulnerability Details **File Location**: `scripts/flirt_cron.sh:169-182` **Vulnerability Type**: Insecure temporary-file creation and symlink race **Risk Level**: High ### Complete Vulnerable Code ```bash # 生成飞书语音 (使用Noiz克隆) VOICE_FILE_FEISHU="/tmp/flirt_voice_feishu_$(date +%s).wav" python3 $VOICE_SCRIPT -t "$MESSAGE_FEISHU" --ref-audio "$REF_VOICE" -o "$VOICE_FILE_FEISHU" 2>/dev/null # 转换为真正的Opus格式 VOICE_FILE_FEISHU_OGG="${VOICE_FILE_FEISHU%.wav}.ogg" ffmpeg -y -i "$VOICE_FILE_FEISHU" -c:a libopus -b:a 64k "$VOICE_FILE_FEISHU_OGG" 2>/dev/null VOICE_FILE_FEISHU="$VOICE_FILE_FEISHU_OGG" # 生成QQ语音 (使用Noiz克隆) VOICE_FILE_QQ="/tmp/flirt_voice_qq_$(date +%s).wav" python3 $VOICE_SCRIPT -t "$MESSAGE_QQ" --ref-audio "$REF_VOICE" -o "$VOICE_FILE_QQ" 2>/dev/null # 转换为真正的Opus格式 VOICE_FILE_QQ_OGG="${VOICE_FILE_QQ%.wav}.ogg" ffmpeg -y -i "$VOICE_FILE_QQ" -c:a libopus -b:a 64k "$VOICE_FILE_QQ_OGG" 2>/dev/null VOICE_FILE_QQ="$VOICE_FILE_QQ_OGG" ``` Equivalent output creation is also duplicated at `scripts/flirt_cron.sh:29-42`. ### Technical Analysis Temporary audio files are placed directly in the shared `/tmp` directory. Their names contain only the current Unix timestamp in seconds, making them predictable. The script does not create files atomically, verify ownership, reject symbolic links, or use a private temporary directory. A local attacker can predict the filenames and pre-create symbolic links at the expected `.wav` or `.ogg` paths. Programs invoked by the script, particularly `ffmpeg -y`, may follow those links and overwrite their targets. The severity is elevated when the cron job runs as root, as suggested by the documented `/root` deployment path. The duplicated pre-processing block at lines 29-42 creates additional predictable files before the probability check and before message variables are initialized, unnecessarily expanding the attack surface. ### Attack Path 1. The attacker observes or infers the scheduled execution time. 2. Immedia ...[truncated 1006 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Create a private directory with `mktemp -d`, set `umask 077`, and place every temporary output inside that directory. - Register an `EXIT`, `INT`, and `TERM` trap that removes the private directory. - Avoid predictable timestamp-only filenames. - Ensure temporary outputs are created atomically and are not symbolic links. - Remove the duplicate voice-generation block at lines 29-42. - Quote the executable path and all file arguments. - Run the scheduled job under a dedicated unprivileged account. - Consider storing temporary data in a service-specific runtime directory inaccessible to other local users. A safer pattern is: ```bash umask 077 TMP_DIR=$(mktemp -d) || exit 1 trap 'rm -rf -- "$TMP_DIR"' EXIT INT TERM VOICE_FILE_FEISHU="$TMP_DIR/feishu.wav" VOICE_FILE_FEISHU_OGG="$TMP_DIR/feishu.ogg" VOICE_FILE_QQ="$TMP_DIR/qq.wav" VOICE_FILE_QQ_OGG="$TMP_DIR/qq.ogg" ``` ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/flirt_cron.sh:12
Finding
Feishu Application Secret Stored in Plaintext Script Configuration<![CDATA[ ## Vulnerability Details **File Location**: `scripts/flirt_cron.sh:12-18` **Vulnerability Type**: Plaintext credential storage **Risk Level**: Medium ### Complete Vulnerable Code ```bash # 飞书配置 - 请替换为你的值 FEISHU_APP_ID="cli_你的APP_ID" FEISHU_APP_SECRET="你的APP_SECRET" FEISHU_USER_ID="你的用户ID" # QQ配置 - 请替换为你的值 QQ_OPENID="你的QQ_OPENID" ``` The same configuration method is recommended in `SKILL.md:33-39` and `SKILL.md:87-94`. ### Technical Analysis Users are explicitly instructed to replace placeholders in the executable script with live Feishu credentials. This stores the application secret in plaintext alongside code. Such files are commonly copied into repositories, backups, diagnostic archives, shared workspaces, or support bundles. No restrictive permission check is performed before the secret is used. Anyone who can read the script can recover the credential and attempt to obtain a Feishu tenant access token. The resulting access is constrained by the application permissions assigned in Feishu, but those permissions may include file upload and message sending. ### Attack Path 1. A user follows the documentation and writes a live Feishu application secret into `flirt_cron.sh`. 2. The script is left readable to other local users, committed to version control, included in a backup, or otherwise disclosed. 3. An attacker extracts the application ID and secret. 4. The attacker submits them to Feishu's tenant-token endpoint. 5. If the credentials remain valid, the attacker receives a token with the application's configured scopes. 6. The attacker uses those scopes to impersonate the application or abuse its messaging capabilities. ### Impact Assessment Exposure may allow unauthorized Feishu API access within the application's granted scope. Potential effects include sending messages as the application, uploading files, accessing permitted tenant resources, reputational damage, and consumption of service quotas. This finding does not establish that ...[truncated 167 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Do not store live credentials in the executable script. - Load credentials from a dedicated secret manager or a configuration file outside the Skill directory. - Restrict a local credential file to the service account with mode `0600` and restrict its parent directory. - Add secret-bearing files to version-control ignore rules. - Fail closed when credentials are absent instead of encouraging inline replacement. - Use the minimum Feishu application scopes required for token acquisition, audio upload, and message delivery. - Document credential rotation and revoke any secret that may have been committed or shared. - Ensure logs never print application secrets or bearer tokens. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:27
Finding
Unpinned Third-Party Dependency Installation<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:27-30` and `SKILL.md:56-64` **Vulnerability Type**: Unpinned and mutable dependency retrieval **Risk Level**: Medium ### Complete Vulnerable Code ```bash # 1. 安装Noiz TTS skill npx skills add https://github.com/noizai/skills --skill tts ``` Additional installation instructions are: ```bash # 安装依赖 pip install requests # 安装Noiz TTS skill(用于声音克隆) npx skills add https://github.com/noizai/skills --skill tts # 或使用skillhub skillhub install tts ``` ### Technical Analysis The installation commands do not pin `requests` or the TTS Skill to an immutable version, commit, lockfile, or integrity hash. Consequently, the code installed in the future can differ from the code that was reviewed. The GitHub installation references a mutable repository state, while the package-manager commands resolve whatever version is current under their normal resolution rules. Dependency installation may execute package lifecycle or setup logic. The scheduled script later invokes the installed TTS script with generated message content and reference voice audio, increasing the impact of an upstream compromise. The reviewed project does not contain a `curl | bash` pipeline. The relevant issue is mutable third-party dependency installation rather than direct remote shell-payload execution. ### Attack Path 1. A user follows the documented installation instructions. 2. The package registry entry, Skill registry entry, repository, maintainer account, or dependency chain is compromised or changes unexpectedly. 3. The unpinned command retrieves the altered release or repository state. 4. Installation-time code may execute immediately, or malicious TTS code is installed for later execution. 5. The cron job invokes the installed TTS script. 6. The dependency executes with the scheduled account's privileges and can access data available to that process, including reference voice audio and local configuration. ### Impact Assessme ...[truncated 505 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Pin the TTS Skill to a reviewed immutable commit hash or signed release. - Pin Python packages to audited versions and use a lockfile. - Use hash verification, such as `pip --require-hashes`, where supported. - Record expected repository URLs, commit identifiers, package hashes, and signer information. - Review dependency manifests and transitive dependencies before installation. - Avoid installing dependencies as root. - Separate installation privileges from runtime privileges and execute the TTS component in a constrained environment. - Establish an explicit update process that re-audits dependency changes before advancing pinned versions. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (18)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The skill advertises flirt-message scheduling but the documented behavior also includes account credential configuration, platform authentication, file upload, text/voice messaging, and external API use without declaring permissions. This mismatch reduces informed consent and can cause users or orchestrators to authorize a skill without understanding that it will access external communication channels and send content automatically.

Missing User Warnings

High
Confidence
95% confidence
Finding
The setup asks for sensitive identifiers and a reference voice sample, then uses them for voice cloning and external messaging, but does not provide a clear privacy, consent, retention, or misuse warning. Voice samples are biometric-like data and account identifiers are sensitive; collecting them without explicit safeguards creates privacy and impersonation risk.

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Content
#!/bin/bash
# flirt_cron.sh - 情话定时发送脚本
# 调用方式: crontab -e 添加: 0 8-22 * * * /root/.openclaw/workspace/flirt_cron.sh
# 每小时(8-22点)触发一次,40%概率发送

# 配置
PROBABILITY=40  # 触发概率40%
WORKSPACE="/root/.openclaw/workspace"
FLIRT_LIB="$WORKSPACE/flirt_library.txt"
FLIRT_STATE="$WORKSPACE/flirt_state.json"

# 飞书配置 - 请替换为你的值
FEISHU_APP_ID="cli_你的APP_ID"
FEISHU_APP_SECRET="你的APP_SECRET"
FEISHU_USER_ID="你的用户ID"

# QQ配置 - 请替换为你的值
QQ_OPENID="你的QQ_OPENID"

# 上次对话时间记录(分开记录)
LAST_CHAT_FILE_FEISHU="$WORKSPACE/memory/last_chat_feishu.tx
Confidence
75% confidence
Finding
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

External Script Fetching

High
Category
Supply Chain
Content
DURATION_MS=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$VOICE_FILE_FEISHU" | python3 -c "print(int(float(input()) * 1000))")
        
        # 上传文件
        UPLOAD_RESP=$(curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/files" \
            -H "Authorization: Bearer $FEISHU_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.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill documentation describes shell execution, file writes, external network interaction, and persistent scheduling, but declares no tool scope or permissions. This creates an authorization transparency gap: an agent or user may invoke capabilities with broader effects than the manifest communicates, increasing the chance of unsafe execution or accidental approval.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The feature list describes scheduling and voice cloning, but does not clearly warn that the skill will automatically send messages and cloned audio to external platforms on a timer. Automatic outbound communication can surprise users, create spam/harassment issues, and disclose personal content if misconfigured.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding
Using `npx skills add https://github.com/noizai/skills --skill tts` without a pinned version or commit causes the installation source to be mutable. If the upstream repository changes or is compromised, later installs may fetch malicious code, leading to supply-chain execution under the user's environment.

Ssd 3

Medium
Confidence
94% confidence
Finding
The AI-guided setup instructs the user to disclose account identifiers and a voice sample, then states the AI will automatically extract audio, transform it, and configure the script. This encourages handing sensitive data to an automation flow without clear validation boundaries, storage protections, or confirmation steps, increasing the risk of accidental leakage, misconfiguration, or unauthorized impersonation.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding
The second unpinned `npx skills` installation instruction has the same supply-chain risk: it relies on remote code that can change over time. This is especially risky because the installed skill is then used for TTS/voice processing and likely runs with file and shell access.

Session Persistence

Medium
Category
Rogue Agent
Content
```bash
# 每小时触发 (8-22点)
crontab -e
0 8-22 * * * /path/to/scripts/flirt_cron.sh
```
Confidence
89% confidence
Finding
The skill instructs users to install a cron job, creating persistent scheduled execution that continues independently of the interactive session. Persistence is security-relevant because a misconfigured or abused task can keep sending external messages, consuming credentials, or running after the user forgets it was enabled.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
This plain-text skill resource contains only Chinese natural-language content and provides no indication that users can choose another language or that the skill is intentionally limited to a Chinese-speaking context. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation.

Session Persistence

Medium
Category
Rogue Agent
Content
#!/bin/bash
# flirt_cron.sh - 情话定时发送脚本
# 调用方式: crontab -e 添加: 0 8-22 * * * /root/.openclaw/workspace/flirt_cron.sh
# 每小时(8-22点)触发一次,40%概率发送

# 配置
Confidence
85% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The script is designed to use Feishu application credentials and a user identifier, but it handles them as inline shell variables without any security guidance or safer secret-loading pattern. This increases the risk of accidental credential exposure through file disclosure, backups, version control, or operational mishandling.

External Transmission

Medium
Category
Data Exfiltration
Content
# 获取飞书token
get_feishu_token() {
    curl -s -X POST "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal" \
        -H "Content-Type: application/json" \
        -d "{\"app_id\":\"$FEISHU_APP_ID\",\"app_secret\":\"$FEISHU_APP_SECRET\"}" | \
        python3 -c "import json,sys; print(json.load(sys.stdin).get('tenant_access_token',''))"
Confidence
92% confidence
Finding
This function transmits the Feishu app ID and app secret to Feishu's token endpoint to obtain an access token. Although expected for the integration, it is still a real external transmission of sensitive credentials, so the risk depends on whether operators understand and approve that secret exchange.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The script automatically sends generated text and cloned-voice audio to Feishu and QQ, which is an external transmission of user-derived content. In a skill context, undisclosed outbound messaging and voice upload is security-relevant because it can leak private content or biometric voice data if enabled without explicit operator awareness and consent.

External Transmission

Medium
Category
Data Exfiltration
Content
# 发送飞书
if [ -f "$VOICE_FILE_FEISHU" ]; then
    # 获取飞书token并发送语音
    FEISHU_TOKEN=$(curl -s -X POST "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal" \
        -H "Content-Type: application/json" \
        -d "{\"app_id\":\"$FEISHU_APP_ID\",\"app_secret\":\"$FEISHU_APP_SECRET\"}" | \
        python3 -c "import json,sys; print(json.load(sys.stdin).get('tenant_access_token',''))")
Confidence
92% confidence
Finding
The script again posts Feishu credentials to an external API during message sending, duplicating sensitive outbound authentication behavior. Repeated ad hoc token retrieval expands the attack surface and operational risk if the script or logs are exposed.

External Transmission

Medium
Category
Data Exfiltration
Content
if [ -n "$FILE_KEY" ]; then
            # 发送语音消息
            curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id" \
                -H "Authorization: Bearer $FEISHU_TOKEN" \
                -H "Content-Type: application/json" \
                -d "{\"receive_id\":\"$FEISHU_USER_ID\",\"msg_type\":\"audio\",\"content\":\"{\\\"file_key\\\":\\\"$FILE_KEY\\\"}\"}" 2>/dev/null
Confidence
90% confidence
Finding
This sends an audio message to Feishu using a recipient identifier and uploaded file key, which is a direct external transmission of generated content. In this skill, the content includes cloned voice audio, making the data transfer more sensitive than ordinary text because it may expose biometric or impersonation-capable material.

Natural-Language Policy Violations

Low
Confidence
87% confidence
Finding
The natural-language instructions and examples are entirely in Chinese, and the skill does not indicate that language choice is optional or that the tool is intentionally limited to a Chinese-speaking audience. Under the stated policy, forcing a specific language without opt-in can be a locale-policy issue.

Static analysis

No suspicious patterns detected.