T01 · Skill Instruction Hijacking
- Location
agents/openai.yaml:4- Finding
Agent Behavior and Output Hijacking Through Skill Instructions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This voice-reply skill is coherent, but it needs review because it can automatically send audio through Feishu, infer recipients from local logs, use stored credentials, and execute a caller-selected ffmpeg path.
Install only in an AudioClaw environment where direct Feishu audio sending is intended. Prefer explicit chat IDs over log inference, avoid accepting untrusted request JSON, do not expose ffmpeg_exe or cache_dir to users, review stored credential handling, and treat generated voice replies as data sent to SenseAudio and Feishu.
agents/openai.yaml:4Agent Behavior and Output Hijacking Through Skill Instructions
scripts/openclaw_voice_switchboard.py:1237Arbitrary Executable Invocation Through Request-Controlled ffmpeg Path
scripts/openclaw_voice_switchboard.py:1221Shared Predictable Temporary Cache Enables Symlink and Cache-Poisoning Attacks
scripts/feishu_audio_sender.py:111Automatic Session-Log Recipient Inference Can Send Audio to the Wrong Feishu Chat
The skill advertises narrowly scoped voice-reply behavior but also instructs access to local workspace/session/state files and chat inference behavior that is not prominently declared in the purpose statement. That mismatch is dangerous because operators may approve the skill expecting only TTS generation, while it can also inspect local state and perform message-delivery actions with side effects.
The skill advertises narrowly scoped voice-reply behavior but also instructs access to local workspace/session/state files and chat inference behavior that is not prominently declared in the purpose statement. That mismatch is dangerous because operators may approve the skill expecting only TTS generation, while it can also inspect local state and perform message-delivery actions with side effects.
Referenced artifact was not completely inspected
3. Run `scripts/openclaw_voice_switchboard.py`.
Referenced artifact was not completely inspected
3. Run `scripts/openclaw_voice_switchboard.py`.
Referenced artifact was not completely inspected
3. Run `scripts/openclaw_voice_switchboard.py`.
Referenced artifact was not completely inspected
3. Run `scripts/openclaw_voice_switchboard.py`.
Referenced artifact was not completely inspected
3. Run `scripts/openclaw_voice_switchboard.py`.
Referenced artifact was not completely inspected
3. Run `scripts/openclaw_voice_switchboard.py`.
Referenced artifact was not completely inspected
3. Run `scripts/openclaw_voice_switchboard.py`.
Referenced artifact was not completely inspected
3. Run `scripts/openclaw_voice_switchboard.py`.
Referenced artifact was not completely inspected
3. Run `scripts/openclaw_voice_switchboard.py`.
Referenced artifact was not completely inspected
3. Run `scripts/openclaw_voice_switchboard.py`.
Referenced artifact was not completely inspected
3. Run `scripts/openclaw_voice_switchboard.py`.
Referenced artifact was not completely inspected
3. Run `scripts/openclaw_voice_switchboard.py`.
Referenced artifact was not completely inspected
3. Run `scripts/openclaw_voice_switchboard.py`.
The skill instructs runtime substitution of an injected token with the real sk-... API key from ~/.audioclaw/workspace/state/senseaudio_credentials.json. Accessing a local credential store to retrieve a more privileged secret increases blast radius: a skill that appears to need only a provided token can silently escalate to stored credentials, and compromise of the skill or host process could expose reusable API secrets.
This skill now treats `SENSEAUDIO_API_KEY` as the default API key source again.
Runtime rules:
- If the host app injects `SENSEAUDIO_API_KEY` as an AudioClaw login token such as `v2.public...`, the shared bootstrap will replace it with the real `sk-...` value from `~/.audioclaw/workspace/state/senseaudio_credentials.json` before TTS starts.
- `--api-key-env` still works, but the default runtime path is `SENSEAUDIO_API_KEY`.
If you need the exact same speaker timbre across many emotions, use a purchased multi-variant voice family or an authorized custom voice. Otherwise this skill will approximate the requested emotion with the best available voice and tuning.
User-provided text is sent to an external TTS provider, but the code contains no consent, warning, minimization, or policy gate around transmitting potentially sensitive content. In a voice-reply skill this behavior is expected functionally, yet it is still dangerous because agents may pass secrets, personal data, or internal content to a third-party service without explicit disclosure.
The code copies the entire parent process environment and forwards it to subordinate scripts, which may include unrelated secrets such as API keys, tokens, proxy credentials, or CI secrets. In a skill/executor context that chains multiple helper scripts, this broad propagation increases the blast radius if a child script logs, exposes, or mishandles environment data.
parser.add_argument("--skip-direct-send", action="store_true")
args = parser.parse_args()
env = os.environ.copy()
workspace_root = Path(args.workspace_root).expanduser()
switchboard_args = [
"--text", args.text,
The skill describes capabilities that require shell execution, network access, environment-variable use, and reads/writes under the local workspace, yet it declares no explicit tool scope or permission boundaries. In an agent setting, that omission can cause over-broad execution authority and makes it harder for a host to sandbox the skill to the minimum necessary privileges.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
- `--out` inside the AudioClaw workspace
- `--openclaw-workspace-root` pointing at the workspace root
- `--delivery-profile feishu_voice` when the downstream channel prefers `.ogg/.opus`
- optional `--chmod 644` if you want to be explicit, though this skill now defaults to `0644`
- if `--openclaw-workspace-root` is set and `--out` is omitted, this skill now writes to `workspace/state/audio/` automatically
7. Use the returned JSON manifest in AudioClaw to:
- prefer `scripts/picoclaw_voice_reply.py` for AudioClaw on Feishu
The instruction says the assistant should send 'one short natural Chinese line' if a final message is required. This imposes a specific language choice without indicating that it depends on the user's language or offering an opt-in, which violates the language/locale policy criteria.
The skill is explicitly designed to send user-provided text and generated audio to external services, including the SenseAudio API and Feishu endpoints. External transmission is expected for TTS, but it is still security-relevant because sensitive conversation content, voice preferences, and possibly metadata may leave the local environment without clear consent, minimization, or domain restrictions.
## Resources
- `scripts/senseaudio_tts_client.py`
- Small importable client for `https://api.senseaudio.cn/v1/t2a_v2`
- Handles SSE chunks and writes audio bytes
- `references/openclaw_voice_switchboard.md`
- TTS capability summary plus the official voice catalog reference at `https://senseaudio.cn/docs/voice_api`
The default prompt uses broad activation language such as "Use $audioclaw-skills-voice-reply to turn an AudioClaw reply into AudioClaw speech" and then sets behavioral defaults for future voice replies. Without a narrowly defined trigger condition, the host agent may invoke this skill more often than intended, causing mode-switching into voice output when the user did not clearly request it and increasing the chance of unintended message handling in Feishu/Lark workflows.
The prompt instructs the agent to send a short natural Chinese line if a final assistant message is required, regardless of the user's language preference. This can override user expectations, create confusing or inaccessible output, and leak implementation-specific behavior into the user interaction when no confirmation or a different language would be more appropriate.
This code fetches a tenant token, uploads a local audio file to Feishu, and sends it to a chat, which transmits user data over the network. The script includes no confirmation prompt, no user-facing disclosure before transmission, and no comments/docstrings warning about the privacy impact of uploading local audio and inferred chat context.