T09 · Insecure Skill Coding Practices
- Location
scripts/common.sh:8- Finding
Arbitrary Shell Command Execution Through Unsafe Path Expansion
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is a coherent macOS wallpaper utility, but its scripts contain confirmed command-injection risks and install a persistent LaunchAgent.
Review before installing. Only use trusted wallpaper directories and filenames, avoid paths containing shell or XML metacharacters, and do not install the LaunchAgent unless you understand it will keep running on a schedule. The unsafe scripting should be fixed before general use.
scripts/common.sh:8Arbitrary Shell Command Execution Through Unsafe Path Expansion
scripts/common.sh:53AppleScript Injection Through Malicious Image Filenames
scripts/install_launchagent.sh:18LaunchAgent Plist Injection Through Unescaped Filesystem Paths
声明的核心功能是“立即换壁纸”或“安装定时轮换任务”,而该代码片段的实际功能只是读取本地目录、收集图片、统计数量并打印示例文件名。这属于与声明主目的明显不一致:代码没有调用任何 macOS 壁纸设置机制,也没有创建、写入或加载 launchd 配置。虽然访问本地壁纸目录与该技能主题相关,但这里只体现为辅助性的图片清单检查脚本,不能代表声明中的主要能力,因此应判定为描述与行为不匹配。
The trigger phrases for immediate execution are broad everyday language and directly map user utterances to a local command that changes system state. In an agent setting, overly permissive triggers increase the chance of accidental activation or prompt-induced execution without a sufficiently explicit confirmation boundary.
The folder-check phrases are somewhat ambiguous and can cause the agent to inspect arbitrary local directories based on loosely phrased requests. While the action is read-oriented rather than destructive, it still broadens access to local file metadata and can normalize execution on unclear intent.
These broad install/uninstall automation triggers authorize creation or removal of a persistent launchd job from common-language requests. Persistence mechanisms are security-sensitive because they survive the current session and can be abused or triggered accidentally if the agent does not enforce explicit consent and precise scoping.
The skill explicitly supports writing a launchd plist under the user's LaunchAgents directory, which establishes session persistence. Although persistence is the stated feature rather than covert behavior, persistence itself is security-relevant because it causes recurring execution and can be repurposed if the installed command or target path is not tightly controlled.
输出:
1. 壁纸目录
2. 轮换间隔(分钟)
3. launchd plist 路径
4. 是否安装成功
5. 如何卸载
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.
SUPPORTED_EXTENSIONS=(jpg jpeg png heic webp)
LAUNCHD_LABEL="com.openclaw.wallpaperrotator"
LAUNCHD_PLIST="$HOME/Library/LaunchAgents/${LAUNCHD_LABEL}.plist"
expand_path() {
local input="$1"
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.
SUPPORTED_EXTENSIONS=(jpg jpeg png heic webp)
LAUNCHD_LABEL="com.openclaw.wallpaperrotator"
LAUNCHD_PLIST="$HOME/Library/LaunchAgents/${LAUNCHD_LABEL}.plist"
expand_path() {
local input="$1"
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.
SUPPORTED_EXTENSIONS=(jpg jpeg png heic webp)
LAUNCHD_LABEL="com.openclaw.wallpaperrotator"
LAUNCHD_PLIST="$HOME/Library/LaunchAgents/${LAUNCHD_LABEL}.plist"
expand_path() {
local input="$1"
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.
SUPPORTED_EXTENSIONS=(jpg jpeg png heic webp)
LAUNCHD_LABEL="com.openclaw.wallpaperrotator"
LAUNCHD_PLIST="$HOME/Library/LaunchAgents/${LAUNCHD_LABEL}.plist"
expand_path() {
local input="$1"
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.
SUPPORTED_EXTENSIONS=(jpg jpeg png heic webp)
LAUNCHD_LABEL="com.openclaw.wallpaperrotator"
LAUNCHD_PLIST="$HOME/Library/LaunchAgents/${LAUNCHD_LABEL}.plist"
expand_path() {
local input="$1"
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.
SUPPORTED_EXTENSIONS=(jpg jpeg png heic webp)
LAUNCHD_LABEL="com.openclaw.wallpaperrotator"
LAUNCHD_PLIST="$HOME/Library/LaunchAgents/${LAUNCHD_LABEL}.plist"
expand_path() {
local input="$1"
The expand_path function uses eval on attacker-controlled input, which can trigger shell command execution during path expansion. In a skill that only needs to resolve local wallpaper paths, eval is unnecessary and materially increases risk because crafted input such as command substitution or shell metacharacters could execute arbitrary commands under the user's account.
The error message is hardcoded in Chinese, which forces a specific language for user-facing output without any opt-in or documented locale constraint. This can violate language/locale policy when the skill is intended for general use.
The error message is hardcoded in Chinese, which forces a specific language for user-facing output without any opt-in or documented locale constraint. This can violate language/locale policy when the skill is intended for general use.
The error message is hardcoded in Chinese, which forces a specific language for user-facing output without any opt-in or documented locale constraint. This can violate language/locale policy when the skill is intended for general use.
This shell script emits user-facing status and error text in Chinese, which imposes a specific language on all users. The file does not provide any opt-in, fallback, or justification for the locale restriction, so it conflicts with the language/locale policy criteria.
Writing a LaunchAgent plist into ~/Library/LaunchAgents is a persistence mechanism, because it prepares recurring execution under launchd for the current user. Although this aligns with the skill's stated purpose, persistence always increases attack surface if the plist or referenced script can be modified after installation.
mkdir -p "$HOME/Library/LaunchAgents"
cat > "$LAUNCHD_PLIST" <<PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
The script unloads any existing agent and bootstraps the new plist into the user's launchd domain, activating persistence immediately. In context this is expected functionality, but it remains security-sensitive because it registers recurring execution without additional integrity checks on the referenced script.
<string>${HOME}/Library/Logs/${LAUNCHD_LABEL}.err.log</string>
</dict>
</plist>
PLIST
launchctl bootout "gui/$(id -u)" "$LAUNCHD_PLIST" >/dev/null 2>&1 || true
launchctl bootstrap "gui/$(id -u)" "$LAUNCHD_PLIST"
Enabling the launchd label makes the persistent agent active across future sessions, which is a classic persistence mechanism. The skill context makes this less suspicious than in unrelated software, but it is still a real persistence capability that could be leveraged if the installed components are replaced or modified.
</plist>
PLIST
launchctl bootout "gui/$(id -u)" "$LAUNCHD_PLIST" >/dev/null 2>&1 || true
launchctl bootstrap "gui/$(id -u)" "$LAUNCHD_PLIST"
launchctl enable "gui/$(id -u)/${LAUNCHD_LABEL}" >/dev/null 2>&1 || true
launchctl kickstart -k "gui/$(id -u)/${LAUNCHD_LABEL}" >/dev/null 2>&1 || true
Kickstarting the label forces immediate execution of the persistent LaunchAgent, reducing the time between installation and code execution. In a wallpaper utility this is expected, but from a security perspective it means any unsafe or tampered referenced script runs right away under the user's session.
PLIST
launchctl bootout "gui/$(id -u)" "$LAUNCHD_PLIST" >/dev/null 2>&1 || true
launchctl bootstrap "gui/$(id -u)" "$LAUNCHD_PLIST"
launchctl enable "gui/$(id -u)/${LAUNCHD_LABEL}" >/dev/null 2>&1 || true
launchctl kickstart -k "gui/$(id -u)/${LAUNCHD_LABEL}" >/dev/null 2>&1 || true
The script explicitly enables a per-user launchd agent, creating session persistence that will automatically run on login and at intervals. In this skill's context, persistence is the intended feature for wallpaper rotation, but it is still security-relevant because it establishes recurring execution from a user-writable location and could be abused if the referenced script or directory is later tampered with.
launchctl bootout "gui/$(id -u)" "$LAUNCHD_PLIST" >/dev/null 2>&1 || true
launchctl bootstrap "gui/$(id -u)" "$LAUNCHD_PLIST"
launchctl enable "gui/$(id -u)/${LAUNCHD_LABEL}" >/dev/null 2>&1 || true
launchctl kickstart -k "gui/$(id -u)/${LAUNCHD_LABEL}" >/dev/null 2>&1 || true
echo "状态: 成功"
The script emits user-facing status messages entirely in Chinese (for example at L14, L15, L18, and L22). This imposes a specific language on all users without opt-in or any documented justification, which matches the language/locale policy violation criteria.
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.
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
source "$SCRIPT_DIR/common.sh"
launchctl bootout "gui/$(id -u)" "$LAUNCHD_PLIST" >/dev/null 2>&1 || true
rm -f "$LAUNCHD_PLIST"
echo "状态: 成功"
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.
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
source "$SCRIPT_DIR/common.sh"
launchctl bootout "gui/$(id -u)" "$LAUNCHD_PLIST" >/dev/null 2>&1 || true
rm -f "$LAUNCHD_PLIST"
echo "状态: 成功"
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.
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
source "$SCRIPT_DIR/common.sh"
launchctl bootout "gui/$(id -u)" "$LAUNCHD_PLIST" >/dev/null 2>&1 || true
rm -f "$LAUNCHD_PLIST"
echo "状态: 成功"