Commit Graph

7281 Commits

Author SHA1 Message Date
github-actions[bot]
82c25fb74b chore(v5): weekly merge from develop (2026-06-01) 2026-06-01 07:52:40 +00:00
nicolargo
1f5aead12c Merge branch 'issue3559' into develop 2026-05-31 17:35:59 +02:00
nicolargo
2e5ab02bda Get back to default ThreadedIterableStreamer.sleep_duration to 0.1 second 2026-05-31 17:35:44 +02:00
nicolargo
e68e9f4452 Add unit test to containers/docker plugin 2026-05-31 17:34:25 +02:00
nicolargo
2353e49655 Make only one API call for multiple containers (use sparse=True option). Also correct behavor for Podman and LXD. 2026-05-31 17:33:37 +02:00
nicolargo
04419de50a Correct display issue on start with all perCPU = 100% 2026-05-30 15:56:23 +02:00
nicolargo
4dbc015214 Correct display issue on start with CPU = 100% 2026-05-30 15:37:04 +02:00
nicolargo
87eb1bdc9f Merge branch 'develop' into develop-v5 2026-05-30 11:00:08 +02:00
nicolargo
963e5445f0 Add first batch of hotkey management in the TUI 2026-05-30 10:59:57 +02:00
nicolargo
d050ab4151 Merge branch 'issue3559' into develop 2026-05-30 09:18:23 +02:00
nicolargo
476a26defc Try to reduce the time between two containers when stats are collected - #3559 2026-05-30 09:18:08 +02:00
nicolargo
f40f6f136d Merge branch 'develop-v5' of github.com:nicolargo/glances into develop-v5 2026-05-23 19:45:26 +02:00
nicolargo
23ffad1b64 Merge branch 'develop' into develop-v5 2026-05-23 19:45:17 +02:00
nicolargo
e52e84f354 Add a short-cut to not generate alert for some plugin (first candidate is processlist) 2026-05-23 19:44:52 +02:00
nicolargo
4f399c41b2 Merge branch '20086080-Issue-3555_load_additional_plugins' into develop 2026-05-23 15:50:00 +02:00
nicolargo
2afc533d67 Merge branch 'Issue-3555_load_additional_plugins' of github.com:20086080/glances into 20086080-Issue-3555_load_additional_plugins 2026-05-23 15:48:42 +02:00
nicolargo
07080cdca4 Update WebUI, requirements and docs 2026-05-23 15:42:02 +02:00
nicolargo
3fdd03964b Merge branch 'GHSA-v5r2-qh84-fjx5' into develop 2026-05-23 12:27:38 +02:00
nicolargo
ff3eec3295 Command Injection via KVM/QEMU VM Domain Names in glances/plugins/vms/engines/virsh.py - CVE-2026-46606 2026-05-23 12:27:19 +02:00
nicolargo
e1f6c387dd Command Injection via KVM/QEMU VM Domain Names in glances/plugins/vms/engines/virsh.py - CVE-2026-46606 2026-05-23 12:27:00 +02:00
nicolargo
6986c382d9 Merge branch 'GHSA-9837-48hr-q32j' into develop 2026-05-23 11:57:50 +02:00
nicolargo
cf14166fbe test(outdated): json round-trip and graceful migration from legacy pickle cache
Cover the non-RCE behaviour of the new JSON cache:
- round-trip: written file is valid JSON, re-read produces equivalent dict
- legacy pickle: a pre-fix pickle cache is treated as a cache miss, not
  a crash (upgrade path)
- expiry: caches older than 7 days are invalidated
- version skew: caches written by a different installed version are
  invalidated
- first run: a missing file is not an error
2026-05-23 11:52:53 +02:00
nicolargo
622994add7 fix(outdated): replace pickle with json for version cache (GHSA-9837-48hr-q32j)
The version-check cache at $XDG_CACHE_HOME/glances/glances-version.db is
read at every Glances startup via pickle.load() — an execution-capable
deserialization format. Any process able to write that path (local user
on a shared host, sibling container on a shared volume, symlink race
during first run) could plant a pickle whose __reduce__ runs arbitrary
code as the Glances user, including root in typical deployments.

Switch to json for both load and save. The stored payload is trivial:
two strings plus a timestamp that round-trips via isoformat(). Any
unreadable, malformed, or legacy-pickle file is caught by the existing
exception handler and treated as a cache miss — the next PyPI refresh
overwrites it with a JSON file. No user-visible behaviour change.

The pickle module is removed from the imports — it has no other use in
this file.

Mitigates CVE-2026-46607.
2026-05-23 11:51:36 +02:00
nicolargo
7098478c39 test(outdated): failing test — malicious pickle cache must not execute (CVE-2026-46607)
Regression test for GHSA-9837-48hr-q32j: glances/outdated.py reads its
version-check cache file via pickle.load(), a deserialization format
that executes arbitrary callables embedded via __reduce__.

The test plants a poisoned pickle at the cache path and asserts that
_load_cache() does NOT trigger the embedded callable. Against the
current (vulnerable) code this fails because the payload fires before
the TypeError is raised on the unrelated dict subscript.

