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

Content
View full analysis

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
View 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
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · CHANGELOG.md (reported line 11)May include surrounding context.

md
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

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · CHANGELOG.md (reported line 13)May include surrounding context.

md
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.

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · SKILL.md (reported line 9)May include surrounding context.

md
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.

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · SKILL.md (reported line 26)May include surrounding context.

bash setup.sh

text

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

## Usage

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · CHANGELOG.md (reported line 12)May include surrounding context.

md
"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"],

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · SKILL.md (reported line 8)May include surrounding context.

md
"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"],

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · _meta.json (reported line 5)May include surrounding context.

json
"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"],

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · astrill-watchdog.sh (reported line 8)May include surrounding context.

sh
"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"],

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · astrill-watchdog.sh (reported line 126)May include surrounding context.

sh
"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"],

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · setup.sh (reported line 7)May include surrounding context.

sh
"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"],

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · CHANGELOG.md (reported line 17)May include surrounding context.

md
"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"],

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · _meta.json (reported line 5)May include surrounding context.

json
"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"],

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · astrill-watchdog.sh (reported line 7)May include surrounding context.

sh
"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"],

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · astrill-watchdog.sh (reported line 17)May include surrounding context.

sh
"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"],

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · astrill-watchdog.sh (reported line 43)May include surrounding context.

sh
"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"],

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · astrill-watchdog.sh (reported line 127)May include surrounding context.

sh
"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"],

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · astrill-watchdog.sh (reported line 72)May include surrounding context.

sh
mkdir -p "$LOG_DIR"
chmod 700 "$LOG_DIR"
touch "$LOG_FILE" "$PID_FILE"
chmod 600 "$LOG_FILE" "$PID_FILE"

# ── Logging ───────────────────────────────────────────────────────────────────

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · astrill-watchdog.sh (reported line 93)May include surrounding context.

sh
mkdir -p "$LOG_DIR"
chmod 700 "$LOG_DIR"
touch "$LOG_FILE" "$PID_FILE"
chmod 600 "$LOG_FILE" "$PID_FILE"

# ── Logging ───────────────────────────────────────────────────────────────────

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · astrill-watchdog.sh (reported line 163)May include surrounding context.

sh
mkdir -p "$LOG_DIR"
chmod 700 "$LOG_DIR"
touch "$LOG_FILE" "$PID_FILE"
chmod 600 "$LOG_FILE" "$PID_FILE"

# ── Logging ───────────────────────────────────────────────────────────────────

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · astrill-watchdog.sh (reported line 233)May include surrounding context.

sh
mkdir -p "$LOG_DIR"
chmod 700 "$LOG_DIR"
touch "$LOG_FILE" "$PID_FILE"
chmod 600 "$LOG_FILE" "$PID_FILE"

# ── Logging ───────────────────────────────────────────────────────────────────

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · astrill-watchdog.sh (reported line 137)May include surrounding context.

sh
return 1
    fi

    env "${DESKTOP_ENV[@]}" setsid "$ASTRILL_BIN" /autostart &>/dev/null &
    log "INFO" "  Astrill relaunched (PID $!)."
}

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · astrill-watchdog.sh (reported line 230)May include surrounding context.

sh
sleep 1
    fi

    nohup bash "$0" _loop >> "$LOG_FILE" 2>&1 &
    local new_pid="$!"
    echo "$new_pid" > "$PID_FILE"
    chmod 600 "$PID_FILE"

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · astrill-watchdog.sh (reported line 70)May include surrounding context.

sh
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}"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · setup.sh (reported line 63)May include surrounding context.

sh
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}"

Static analysis

No suspicious patterns detected.