Back to skill

Security audit

Astrill Watchdog

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed Astrill VPN watchdog that installs a user-level auto-start service and restarts Astrill when the VPN tunnel appears down.

Install only if you want a background user service that automatically restarts Astrill when connectivity checks fail. Review the start/stop behavior, because it can kill and relaunch Astrill and has a PID-matching weakness that could stop an unrelated same-user process in edge cases. Use the documented stop command or systemd user controls if you no longer want it running at login.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
astrill-watchdog.sh:223
Finding
Unsafe PID File Trust and Broad Process Matching Can Terminate Unrelated Processes## Vulnerability Details **File Location**: `astrill-watchdog.sh:223-256` **Vulnerability Type**: Unsafe process identification and termination **Risk Level**: Medium The standalone lifecycle commands trust a PID read from a persistent file without verifying the identity of the referenced process. They also use broad full-command-line matching to locate and terminate presumed orphan watchdog processes. Vulnerable code in `cmd_start`: ```bash cmd_start() { if [[ -f "$PID_FILE" ]]; then local old old="$(cat "$PID_FILE" 2>/dev/null)" || old="" if [[ -n "$old" ]] && kill -0 "$old" 2>/dev/null; then echo "Watchdog already running (PID ${old})." exit 0 fi rm -f "$PID_FILE" fi local orphans orphans="$(pgrep -f 'astrill-watchdog.sh _loop' 2>/dev/null || true)" if [[ -n "$orphans" ]]; then echo "Cleaning up orphaned loop processes: ${orphans}" echo "$orphans" | xargs kill 2>/dev/null || true sleep 1 fi nohup bash "$0" _loop >> "$LOG_FILE" 2>&1 & local new_pid="$!" echo "$new_pid" > "$PID_FILE" chmod 600 "$PID_FILE" echo "Watchdog started (PID ${new_pid}). Log: ${LOG_FILE}" } ``` Vulnerable code in `cmd_stop`: ```bash cmd_stop() { local killed=0 if [[ -f "$PID_FILE" ]]; then local pid pid="$(cat "$PID_FILE" 2>/dev/null)" || pid="" if [[ -n "$pid" ]] && kill "$pid" 2>/dev/null; then echo "Watchdog (PID ${pid}) stopped." killed=1 fi rm -f "$PID_FILE" fi local orphans orphans="$(pgrep -f 'astrill-watchdog.sh _loop' 2>/dev/null || true)" if [[ -n "$orphans" ]]; then echo "$orphans" | xargs kill 2>/dev/null || true echo "Killed orphaned loop processes: ${orphans}" killed=1 ...[truncated 2638 chars]
Remediation
## Remediation Suggestions 1. Use systemd as the sole lifecycle authority when the watchdog is installed as a user service. Replace manual PID discovery and termination with: ```bash systemctl --user start astrill-watchdog.service systemctl --user stop astrill-watchdog.service systemctl --user is-active astrill-watchdog.service ``` 2. If standalone operation must remain, validate PID-file contents before using them: - Require a strictly numeric value. - Reject PID values less than or equal to 1. - Confirm `/proc/$pid` exists. - Verify `/proc/$pid/exe` resolves to the expected Bash executable or installed watchdog. - Verify the NUL-separated `/proc/$pid/cmdline` contains the exact installed script path and `_loop` argument. - Compare the process start time against a start-time value stored alongside the PID to detect PID reuse. 3. Use an exclusive lock, such as `flock`, held for the lifetime of the loop rather than relying on PID-file existence: ```bash exec 9>"$LOG_DIR/watchdog.lock" flock -n 9 || exit 0 ``` 4. Remove `pgrep -f | xargs kill`. If orphan recovery is required, enumerate candidate PIDs and independently validate each process's executable, exact argument vector, user ID, and installed script path before sending a signal. 5. After validation, signal one PID at a time using `kill -- "$pid"` and recheck its identity immediately before signaling to reduce time-of-check/time-of-use exposure. 6. Remove the PID file with an `EXIT`, `TERM`, and `INT` trap when running in standalone mode, while retaining identity validation because abrupt termination can bypass cleanup.
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (28)

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
non-functional:
  - Method 1 (`astrill /reconnect`): silently ignored — it is a single-instance
    handoff argument, not a runtime control command.
  - Method 2 (kill `asovpnc`/`asproxy`): both child processes run as root;
    `pkill` without sudo returns exit 1 and does nothing.
  - Method 3 (`nohup /autostart`): Astrill requires a Wayland display session
    to initialize its GUI stack; `nohup` in a systemd service context lacks
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Session Persistence