The fix in the next commit replaces pickle with json, which is a passive
data format.
2026-05-23 11:50:55 +02:00
nicolargo
74c5352ebc Merge branch 'GHSA-87qc-fj39-wccr' into develop 2026-05-23 11:40:35 +02:00
nicolargo
0de3b8f875 XML-RPC Multi-Origin CORS Configuration Silently Falls Back to Wildcard - CVE-2026-46608 2026-05-23 11:40:20 +02:00
nicolargo
8eeacd8856 Merge branch 'GHSA-w856-8p3r-p338' into develop 2026-05-23 10:04:50 +02:00
nicolargo
16c7ca8e13 Update other glances.conf file 2026-05-23 10:04:32 +02:00
nicolargo
4976bd7509 docs(quickstart): document xmlrpc_allowed_hosts DNS rebinding protection
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 09:56:46 +02:00
nicolargo
d9316dfac2 docs(conf): document xmlrpc_allowed_hosts in glances.conf
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 09:56:28 +02:00
nicolargo
cbc22e77d4 feat(server): warn at startup when XML-RPC server has no Host allowlist
Mirrors the existing REST/WebUI warning style. Makes unprotected
XML-RPC deployments visible to operators without changing default
behaviour (no enforcement).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 09:56:15 +02:00
nicolargo
cad6f985a5 test(xmlrpc): port stripping and missing-Host edge cases
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 09:53:06 +02:00
nicolargo
8e6c9c955c test(xmlrpc): wildcard Host patterns via fnmatch
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 09:52:30 +02:00
nicolargo
575dc7e81b test(xmlrpc): allowlisted Host returns 200
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 09:51:58 +02:00
nicolargo
5961e0b507 fix(server): validate Host header in XML-RPC server (GHSA-w856-8p3r-p338)
Add opt-in DNS rebinding protection to the XML-RPC server via a new
xmlrpc_allowed_hosts config key in [outputs]. When set, the handler
rejects requests whose Host header does not match any of the listed
patterns (fnmatch wildcards supported). Validation runs before
authentication so spoofed Host values are rejected regardless of
credentials.

Default behaviour is unchanged (no allowlist = no filtering). A
startup warning is added in a follow-up commit to make unprotected
deployments visible to operators.

Mitigates CVE-2026-46611.
2026-05-23 09:51:25 +02:00
nicolargo
b88dd7bcfd test(xmlrpc): failing test — spoofed Host should be rejected (CVE-2026-46611)
Adds a second test server bound to a config that enables xmlrpc_allowed_hosts,
plus the failing assertion that a spoofed Host header returns 400. The fix in
glances/server.py follows in the next commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 09:50:40 +02:00
nicolargo
b2965cca96 test(xmlrpc): lock in current permissive default (regression baseline)
This test passes on the unpatched server and proves the CVE-2026-46611
vulnerability exists today: a spoofed Host header is accepted.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 09:49:43 +02:00
nicolargo
01437d61e2 test(xmlrpc): scaffold for Host header validation tests
Re-creates tests/test_xmlrpc.py (deleted symlink) with a pytest module
modelled on test_restful.py: subprocess-launched server and a helper
to POST XML-RPC calls with a controllable Host header. Restores the
existing 'make test-xmlrpc' Makefile target.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 09:48:47 +02:00
nicolargo
8b6cab83e8 docs(plan): implementation plan for GHSA-w856-8p3r-p338 XML-RPC fix
11-task TDD plan covering test scaffold, regression baseline,
parse_request Host validation, wildcard/port/missing-Host edge
cases, startup warning, conf entry, docs and lint/format check.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 09:43:23 +02:00
nicolargo
bcbeae7af6 docs(spec): design for GHSA-w856-8p3r-p338 XML-RPC Host validation
Design document for CVE-2026-46611 patch: add opt-in Host header
validation to the XML-RPC server via a new xmlrpc_allowed_hosts
config key, with permissive default and startup warning (mirrors
the REST/WebUI mitigation pattern).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 09:38:43 +02:00
Nicolas Hennion
2cfc64e8e9 Update MCP configuration instructions in mcp.rst
Added instructions for configuring Glances MCP from the Claude command line.
2026-05-21 17:18:50 +02:00
20086080
bcc18b4ab3 Fix : Codacy 2026-05-21 03:06:41 +00:00
20086080
389b6d45bb Fix : Codacy 2026-05-21 02:57:23 +00:00
20086080
c3a8fb2f05 Test : Unit tests 2026-05-21 02:22:17 +00:00
20086080
86f821340d Doc : Comments 2026-05-20 15:23:45 +00:00
20086080
b71094adc5 Refactor : load_additional_plugins seperation of concerns 2026-05-20 15:16:45 +00:00
github-actions[bot]
0ac0b7f779 chore(v5): weekly merge from develop (2026-05-18) 2026-05-18 07:29:57 +00:00
nicolargo
b31c07eb3a perf(v5): coalesce per-partition fs calls + skip dead work in pipeline
Investigation flagged 88 epoll wakes/sec inside the asyncio scheduler
loop — vs the ~5/sec expected from 10 plugins on a 2s refresh. Root
cause: ``fs.model_v5._grab_stats`` issued one
``await asyncio.to_thread(psutil.disk_usage, mnt)`` per partition.
Snap-heavy hosts routinely expose 70+ mountpoints, producing 70+
thread-pool submissions + completions per cycle, each generating a
loop wake. Coalesce the whole walk inside a single ``to_thread`` so
the asyncio loop sees exactly one wake per fs cycle. Drop:
  epoll.poll  701/8s → 138/8s   (~88/s → ~17/s)

