{"id":"CVE-2026-62982","aliases":["DEBIAN-CVE-2026-62982","EUVD-2026-60303","GHSA-73wf-9vmv-5pv9","PYSEC-2026-3666","UBUNTU-CVE-2026-62982","openSUSE-SU-2026:11674-1"],"status":"published","title":"Glances: Incomplete fix of CVE-2026-32608: action-template sanitizer is bypassed by nested stat values (process 'cmdline') → OS command injection","description":"Glances is an open-source system cross-platform monitoring tool. From 4.5.2 until 4.5.6, _sanitize_mustache_dict() in glances/actions.py skips nested list and dictionary strings such as process cmdline values, allowing pipe characters to survive chevron.render() and be executed by secure_popen() through administrator-configured action templates. This issue is fixed in 4.5.6.","severity":{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-11","score":0.00197,"percentile":0.09564,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-78"],"published":"2026-08-17T17:07:49Z","modified":"2026-10-28T02:31:13Z","fixes":[{"ecosystem":"PyPI","package":"glances","fixed_in":["4.5.6"],"sources":["ghsa","osv"]},{"ecosystem":"Debian:14","package":"glances","fixed_in":["4.5.6+dfsg-1"],"sources":["osv"]}],"affected":[{"source":"ghsa","ecosystem":"PyPI","package":"glances","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.5.2"},{"fixed":"4.5.6"}]}]},{"source":"osv","ecosystem":"Debian:14","package":"glances","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"4.5.6+dfsg-1"}]}],"versions":["4.3.1+dfsg-1","4.3.3+dfsg-1","4.5.1+dfsg-1","4.5.2+dfsg-1","4.5.3.2+dfsg-1","4.5.4+dfsg-1","4.5.5+dfsg-1"]},{"source":"osv","ecosystem":"PyPI","package":"glances","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.5.2"},{"fixed":"4.5.6"}]}],"versions":["4.5.2","4.5.3","4.5.4","4.5.5"]},{"source":"osv","ecosystem":"PyPI","package":"glances","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.5.2"},{"fixed":"4.5.6"}]}],"versions":["4.5.2","4.5.3","4.5.4","4.5.5"]},{"source":"osv","ecosystem":"Ubuntu:Pro:16.04:LTS","package":"glances","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.3-1build1","2.3-1ubuntu0.1~esm1"]},{"source":"osv","ecosystem":"Ubuntu:Pro:18.04:LTS","package":"glances","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.10-2","2.11.1-1","2.11.1-2","2.11.1-3","2.11.1-3ubuntu0.1~esm1"]},{"source":"osv","ecosystem":"Ubuntu:Pro:20.04:LTS","package":"glances","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.1.0-1","3.1.1-1","3.1.3-1","3.1.3-1ubuntu0.1~esm1"]},{"source":"osv","ecosystem":"Ubuntu:22.04:LTS","package":"glances","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.1.5-1","3.2.3.1+dfsg-1","3.2.4.2+dfsg-1"]},{"source":"osv","ecosystem":"Ubuntu:24.04:LTS","package":"glances","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.4.0.3+dfsg-1"]},{"source":"osv","ecosystem":"Ubuntu:26.04:LTS","package":"glances","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["4.3.1+dfsg-1","4.3.3+dfsg-1"]},{"source":"osv","ecosystem":"openSUSE:Tumbleweed","package":"python-Glances","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"4.5.6-1.1"}]}],"bundled":6}],"products":[{"vendor":"nicolargo","product":"glances"}],"references":[{"url":"https://github.com/nicolargo/glances/security/advisories/GHSA-73wf-9vmv-5pv9","tags":["x_refsource_CONFIRM","exploit","advisory","web","report"]},{"url":"https://github.com/nicolargo/glances/commit/ea4cf2f54f0d961e24aa0b24fff9584bab39db93","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/nicolargo/glances/releases/tag/v4.5.6","tags":["x_refsource_MISC","web"]},{"url":"https://github.com/advisories/GHSA-73wf-9vmv-5pv9","tags":["advisory"]},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/62xxx/CVE-2026-62982.json","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-62982","tags":["advisory"]},{"url":"https://security-tracker.debian.org/tracker/CVE-2026-62982","tags":["advisory"]},{"url":"https://github.com/nicolargo/glances","tags":["package"]},{"url":"https://pypi.org/project/glances","tags":["package"]},{"url":"https://ubuntu.com/security/CVE-2026-62982","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-62982","tags":["report"]},{"url":"","tags":["advisory"]},{"url":"https://www.suse.com/security/cve/CVE-2021-23418","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-62982","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-68517","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-68518","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-68519","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-68520","tags":["web"]}],"sources":{"cve":[{"id":"CVE-2026-62982","title":"Glances: Incomplete fix of CVE-2026-32608: action-template sanitizer is bypassed by nested stat values (process 'cmdline') → OS command injection","description":"Glances is an open-source system cross-platform monitoring tool. From 4.5.2 until 4.5.6, _sanitize_mustache_dict() in glances/actions.py skips nested list and dictionary strings such as process cmdline values, allowing pipe characters to survive chevron.render() and be executed by secure_popen() through administrator-configured action templates. This issue is fixed in 4.5.6.","status":"published","published":"2026-08-17T17:07:49.364Z","modified":"2026-08-17T18:53:15.749Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H","level":"high","assessor":"cna"}],"cwes":["CWE-78"],"updated_at":"2026-11-02T14:20:14.999906Z"}],"euvd":[{"id":"EUVD-2026-60303","description":"Glances is an open-source system cross-platform monitoring tool. From 4.5.2 until 4.5.6, _sanitize_mustache_dict() in glances/actions.py skips nested list and dictionary strings such as process cmdline values, allowing pipe characters to survive chevron.render() and be executed by secure_popen() through administrator-configured action templates. This issue is fixed in 4.5.6.","status":"published","published":"2026-08-17T17:07:49Z","modified":"2026-08-17T18:53:15Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T18:01:48.395378Z"}],"ghsa":[{"id":"GHSA-73wf-9vmv-5pv9","title":"Glances: Incomplete fix of CVE-2026-32608: action-template sanitizer is bypassed by nested stat values (process 'cmdline') → OS command injection","description":"## Summary\nCVE-2026-32608 (\"Command Injection via Process Names in Action Command Templates\") was fixed (commit `5680a5d`) by adding `_sanitize_mustache_dict`, which replaces the shell operators `\u0026\u0026`, `|`, `\u003e\u003e`, `\u003e` with spaces in the values rendered into action command templates.\n\nThe sanitizer only processes **top-level string** values (`if isinstance(v, str)`). Attacker-controlled **nested** values — most notably a process's **`cmdline`, which Glances exposes as a `list`** and which is fully attacker-controlled via argv — are passed through **unsanitized**. Because the Mustache renderer (`chevron`) does **not** HTML-escape the pipe character `|`, a `|` embedded in such a nested value survives into the rendered command and is then interpreted by `secure_popen` (which still interprets `\u0026\u0026`/`|`/`\u003e` by default, `allow_operators=True`), re-introducing the exact command injection the CVE was meant to close.\n\n## Details\nThe fix (`glances/actions.py`):\n```python\n_SHELL_OPERATORS = ('\u0026\u0026', '|', '\u003e\u003e', '\u003e')                     # line 25\n\ndef _sanitize_mustache_dict(mustache_dict):                   # line 28\n    ...\n    for k, v in mustache_dict.items():\n        if isinstance(v, str):                                # line 40  \u003c-- ONLY top-level strings\n            for op in _SHELL_OPERATORS:\n                v = v.replace(op, ' ')\n            safe[k] = v\n        else:\n            safe[k] = v                                       # nested list/dict passed VERBATIM\n    return safe\n```\nRender + sink (`glances/actions.py:104-111`):\n```python\nsafe_dict = _sanitize_mustache_dict(mustache_dict)\ncmd_full  = chevron.render(cmd, safe_dict)                    # chevron does NOT escape '|'\n...\nret = secure_popen(cmd_full)                                 # secure_popen(cmd, allow_operators=True)\n```\n`secure_popen` (`glances/secure.py:17`, default `allow_operators=True`) splits the command by `\u0026\u0026`, then `__secure_popen` interprets `|` (pipe to a new process) and `\u003e` (write output to a file). A surviving `|` therefore launches an attacker-named second process.\n\n**The attacker-controlled nested value — `cmdline`.** The action `mustache_dict` is the per-item plugin stat (`glances/plugins/plugin/model.py:931` `mustache_dict = item`, then `:943` `self.actions.run(..., mustache_dict=mustache_dict)`). For the processlist plugin, each `item` contains `cmdline`, a **list** of the process arguments, set by the attacker simply by launching a process with chosen argv. The sanitizer's `isinstance(v, str)` test skips the list, so its elements reach `chevron.render` unmodified.\n\n**Why the operator survives render.** `chevron`/Mustache HTML-escapes `\u0026 \u003c \u003e \" '` for `{{var}}` (so `\u003e` and `\u0026\u0026` are neutralized) but **does not escape `|`**. A pipe in the (unsanitized) nested value therefore reaches `secure_popen` intact and is interpreted.\n\n**Parent-fix attribution (verified against the real diff of commit `5680a5d` / CVE-2026-32608):** that fix added exactly `_SHELL_OPERATORS`, `_sanitize_mustache_dict`, and the `_sanitize_mustache_dict(mustache_dict)` call — and the sanitizer's docstring explicitly claims to neutralize \"user-controllable data (process names, container names, mount points, etc.)\". It does so only for top-level strings; the list/dict case (`else: safe[k] = v`) was left unsanitized. This is therefore a genuine incomplete-fix gap, not a re-report of the patched (top-level string) vector.\n\n## Proof of Concept\nLab-only, harmless (touches a marker file; non-destructive). Runs the real `glances` chain (`_sanitize_mustache_dict` → `chevron.render` → `secure_popen`) — see `poc/glances_nested_mustache_poc.py`.\n\nAttacker process argv (the only attacker input): `cmdline = ['x', '|touch /tmp/glances_poc_marker', '#']`.\nAdmin action template (renders the offending process's cmdline): `echo ALERT {{#cmdline}}{{.}} {{/cmdline}}`.\n\nObserved (confirmed on develop HEAD `92156d0`/4.5.6 and verified code-identical on v4.5.5):\n```\ncmdline after sanitizer : ['x', '|touch /tmp/glances_poc_marker', '#']   \u003c- pipe survives\ncmd_full -\u003e secure_popen : 'echo ALERT x |touch /tmp/glances_poc_marker # '\n[VULNERABLE] marker created -\u003e /tmp/glances_poc_marker  (command injection executed)\n```\nReplacing `touch /tmp/...` with any command yields arbitrary execution in the Glances process context.\n\n## Preconditions (stated honestly)\n- A configured alert **action** whose command template **renders a nested stat field** (e.g. the process `cmdline` via a `{{#cmdline}}…{{/cmdline}}` section). Templates that render only **flat string** fields (`{{name}}`, `{{value}}`, `{{username}}`, `{{mnt_point}}`) are **not** affected — those values *are* sanitized.\n- Glances running with privilege to enumerate the attacker's process (typically **root** in server/agent monitoring deployments) → privilege boundary crossed (`S:C`).\n\n## Impact\nA local unprivileged user gains OS command execution in the Glances security context (commonly root) — the same impact and threat model as the parent CVE-2026-32608, re-enabled for any action template that renders a nested stat field. The injection is reliable once the (admin-set) template references such a field.\n\n## Suggested fix\n- Sanitize **recursively** — apply the operator stripping to strings inside lists and dicts, not only top-level `str` values.\n- And/or build the templated action as an argument list and run it via `secure_popen(..., allow_operators=False)` / `shell=False` without operator interpretation.\n- And/or also strip the pipe `|` (and treat all `_SHELL_OPERATORS`) on every rendered string regardless of nesting; do not rely on Mustache HTML-escaping (it does not escape `|`).\n\n## Credit\nTa Duc Thien","status":"published","published":"2026-08-17T17:20:24Z","modified":"2026-08-17T17:20:25Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H","level":"high"}],"cwes":["CWE-78"],"updated_at":"2026-11-02T14:41:01.23108Z"}],"nvd":[{"id":"CVE-2026-62982","description":"Glances is an open-source system cross-platform monitoring tool. From 4.5.2 until 4.5.6, _sanitize_mustache_dict() in glances/actions.py skips nested list and dictionary strings such as process cmdline values, allowing pipe characters to survive chevron.render() and be executed by secure_popen() through administrator-configured action templates. This issue is fixed in 4.5.6.","status":"published","published":"2026-08-17T18:17:56.74Z","modified":"2026-10-23T16:10:00.313Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H","level":"high","assessor":"secondary"}],"cwes":["CWE-78"],"updated_at":"2026-11-02T14:12:38.647684Z"}],"osv":[{"id":"CVE-2026-62982","title":"Glances: Incomplete fix of CVE-2026-32608: action-template sanitizer is bypassed by nested stat values (process 'cmdline') → OS command injection","description":"Glances is an open-source system cross-platform monitoring tool. From 4.5.2 until 4.5.6, _sanitize_mustache_dict() in glances/actions.py skips nested list and dictionary strings such as process cmdline values, allowing pipe characters to survive chevron.render() and be executed by secure_popen() through administrator-configured action templates. This issue is fixed in 4.5.6.","status":"published","published":"2026-08-17T17:07:49.364Z","modified":"2026-10-28T02:31:13.884134127Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H","level":"high"}],"cwes":["CWE-78"],"updated_at":"2026-11-02T15:45:13.306117Z"},{"id":"DEBIAN-CVE-2026-62982","description":"Glances is an open-source system cross-platform monitoring tool. From 4.5.2 until 4.5.6, _sanitize_mustache_dict() in glances/actions.py skips nested list and dictionary strings such as process cmdline values, allowing pipe characters to survive chevron.render() and be executed by secure_popen() through administrator-configured action templates. This issue is fixed in 4.5.6.","status":"published","published":"2026-08-17T18:17:56.74Z","modified":"2026-10-24T09:47:24.312357472Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T15:45:57.932517Z"},{"id":"GHSA-73wf-9vmv-5pv9","title":"Glances: Incomplete fix of CVE-2026-32608: action-template sanitizer is bypassed by nested stat values (process 'cmdline') → OS command injection","description":"## Summary\nCVE-2026-32608 (\"Command Injection via Process Names in Action Command Templates\") was fixed (commit `5680a5d`) by adding `_sanitize_mustache_dict`, which replaces the shell operators `\u0026\u0026`, `|`, `\u003e\u003e`, `\u003e` with spaces in the values rendered into action command templates.\n\nThe sanitizer only processes **top-level string** values (`if isinstance(v, str)`). Attacker-controlled **nested** values — most notably a process's **`cmdline`, which Glances exposes as a `list`** and which is fully attacker-controlled via argv — are passed through **unsanitized**. Because the Mustache renderer (`chevron`) does **not** HTML-escape the pipe character `|`, a `|` embedded in such a nested value survives into the rendered command and is then interpreted by `secure_popen` (which still interprets `\u0026\u0026`/`|`/`\u003e` by default, `allow_operators=True`), re-introducing the exact command injection the CVE was meant to close.\n\n## Details\nThe fix (`glances/actions.py`):\n```python\n_SHELL_OPERATORS = ('\u0026\u0026', '|', '\u003e\u003e', '\u003e')                     # line 25\n\ndef _sanitize_mustache_dict(mustache_dict):                   # line 28\n    ...\n    for k, v in mustache_dict.items():\n        if isinstance(v, str):                                # line 40  \u003c-- ONLY top-level strings\n            for op in _SHELL_OPERATORS:\n                v = v.replace(op, ' ')\n            safe[k] = v\n        else:\n            safe[k] = v                                       # nested list/dict passed VERBATIM\n    return safe\n```\nRender + sink (`glances/actions.py:104-111`):\n```python\nsafe_dict = _sanitize_mustache_dict(mustache_dict)\ncmd_full  = chevron.render(cmd, safe_dict)                    # chevron does NOT escape '|'\n...\nret = secure_popen(cmd_full)                                 # secure_popen(cmd, allow_operators=True)\n```\n`secure_popen` (`glances/secure.py:17`, default `allow_operators=True`) splits the command by `\u0026\u0026`, then `__secure_popen` interprets `|` (pipe to a new process) and `\u003e` (write output to a file). A surviving `|` therefore launches an attacker-named second process.\n\n**The attacker-controlled nested value — `cmdline`.** The action `mustache_dict` is the per-item plugin stat (`glances/plugins/plugin/model.py:931` `mustache_dict = item`, then `:943` `self.actions.run(..., mustache_dict=mustache_dict)`). For the processlist plugin, each `item` contains `cmdline`, a **list** of the process arguments, set by the attacker simply by launching a process with chosen argv. The sanitizer's `isinstance(v, str)` test skips the list, so its elements reach `chevron.render` unmodified.\n\n**Why the operator survives render.** `chevron`/Mustache HTML-escapes `\u0026 \u003c \u003e \" '` for `{{var}}` (so `\u003e` and `\u0026\u0026` are neutralized) but **does not escape `|`**. A pipe in the (unsanitized) nested value therefore reaches `secure_popen` intact and is interpreted.\n\n**Parent-fix attribution (verified against the real diff of commit `5680a5d` / CVE-2026-32608):** that fix added exactly `_SHELL_OPERATORS`, `_sanitize_mustache_dict`, and the `_sanitize_mustache_dict(mustache_dict)` call — and the sanitizer's docstring explicitly claims to neutralize \"user-controllable data (process names, container names, mount points, etc.)\". It does so only for top-level strings; the list/dict case (`else: safe[k] = v`) was left unsanitized. This is therefore a genuine incomplete-fix gap, not a re-report of the patched (top-level string) vector.\n\n## Proof of Concept\nLab-only, harmless (touches a marker file; non-destructive). Runs the real `glances` chain (`_sanitize_mustache_dict` → `chevron.render` → `secure_popen`) — see `poc/glances_nested_mustache_poc.py`.\n\nAttacker process argv (the only attacker input): `cmdline = ['x', '|touch /tmp/glances_poc_marker', '#']`.\nAdmin action template (renders the offending process's cmdline): `echo ALERT {{#cmdline}}{{.}} {{/cmdline}}`.\n\nObserved (confirmed on develop HEAD `92156d0`/4.5.6 and verified code-identical on v4.5.5):\n```\ncmdline after sanitizer : ['x', '|touch /tmp/glances_poc_marker', '#']   \u003c- pipe survives\ncmd_full -\u003e secure_popen : 'echo ALERT x |touch /tmp/glances_poc_marker # '\n[VULNERABLE] marker created -\u003e /tmp/glances_poc_marker  (command injection executed)\n```\nReplacing `touch /tmp/...` with any command yields arbitrary execution in the Glances process context.\n\n## Preconditions (stated honestly)\n- A configured alert **action** whose command template **renders a nested stat field** (e.g. the process `cmdline` via a `{{#cmdline}}…{{/cmdline}}` section). Templates that render only **flat string** fields (`{{name}}`, `{{value}}`, `{{username}}`, `{{mnt_point}}`) are **not** affected — those values *are* sanitized.\n- Glances running with privilege to enumerate the attacker's process (typically **root** in server/agent monitoring deployments) → privilege boundary crossed (`S:C`).\n\n## Impact\nA local unprivileged user gains OS command execution in the Glances security context (commonly root) — the same impact and threat model as the parent CVE-2026-32608, re-enabled for any action template that renders a nested stat field. The injection is reliable once the (admin-set) template references such a field.\n\n## Suggested fix\n- Sanitize **recursively** — apply the operator stripping to strings inside lists and dicts, not only top-level `str` values.\n- And/or build the templated action as an argument list and run it via `secure_popen(..., allow_operators=False)` / `shell=False` without operator interpretation.\n- And/or also strip the pipe `|` (and treat all `_SHELL_OPERATORS`) on every rendered string regardless of nesting; do not rely on Mustache HTML-escaping (it does not escape `|`).\n\n## Credit\nTa Duc Thien","status":"published","published":"2026-08-17T17:20:24Z","modified":"2026-08-19T12:55:55.814415461Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H","level":"high"}],"cwes":["CWE-78"],"updated_at":"2026-11-02T15:46:40.308826Z"},{"id":"PYSEC-2026-3666","title":"Glances: Incomplete fix of CVE-2026-32608: action-template sanitizer is bypassed by nested stat values (process 'cmdline') → OS command injection","description":"## Summary\nCVE-2026-32608 (\"Command Injection via Process Names in Action Command Templates\") was fixed (commit `5680a5d`) by adding `_sanitize_mustache_dict`, which replaces the shell operators `\u0026\u0026`, `|`, `\u003e\u003e`, `\u003e` with spaces in the values rendered into action command templates.\n\nThe sanitizer only processes **top-level string** values (`if isinstance(v, str)`). Attacker-controlled **nested** values — most notably a process's **`cmdline`, which Glances exposes as a `list`** and which is fully attacker-controlled via argv — are passed through **unsanitized**. Because the Mustache renderer (`chevron`) does **not** HTML-escape the pipe character `|`, a `|` embedded in such a nested value survives into the rendered command and is then interpreted by `secure_popen` (which still interprets `\u0026\u0026`/`|`/`\u003e` by default, `allow_operators=True`), re-introducing the exact command injection the CVE was meant to close.\n\n## Details\nThe fix (`glances/actions.py`):\n```python\n_SHELL_OPERATORS = ('\u0026\u0026', '|', '\u003e\u003e', '\u003e')                     # line 25\n\ndef _sanitize_mustache_dict(mustache_dict):                   # line 28\n    ...\n    for k, v in mustache_dict.items():\n        if isinstance(v, str):                                # line 40  \u003c-- ONLY top-level strings\n            for op in _SHELL_OPERATORS:\n                v = v.replace(op, ' ')\n            safe[k] = v\n        else:\n            safe[k] = v                                       # nested list/dict passed VERBATIM\n    return safe\n```\nRender + sink (`glances/actions.py:104-111`):\n```python\nsafe_dict = _sanitize_mustache_dict(mustache_dict)\ncmd_full  = chevron.render(cmd, safe_dict)                    # chevron does NOT escape '|'\n...\nret = secure_popen(cmd_full)                                 # secure_popen(cmd, allow_operators=True)\n```\n`secure_popen` (`glances/secure.py:17`, default `allow_operators=True`) splits the command by `\u0026\u0026`, then `__secure_popen` interprets `|` (pipe to a new process) and `\u003e` (write output to a file). A surviving `|` therefore launches an attacker-named second process.\n\n**The attacker-controlled nested value — `cmdline`.** The action `mustache_dict` is the per-item plugin stat (`glances/plugins/plugin/model.py:931` `mustache_dict = item`, then `:943` `self.actions.run(..., mustache_dict=mustache_dict)`). For the processlist plugin, each `item` contains `cmdline`, a **list** of the process arguments, set by the attacker simply by launching a process with chosen argv. The sanitizer's `isinstance(v, str)` test skips the list, so its elements reach `chevron.render` unmodified.\n\n**Why the operator survives render.** `chevron`/Mustache HTML-escapes `\u0026 \u003c \u003e \" '` for `{{var}}` (so `\u003e` and `\u0026\u0026` are neutralized) but **does not escape `|`**. A pipe in the (unsanitized) nested value therefore reaches `secure_popen` intact and is interpreted.\n\n**Parent-fix attribution (verified against the real diff of commit `5680a5d` / CVE-2026-32608):** that fix added exactly `_SHELL_OPERATORS`, `_sanitize_mustache_dict`, and the `_sanitize_mustache_dict(mustache_dict)` call — and the sanitizer's docstring explicitly claims to neutralize \"user-controllable data (process names, container names, mount points, etc.)\". It does so only for top-level strings; the list/dict case (`else: safe[k] = v`) was left unsanitized. This is therefore a genuine incomplete-fix gap, not a re-report of the patched (top-level string) vector.\n\n## Proof of Concept\nLab-only, harmless (touches a marker file; non-destructive). Runs the real `glances` chain (`_sanitize_mustache_dict` → `chevron.render` → `secure_popen`) — see `poc/glances_nested_mustache_poc.py`.\n\nAttacker process argv (the only attacker input): `cmdline = ['x', '|touch /tmp/glances_poc_marker', '#']`.\nAdmin action template (renders the offending process's cmdline): `echo ALERT {{#cmdline}}{{.}} {{/cmdline}}`.\n\nObserved (confirmed on develop HEAD `92156d0`/4.5.6 and verified code-identical on v4.5.5):\n```\ncmdline after sanitizer : ['x', '|touch /tmp/glances_poc_marker', '#']   \u003c- pipe survives\ncmd_full -\u003e secure_popen : 'echo ALERT x |touch /tmp/glances_poc_marker # '\n[VULNERABLE] marker created -\u003e /tmp/glances_poc_marker  (command injection executed)\n```\nReplacing `touch /tmp/...` with any command yields arbitrary execution in the Glances process context.\n\n## Preconditions (stated honestly)\n- A configured alert **action** whose command template **renders a nested stat field** (e.g. the process `cmdline` via a `{{#cmdline}}…{{/cmdline}}` section). Templates that render only **flat string** fields (`{{name}}`, `{{value}}`, `{{username}}`, `{{mnt_point}}`) are **not** affected — those values *are* sanitized.\n- Glances running with privilege to enumerate the attacker's process (typically **root** in server/agent monitoring deployments) → privilege boundary crossed (`S:C`).\n\n## Impact\nA local unprivileged user gains OS command execution in the Glances security context (commonly root) — the same impact and threat model as the parent CVE-2026-32608, re-enabled for any action template that renders a nested stat field. The injection is reliable once the (admin-set) template references such a field.\n\n## Suggested fix\n- Sanitize **recursively** — apply the operator stripping to strings inside lists and dicts, not only top-level `str` values.\n- And/or build the templated action as an argument list and run it via `secure_popen(..., allow_operators=False)` / `shell=False` without operator interpretation.\n- And/or also strip the pipe `|` (and treat all `_SHELL_OPERATORS`) on every rendered string regardless of nesting; do not rely on Mustache HTML-escaping (it does not escape `|`).\n\n## Credit\nTa Duc Thien","status":"published","published":"2026-08-19T11:56:26.862162Z","modified":"2026-08-19T12:45:05.477492048Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T15:52:56.847083Z"},{"id":"UBUNTU-CVE-2026-62982","description":"Glances is an open-source system cross-platform monitoring tool. From 4.5.2 until 4.5.6, _sanitize_mustache_dict() in glances/actions.py skips nested list and dictionary strings such as process cmdline values, allowing pipe characters to survive chevron.render() and be executed by secure_popen() through administrator-configured action templates. This issue is fixed in 4.5.6.","status":"published","published":"2026-08-17T18:17:00Z","modified":"2026-08-19T13:32:28.743665905Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T16:56:43.630667Z"},{"id":"openSUSE-SU-2026:11674-1","title":"glances-common-4.5.6-1.1 on GA media","description":"These are all security issues fixed in the glances-common-4.5.6-1.1 package on the GA media of openSUSE Tumbleweed.","status":"published","published":"2026-09-02T00:00:00Z","modified":"2026-09-03T10:00:08.662507132Z","updated_at":"2026-11-02T16:58:39.516824Z"}]}}