Medium
Category
Rogue Agent
Content
handoff argument, not a runtime control command.
  - Method 2 (kill `asovpnc`/`asproxy`): both child processes run as root;
    `pkill` without sudo returns exit 1 and does nothing.
  - Method 3 (`nohup /autostart`): Astrill requires a Wayland display session
    to initialize its GUI stack; `nohup` in a systemd service context lacks
    `WAYLAND_DISPLAY`, causing silent launch failure.
Confidence
65% confidence
Finding
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.

Session Persistence

Medium
Category
Rogue Agent
Content
Watches `tun0` + ping every 30 seconds. On failure, performs a full Astrill restart:
- `pkill astrill` kills the process tree (root-owned children `asproxy`/`asovpnc` die with the parent — no sudo needed)
- `setsid /autostart` relaunches Astrill with the full desktop environment (`DISPLAY`, `DBUS`, `WAYLAND_DISPLAY`) so it can initialize its GUI/Wayland stack from a systemd service context
- Astrill auto-connects to the last used server

On restart failure: logs a CRITICAL block, resumes checking next cycle. Never exits.
Confidence
76% confidence
Finding
The use of `setsid /autostart` to relaunch Astrill from a service context detaches and re-establishes a long-running GUI-connected process, which is a form of execution persistence/resurrection. In benign admin tooling this can be legitimate, but it still increases risk because the process is automatically revived after failure and tied to desktop session environment variables.

Session Persistence

