T09 · Insecure Skill Coding Practices
- Location
scripts/send_message.py:44- Finding
Shell Command Injection Through Contact Name and Message Arguments
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill has a coherent DingTalk automation purpose, but it combines real message sending, broad screen capture, optional screenshot upload, and an exploitable shell-command pattern that warrants Review before installation.
Install only if you are comfortable granting Screen Recording and Accessibility to an automation that can control DingTalk and capture your desktop. Avoid using --vision unless you accept sending screenshots to DashScope, keep sensitive windows closed, and do not pass untrusted contact names or message text until the shell-command construction is fixed.
scripts/send_message.py:44Shell Command Injection Through Contact Name and Message Arguments
scripts/send_message.py:114Optional External Transmission of Overbroad Full-Screen Captures
scripts/send_message.py:28Sensitive Screenshots Stored in a Predictable Shared Temporary Path
This is a concrete tool-parameter abuse issue because the code constructs shell commands with user-influenced inputs and executes them via shell=True. Contact names and message bodies are attacker-controlled at the CLI boundary, so a crafted value can break out of quoting and execute arbitrary OS commands, compromising the host and any accessible user data.
def run(cmd, timeout=15):
log(f"→ {cmd[:120]}")
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=timeout)
if result.returncode != 0 and result.stderr:
log(f" stderr: {result.stderr[:200]}")
return result
Vision mode sends screenshots of the user's desktop/application state to an external API without any meaningful runtime warning, consent flow, or disclosure in the core interaction. In this skill context, screenshots can reveal private conversations, login QR codes, names, and other sensitive UI content, making silent transmission a significant privacy and data-handling vulnerability.
The README explicitly describes screenshot capture, OCR, login-state detection, QR-code capture, and automated message sending, but it does not clearly warn users that the skill may collect or expose sensitive on-screen content such as chats, contact names, QR login codes, and message contents. In this context, the absence of a privacy/data-handling warning is risky because the automation operates on a real messaging client and relies on broad Screen Recording and Accessibility permissions.
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.
# Personal skills
git clone https://github.com/jacky-wzj/dingtalk-gui-message.git ~/.claude/skills/dingtalk-gui-message
# Project skills
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.
git clone https://github.com/jacky-wzj/dingtalk-gui-message.git ~/.claude/skills/dingtalk-gui-message
git clone https://github.com/jacky-wzj/dingtalk-gui-message.git .claude/skills/dingtalk-gui-message
The skill invokes powerful local capabilities including shell execution, GUI automation, screen capture/OCR, and likely network-backed vision analysis, but it declares no explicit tool scope or permission boundaries. In an agent environment, this increases the chance the skill can be invoked with broader-than-expected authority, enabling unintended data capture from the screen or unauthorized message sending through DingTalk.
The trigger phrases are broad and ambiguous, such as general requests to send a DingTalk message, which can cause accidental invocation in unrelated conversations. Because this skill performs real GUI actions and sends outbound messages, a mistaken trigger can lead to unintended communications or exposure of on-screen data during automation.
The skill requires Screen Recording, Accessibility, OCR, and full GUI automation, but the documentation does not warn users that these capabilities can capture sensitive on-screen information or misfire into the wrong window/contact. This context makes the issue more dangerous because the automation explicitly screenshots the desktop and analyzes visible content, creating privacy and integrity risks even when functioning as designed.
This code performs OCR on screenshots and emits all recognized text plus coordinates as JSON, which can expose sensitive on-screen information such as messages, credentials, or personal data. The file contains usage text but no warning, confirmation, or comment disclosing the privacy impact of extracting and outputting screenshot contents.
The module docstring, CLI descriptions, logs, and output messages are written in Chinese, effectively forcing a single language for users. There is no opt-in, language selection, or documented justification that this skill is intended only for a Chinese-language environment.
The helper wraps all command execution with subprocess.run(..., shell=True) and later interpolates untrusted values such as image paths, contact names, message text, and keywords into shell command strings. Because those values can contain shell metacharacters, an attacker can achieve arbitrary command execution on the host running the skill, which is especially dangerous in a GUI automation tool that already has access to local apps and screenshots.
def run(cmd, timeout=15):
log(f"→ {cmd[:120]}")
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=timeout)
if result.returncode != 0 and result.stderr:
log(f" stderr: {result.stderr[:200]}")
return result
The optional vision path base64-encodes screenshots and sends them to a remote cloud API, which changes the trust boundary from local-only automation to off-device data processing. Those screenshots may contain chats, contact names, QR codes, or other sensitive desktop content, so this behavior creates a real confidentiality risk beyond the stated local GUI/OCR purpose.
The activation examples prominently prescribe Chinese trigger phrases and the implementation notes emphasize Chinese-specific behavior, yet the README does not clearly state that the skill is intentionally limited to a Chinese-language DingTalk environment or offer locale choice. This can constitute a language/locale policy issue when a skill implicitly assumes one language without opt-in or justification.
L58 写明“中文输入:只用 ...”,属于自然语言层面的语言约束,但文档未说明这是用户可选项,也未解释该技能为何必须仅支持中文。根据规则,强制特定语言而无用户选择或明确合理说明,属于语言/locale 政策问题。
The OCR request hard-codes recognition languages to zh-Hans, zh-Hant, and en-US, which imposes specific language/locale settings without offering user opt-in or configuration. That can violate language/locale policy expectations when users need different recognition languages or neutral defaults.
The skill’s stated purpose is sending DingTalk messages through GUI automation. Reading a Qwen API key from ~/.openclaw/openclaw.json or the QWEN_API_KEY environment variable is only needed for the optional remote vision feature, which is not justified by the manifest’s core messaging purpose as written.
No suspicious patterns detected.