Two complementary base_v5 wins on top:

1) Hot-loop precomputation at __init__:
   ``_rate_fields``, ``_watched_fields`` and ``_allowed_field_names``
   are cached once. ``_compute_rates_in_dict``, ``_compute_levels_for_item``,
   ``_precompute_plugin_thresholds``, ``_scan_pk_override_fields`` and
   ``_remove_parameters`` now skip the per-call ``.items()`` + flag
   check. processlist with 580 procs × 17 fields × 4 hot loops used to
   incur ~40k pointless lookups per cycle.

2) Skip ``_snapshot_raw`` entirely when no field is a rate counter:
   the snapshot is only consulted by ``_transform_gauge``, which is a
   no-op for plugins without ``rate: True`` fields. processlist (no
   rate fields, 580 items) saves ~580 dict allocations per cycle.

10 s scheduler run (10 plugins, 580 procs, 71 fs mountpoints, idle):
  before today:     4.0% CPU
  after fs fix:     3.7% CPU
  after pipeline:   3.1% CPU
v4 sim (raw psutil + engine, sequential): 2.6% CPU
→ v5↔v4 gap closes to ~0.5pp on a snap-heavy host.

Suite v5: 1370+30 green, lint clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 18:44:54 +02:00
nicolargo
ef962e2638 perf(v5): close v4↔v5 CPU gap on large process lists
Three orthogonal wins on the v5 hot path that together close most of the
v4↔v5 CPU gap observed when running both side-by-side with the
processlist plugin enabled:

1) alerts.ingest_plugin — skip min_duration lookup on stable observations
   For processlist with 580 procs × 2 stable ok-levels = 1160 obs/cycle,
   _reconcile already took a fast-path when observed == committed_level
   — but only AFTER paying for _min_duration_for (up to 5 config reads
   per call). Short-circuit before the lookup; book-keep has_committed
   and fall through so the steady-state repeat-action dispatch still
   runs for non-ok committed levels.
   Saves ~5800 config reads/cycle.

2) TUI thread — Event.wait instead of polling sleep
   _sleep_responsive was looping time.sleep(0.05) 20×/s just to check
   the stop flag. threading.Event.wait(timeout) blocks until either the
   timeout expires or stop() flips it — no polling, no kernel wakeups
   between repaints. Same q/ESC latency (bounded by refresh_interval —
   getch() is polled at the top of the loop, not during the sleep).

3) TUI refresh interval default = plugin refresh_time
   Previously: tui_refresh_interval defaulted to 1.0s while plugin
   refresh_time defaulted to 2.0s — the TUI repainted the same data
   twice between every update. Default the TUI cadence to
   [global] refresh_time. Operators who want a snappier UI can still
   override via [outputs] tui_refresh_interval=.

Profile delta (10 cycles, 580 procs, full multi-plugin pipeline with
alerts ingest, 2s refresh):
  before:  126 ms/cycle
  after:   109 ms/cycle
  plus halved TUI wake rate → less idle-CPU between cycles.

Suite v5: 1370+30 green, lint clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 18:27:15 +02:00
nicolargo
b8e10a2ef2 perf(v5): hoist plugin-level thresholds out of per-item loop
processlist with ~580 processes burned ~80 ms/cycle in
``_compute_levels_for_item`` — 1158 calls to ``read_thresholds_categorical``
+ 9264 ``_parse_csv_tokens`` per cycle, all re-reading identical
plugin-wide configuration for every (item, field) pair.

base_v5._derived_parameters now precomputes plugin-level thresholds
(both numeric and categorical) once per cycle, then layers per-item
``<pk>_<field>_<level>`` overrides only when a section scan reports
such keys exist. The common case (no pk overrides — every plugin
except network in practice) reuses the precomputed mapping with a
single dict lookup per item.

GlancesConfigV5 grows ``section_keys(section)`` so the scanner can
introspect declared keys without forcing the read through
``as_dict()`` (which deep-copies the whole config).

Profile delta (10 cycles, 580 procs):
  ``_transform`` cumtime  91 ms/cycle → 25 ms/cycle (-73%)
  cycle total         235 ms/cycle → 165 ms/cycle (-30%)
  ``read_thresholds_categorical``  1158 calls → 2 calls per cycle

Suite v5: 1370+30 green, lint clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 18:11:03 +02:00