T09 · Insecure Skill Coding Practices
- Location
scripts/analyze.js:186- Finding
OS Command Injection Through an Attacker-Controlled Audio Path
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This audio skill mostly does what it advertises, but it handles sensitive audio and voiceprint data with a real command-injection flaw and weak biometric-data controls.
Install only if you are comfortable with audio being sent to AssemblyAI, Gemini, or OpenRouter when those keys are configured. Avoid processing untrusted or oddly named audio files with the Whisper fallback until the shell invocation is fixed, and treat generated transcripts, raw JSON, summaries, and voice-db.json as sensitive files that may need manual permission tightening or deletion.
scripts/analyze.js:186OS Command Injection Through an Attacker-Controlled Audio Path
scripts/voiceprint.py:308Biometric Voice Embeddings Are Disclosed Through Standard Output
scripts/analyze.js:360Transcripts and Raw Speaker Metadata Are Written Without Explicit Restrictive Permissions
scripts/voiceprint.py:190Persistent Biometric Database Is Written Without Explicit Restrictive Permissions
The description overstates the skill's speaker-ID capabilities. The code does perform transcription, basic speaker-labeled formatting when available, scene classification, and structured note generation, so the core audio-analysis workflow is partially aligned. However, the marquee claim—persistent voice profile matching across sessions—is not implemented anywhere: there is no storage or retrieval of speaker embeddings, no cross-session profile database, and no identity matching logic. AssemblyAI speaker labels are generic diarization labels, Gemini is prompted to label speakers textually, and local Whisper assigns all segments to a single speaker. That is materially different from voiceprint identification. Additionally, scene detection is a simple keyword heuristic over a small fixed set of categories and does not include the declared 'talk' scene explicitly. These are material capability mismatches, so the description does not accurately represent the code.
The code accurately supports one important part of the description: persistent voice profile matching across sessions via a saved voice database, plus speaker identification/enrollment. However, the declared description substantially overstates the skill’s functionality. There is no transcription logic, no automatic scene detection, and no structured notes generation. The code is tightly coupled to AssemblyAI-format utterance JSON for the extract flow and does not implement Whisper or Gemini support. Therefore the declared purpose does not accurately represent the actual behavior; the code is a narrower voiceprint utility, not the advertised end-to-end audio analysis skill.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
cd skills/audio-analyzer/scripts && npm install
# 2. Configure (pick ONE — AssemblyAI recommended)
cp .env.example .env
# Edit .env: set ASSEMBLYAI_API_KEY
# 3. Run
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
cd skills/audio-analyzer/scripts && npm install
# 2. Configure (pick ONE — AssemblyAI recommended)
cp .env.example .env
# Edit .env: set ASSEMBLYAI_API_KEY
# 3. Run
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
- Voice embeddings are never sent externally
- Audio files ARE uploaded to cloud ASR (AssemblyAI/Gemini) for transcription. For fully offline operation, use local Whisper
- Speaker identity updates require **explicit user confirmation**
- To delete all voiceprint data: `rm references/voice-db.json`
## Voice Profiles (Text-Based)
The manifest prominently advertises speaker identification by voiceprint and uniquely persistent voice-profile matching across sessions. In this file, the implementation only uses AssemblyAI speaker labels, Gemini prompt-based speaker tags, or Whisper single-speaker placeholders, and merely writes transcript/raw output files locally; there is no logic for creating, storing, retrieving, or matching persistent voice profiles across recordings.
The lockfile pins form-data 4.0.5, which is flagged for CRLF injection in multipart construction. In an audio-analysis skill that uploads files and metadata to external APIs, unsafe multipart field-name handling can enable header or body manipulation if attacker-controlled values are ever inserted into multipart fields by dependent code.
The dependency tree includes ws 8.19.0, which is reported as vulnerable to memory disclosure and memory-exhaustion denial of service. Because this skill processes audio with third-party SDKs and AssemblyAI directly depends on ws, any websocket-based streaming or realtime transcription path could expose sensitive session data or allow a remote party to crash or degrade the service.
Without declared permissions the skill's intent is opaque and cannot be validated.
Broad trigger phrases like 'transcribe', 'meeting notes', or 'analyze audio' can cause unintended activation on ordinary user requests. In this skill, accidental activation is more sensitive because execution may upload audio to third-party APIs and may read or update persistent voice-profile data.
Persisting models and especially cross-session voice-related artifacts under a shared user directory increases privacy and retention risk. In the context of a voice-identification skill, session persistence makes the system more dangerous because biometric-adjacent data and model paths can survive across tasks and potentially across agents without strong lifecycle controls.
apt install ffmpeg # or: brew install ffmpeg
# 3. Download WeSpeaker model
mkdir -p ~/.openclaw/models/wespeaker
# Download cnceleb_resnet34_LM.onnx from:
# https://github.com/wenet-e2e/wespeaker/releases
# Set: export WESPEAKER_MODEL=~/.openclaw/models/wespeaker/cnceleb_resnet34_LM.onnx
The file is fully Chinese and the embedded prompt mandates Chinese output without any language negotiation or documented locale restriction. In an audio-analysis skill that may process multilingual recordings, forcing one output language can lead to misunderstandings, reduced usability, and mishandling of content if users expect summaries in another language.
The fallback condition states this template should be used whenever no other scene matches, which is extremely broad and can cause misclassification of many unrelated recordings. In this skill, scene selection influences downstream summarization behavior and storage, so an overbroad fallback can silently produce incorrect notes, wrong metadata, or inappropriate handling of audio content.
The file is entirely written to operate in Chinese and instructs the assistant in Chinese, but it does not offer the user any language or locale choice. Under the stated policy, forcing a specific language without opt-in can be a natural-language policy violation unless the locale restriction is clearly justified.
The activation section uses a loose list of common words such as '用户', '需求', '反馈', and '产品' without defining context, boundaries, or exclusion conditions. These terms are frequent in everyday product conversations, making it unclear when this scene should activate versus when it should not.
The meeting scene is selected using a short list of very common workplace terms such as 项目, 需求, bug, and 优先级. In an audio-analysis skill that auto-detects scenes and persists outputs to scene-specific memory paths, these broad triggers can misclassify ordinary conversations as meetings, causing incorrect summarization, inappropriate archival, and unintended retention of sensitive content.
The trigger keyword list includes very generic terms such as 教练, 划, 船 that can appear in many unrelated audio contexts, increasing the chance that the rowing scene is selected accidentally. In this skill, misclassification is more dangerous than usual because the selected scene drives downstream structured summarization and may also influence persistent voice-profile workflows, causing incorrect storage, notes, or attribution.
The scene template instructs the system to fetch weather data from an external API, which introduces third-party network transmission and dependency on an external service. Even though the URL shown contains fixed coordinates rather than explicit user data, in the context of an audio-analysis skill this can still create privacy, policy, and integrity risks if external fetches are performed automatically without clear controls, consent, or network restrictions.
### 头部: 天气实况
融合 Open-Meteo 天气数据:
- API: `https://api.open-meteo.com/v1/forecast?latitude=31.143&longitude=121.657&hourly=temperature_2m,apparent_temperature,windspeed_10m,winddirection_10m,precipitation,relative_humidity_2m&timezone=Asia/Shanghai`
- 包含: 气温、体感温度、风速、风向、湿度、降水
### 主体: 按人员
All user-facing instructions are written to produce the analysis in Chinese, and the file does not indicate that language selection is optional or limited to a justified region-specific deployment. Under the policy, forcing a specific language without user opt-in is a natural-language policy concern.
The trigger list includes very common conversational phrases such as '大家好', '提问', and '学习', which are likely to appear in many unrelated recordings. In an audio-analysis skill with automatic scene detection and persistent voice profile matching, overly broad triggers can cause unintended activation or misclassification, leading to unnecessary processing, incorrect note generation, and potential privacy exposure from storing or associating content under the wrong scene.
The entire skill content, including operational instructions and user-facing phrases, is written only in Chinese and directs the assistant to respond with Chinese text such as 'Speaker X 可能是 XXX,因为...'. There is no indication that users may choose another language or that this is a region-specific skill with a documented justification, which creates a language/locale policy concern.
The manifest claims persistent speaker identification by voiceprint across sessions, implying actual biometric/profile-based matching. This file instead describes matching speakers against manually written 'speaking characteristics' and 'content characteristics,' with user confirmation and manual file updates. That is a materially narrower behavior than claimed voiceprint matching.
The description presents scene auto-detection as a general capability, but the code supports only four hard-coded categories and one of them is a very specific rowing-training scenario. Detection is based solely on keyword hits rather than robust audio or conversational analysis, so the implemented behavior is materially narrower than the advertised all-in-one scene detection capability.
Multiple prompt templates explicitly require output in Chinese, and the script also fixes date locale to zh-CN. This enforces a specific language/locale without user opt-in, which matches the stated policy-violation category.
The AssemblyAI transcription path sends user audio to a third-party service without any explicit user-facing disclosure or consent flow in the script. Because audio may contain sensitive personal, business, or biometric information, silent remote transmission increases privacy and compliance risk, especially given this skill markets speaker/voice-related analysis.
Detected: suspicious.dangerous_exec