Medium
Category
Rogue Agent
Content
bash setup.sh
```

No sudo. Installs the watchdog, creates a systemd user unit, and starts the service. Enabled on login automatically.

## Usage
Confidence
84% confidence
Finding
The skill installs and enables a systemd user service that starts automatically on login, creating persistence in the user's session. While this appears intended for legitimate availability of the VPN watchdog, persistence mechanisms are security-relevant because they can be abused to maintain ongoing execution, restart unwanted processes, or make removal less obvious to users.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
"id": "astrill-watchdog",
  "version": "2.0.0",
  "name": "Astrill VPN Watchdog",
  "description": "Monitors Astrill StealthVPN on Ubuntu and auto-restarts it when the tunnel drops. Uses tun0 + ping detection and setsid relaunch with full Wayland environment. No sudo required.",
  "platform": "linux",
  "distro": "ubuntu",
  "requires": ["ping", "ip", "pgrep", "pkill", "setsid"],
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
"id": "astrill-watchdog",
  "version": "2.0.0",
  "name": "Astrill VPN Watchdog",
  "description": "Monitors Astrill StealthVPN on Ubuntu and auto-restarts it when the tunnel drops. Uses tun0 + ping detection and setsid relaunch with full Wayland environment. No sudo required.",
  "platform": "linux",
  "distro": "ubuntu",
  "requires": ["ping", "ip", "pgrep", "pkill", "setsid"],
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
"id": "astrill-watchdog",
  "version": "2.0.0",
  "name": "Astrill VPN Watchdog",
  "description": "Monitors Astrill StealthVPN on Ubuntu and auto-restarts it when the tunnel drops. Uses tun0 + ping detection and setsid relaunch with full Wayland environment. No sudo required.",
  "platform": "linux",
  "distro": "ubuntu",
  "requires": ["ping", "ip", "pgrep", "pkill", "setsid"],
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
"id": "astrill-watchdog",
  "version": "2.0.0",
  "name": "Astrill VPN Watchdog",
  "description": "Monitors Astrill StealthVPN on Ubuntu and auto-restarts it when the tunnel drops. Uses tun0 + ping detection and setsid relaunch with full Wayland environment. No sudo required.",
  "platform": "linux",
  "distro": "ubuntu",
  "requires": ["ping", "ip", "pgrep", "pkill", "setsid"],
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
"id": "astrill-watchdog",
  "version": "2.0.0",
  "name": "Astrill VPN Watchdog",
  "description": "Monitors Astrill StealthVPN on Ubuntu and auto-restarts it when the tunnel drops. Uses tun0 + ping detection and setsid relaunch with full Wayland environment. No sudo required.",
  "platform": "linux",
  "distro": "ubuntu",
  "requires": ["ping", "ip", "pgrep", "pkill", "setsid"],
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
"id": "astrill-watchdog",
  "version": "2.0.0",
  "name": "Astrill VPN Watchdog",
  "description": "Monitors Astrill StealthVPN on Ubuntu and auto-restarts it when the tunnel drops. Uses tun0 + ping detection and setsid relaunch with full Wayland environment. No sudo required.",
  "platform": "linux",
  "distro": "ubuntu",
  "requires": ["ping", "ip", "pgrep", "pkill", "setsid"],
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Session Persistence

Medium
Category
Rogue Agent
Content
"id": "astrill-watchdog",
  "version": "2.0.0",
  "name": "Astrill VPN Watchdog",
  "description": "Monitors Astrill StealthVPN on Ubuntu and auto-restarts it when the tunnel drops. Uses tun0 + ping detection and setsid relaunch with full Wayland environment. No sudo required.",
  "platform": "linux",
  "distro": "ubuntu",
  "requires": ["ping", "ip", "pgrep", "pkill", "setsid"],
Confidence
65% confidence
Finding
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.

Session Persistence

Medium
Category
Rogue Agent
Content
"id": "astrill-watchdog",
  "version": "2.0.0",
  "name": "Astrill VPN Watchdog",
  "description": "Monitors Astrill StealthVPN on Ubuntu and auto-restarts it when the tunnel drops. Uses tun0 + ping detection and setsid relaunch with full Wayland environment. No sudo required.",
  "platform": "linux",
  "distro": "ubuntu",
  "requires": ["ping", "ip", "pgrep", "pkill", "setsid"],
Confidence
65% confidence
Finding
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.

Session Persistence

Medium
Category
Rogue Agent
Content
"id": "astrill-watchdog",
  "version": "2.0.0",
  "name": "Astrill VPN Watchdog",
  "description": "Monitors Astrill StealthVPN on Ubuntu and auto-restarts it when the tunnel drops. Uses tun0 + ping detection and setsid relaunch with full Wayland environment. No sudo required.",
  "platform": "linux",
  "distro": "ubuntu",
  "requires": ["ping", "ip", "pgrep", "pkill", "setsid"],
Confidence
65% confidence
Finding
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.

Session Persistence

Medium
Category
Rogue Agent
Content
"id": "astrill-watchdog",
  "version": "2.0.0",
  "name": "Astrill VPN Watchdog",
  "description": "Monitors Astrill StealthVPN on Ubuntu and auto-restarts it when the tunnel drops. Uses tun0 + ping detection and setsid relaunch with full Wayland environment. No sudo required.",
  "platform": "linux",
  "distro": "ubuntu",
  "requires": ["ping", "ip", "pgrep", "pkill", "setsid"],
Confidence
65% confidence
Finding
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.

Session Persistence

Medium
Category
Rogue Agent
Content
"id": "astrill-watchdog",
  "version": "2.0.0",
  "name": "Astrill VPN Watchdog",
  "description": "Monitors Astrill StealthVPN on Ubuntu and auto-restarts it when the tunnel drops. Uses tun0 + ping detection and setsid relaunch with full Wayland environment. No sudo required.",
  "platform": "linux",
  "distro": "ubuntu",
  "requires": ["ping", "ip", "pgrep", "pkill", "setsid"],
Confidence
65% confidence
Finding
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.

Session Persistence

Medium
Category
Rogue Agent
Content
"id": "astrill-watchdog",
  "version": "2.0.0",
  "name": "Astrill VPN Watchdog",
  "description": "Monitors Astrill StealthVPN on Ubuntu and auto-restarts it when the tunnel drops. Uses tun0 + ping detection and setsid relaunch with full Wayland environment. No sudo required.",
  "platform": "linux",
  "distro": "ubuntu",
  "requires": ["ping", "ip", "pgrep", "pkill", "setsid"],
Confidence
65% confidence
Finding
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.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
mkdir -p "$LOG_DIR"
chmod 700 "$LOG_DIR"
touch "$LOG_FILE" "$PID_FILE"
chmod 600 "$LOG_FILE" "$PID_FILE"

# ── Logging ───────────────────────────────────────────────────────────────────
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
mkdir -p "$LOG_DIR"
chmod 700 "$LOG_DIR"
touch "$LOG_FILE" "$PID_FILE"
chmod 600 "$LOG_FILE" "$PID_FILE"

# ── Logging ───────────────────────────────────────────────────────────────────
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
mkdir -p "$LOG_DIR"
chmod 700 "$LOG_DIR"
touch "$LOG_FILE" "$PID_FILE"
chmod 600 "$LOG_FILE" "$PID_FILE"

# ── Logging ───────────────────────────────────────────────────────────────────
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
mkdir -p "$LOG_DIR"
chmod 700 "$LOG_DIR"
touch "$LOG_FILE" "$PID_FILE"
chmod 600 "$LOG_FILE" "$PID_FILE"

# ── Logging ───────────────────────────────────────────────────────────────────
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Session Persistence

Medium
Category
Rogue Agent
Content
return 1
    fi

    env "${DESKTOP_ENV[@]}" setsid "$ASTRILL_BIN" /autostart &>/dev/null &
    log "INFO" "  Astrill relaunched (PID $!)."
}
Confidence
82% confidence
Finding
This command relaunches Astrill detached from the controlling terminal with forwarded desktop-session variables, making the VPN client continue independently of the invoking shell. In this skill's context that is intended watchdog behavior, not malware persistence, but it still creates autonomous session-resident execution that may surprise users and can complicate stopping or auditing the relaunched process.

Session Persistence

Medium
Category
Rogue Agent
Content
sleep 1
    fi

    nohup bash "$0" _loop >> "$LOG_FILE" 2>&1 &
    local new_pid="$!"
    echo "$new_pid" > "$PID_FILE"
    chmod 600 "$PID_FILE"
Confidence
88% confidence
Finding
Starting the watchdog with `nohup ... &` creates a background process that survives terminal closure and continues autonomous monitoring and process-kill/relaunch behavior. In a benign admin tool this is expected, but it is still a real persistence mechanism because it leaves a long-running process active beyond the user's immediate shell session.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The script's `once` path can kill and relaunch Astrill, and `start` begins a persistent watchdog that will later do the same automatically, but the user-facing output does not clearly disclose that disruptive process-control behavior at invocation time. That creates a consent and safety issue: a user may trigger service interruption, process termination, and automatic reconnection without realizing the script will take those actions.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
echo "── Installing watchdog script…"

mkdir -p "$INSTALL_DIR"
chmod 700 "$INSTALL_DIR"
cp "$WATCHDOG_SCRIPT" "$INSTALL_BIN"
chmod 700 "$INSTALL_BIN"
ok "Installed: ${INSTALL_BIN}"
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
echo "── Installing watchdog script…"

mkdir -p "$INSTALL_DIR"
chmod 700 "$INSTALL_DIR"
cp "$WATCHDOG_SCRIPT" "$INSTALL_BIN"
chmod 700 "$INSTALL_BIN"
ok "Installed: ${INSTALL_BIN}"
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Static analysis

No suspicious patterns detected.