T06 · System Persistence
- Location
scripts/install_launch_agent.sh:14- Finding
Persistent LaunchAgent Executes the Proxy-Switching Script Across User Sessions
- Content
View full analysis
Vulnerability Details
File Location:
scripts/install_launch_agent.sh, lines 14-18 and 52-76
Vulnerability Type:T06: System Persistence
Risk Level: HighVulnerable Code:
sh LABEL="com.codex.clash-verge-auto-switch" PLIST_PATH="$HOME/Library/LaunchAgents/${LABEL}.plist" LOG_DIR="$HOME/Library/Logs" OUT_LOG="$LOG_DIR/clash-verge-auto-switch.log" ERR_LOG="$LOG_DIR/clash-verge-auto-switch.err.log"sh "$PYTHON_BIN" - "$PLIST_PATH" "$OUT_LOG" "$ERR_LOG" "$INTERVAL_SECONDS" "$PYTHON_BIN" "$SCRIPT_DIR/switch_fastest.py" "${SCRIPT_ARGS[@]}" <<'PY' import plistlib import sys plist_path, out_log, err_log, interval_seconds, *program_arguments = sys.argv[1:] payload = { "Label": "com.codex.clash-verge-auto-switch", "ProgramArguments": program_arguments, "RunAtLoad": True, "StartInterval": int(interval_seconds), "StandardOutPath": out_log, "StandardErrorPath": err_log, "WorkingDirectory": "/tmp", } with open(plist_path, "wb") as handle: plistlib.dump(payload, handle) PY launchctl bootout "gui/$(id -u)" "$PLIST_PATH" >/dev/null 2>&1 || true launchctl bootstrap "gui/$(id -u)" "$PLIST_PATH" launchctl enable "gui/$(id -u)/$LABEL" >/dev/null 2>&1 || true launchctl kickstart -k "gui/$(id -u)/$LABEL" >/dev/null 2>&1 || trueTechnical Analysis
The installer creates a macOS LaunchAgent under
~/Library/LaunchAgents, registers it withlaunchctl, enables it, and immediately starts it. The generated configuration uses bothRunAtLoadandStartInterval, causingswitch_fastest.pyto execute after the agent is loaded and repeatedly at the user-selected interval.This is an explicit cross-session persistence mechanism. Although the scheduling feature is documented and an uninstaller is supplied, the installed job remains active after the original skill invocation and continues modifying proxy sele ...[truncated 1658 chars]
- Remediation
View remediation
Remediation Suggestions
- Prefer a scheduler that the user explicitly configures and manages outside the skill package.
- Before installation, display the complete plist, executable path, arguments, interval, and persistence implications, and require explicit confirmation.
- Copy the scheduled script into a dedicated, user-owned directory with restrictive permissions instead of executing a mutable file from the skill directory.
- Record and verify a cryptographic hash or signature before each scheduled execution to detect replacement or modification.
- Validate that the script and its parent directories are owned by the expected user and are not writable by other accounts.
- Create the plist with restrictive permissions and reject existing plist files that are symlinks or have unexpected ownership.
- Provide status and removal commands alongside installation instructions, and clearly state that the job remains active until uninstalled.
- Consider omitting
RunAtLoadand immediatekickstartunless the user separately requests those behaviors.
