VYPR
\n```\n\n3. Victim visits `http://attacker.example.com` in their browser.\n4. After TTL expiry, the attacker's DNS server responds with `127.0.0.1`.\n5. The browser's `fetch()` call is sent to `127.0.0.1:61209` with `Host: attacker.example.com`; the XML-RPC server accepts it.\n6. The `Access-Control-Allow-Origin: *` header (see companion advisory) allows the browser to read the response body.\n7. The attacker receives the complete system monitoring snapshot.\n\nTools that simplify DNS rebinding for research/testing include:\n- [Singularity](https://github.com/nccgroup/singularity)\n- [rbndr.us](https://rbndr.us)\n\n**Step 5 — Confirm absence of Host check in source**\n\n```python\nimport sys, inspect\nsys.path.insert(0, '/path/to/glances') # adjust to local clone\nimport glances.server as s\n\nsrc = inspect.getsource(s.GlancesXMLRPCHandler)\nprint('Host check present:', 'allowed_hosts' in src or 'Host' in src)\n# Host check present: False\n```\n\n---\n\n### Impact\n\n**Vulnerability type:** Insufficient Verification of Data Authenticity / DNS Rebinding (CWE-350)\n\n**Who is impacted:** Any user whose browser can reach a Glances XML-RPC server and who can be lured to visit an attacker controlled web page. This includes deployments where:\n\n- Glances is bound to `127.0.0.1` (loopback) — DNS rebinding bypasses the loopback restriction.\n- Glances is bound to a LAN IP — any browser on that LAN is at risk.\n- Glances is exposed on a public IP — any browser on the internet is at risk.\n\n**Data exposed through the XML-RPC API** includes: hostname, OS and kernel version, full process list with command-line arguments (frequently containing API keys, database passwords, and access tokens passed as environment variables or CLI flags), CPU/memory/disk/network statistics, open file descriptors, listening ports, and Docker/Kubernetes container metadata.\n\n**Impact:**\n- **Confidentiality:** High — complete system monitoring data readable remotely without credentials.\n- **Integrity:** None — read-only XML-RPC API.\n- **Availability:** None — no denial-of-service component.\n\nThe attack is amplified by the companion CORS wildcard issue (vuln03): without `Access-Control-Allow-Origin: *`, the browser would still block the response read. Both issues must be fixed together for effective remediation.\n\n---\n\n### Suggested Fix\n\n**Option 1 — Add Host validation to the XML-RPC handler (preferred)**\n\nAdd a `webui_allowed_hosts` (or new `xmlrpc_allowed_hosts`) configuration key, and validate the `Host` header in `GlancesXMLRPCHandler`:\n\n```python\n# server.py\nclass GlancesXMLRPCHandler(SimpleXMLRPCRequestHandler, GlancesAPI):\n\n allowed_hosts: list[str] = [] # populated from config\n\n def parse_request(self) -> bool:\n if not super().parse_request():\n return False\n if self.allowed_hosts:\n host = self.headers.get('Host', '').split(':')[0]\n if host not in self.allowed_hosts:\n self.send_error(400, 'Bad Request: invalid Host header')\n return False\n return True\n```\n\nPopulate `allowed_hosts` from the existing `webui_allowed_hosts` config key (already used by the REST server), so operators have a single knob.\n\n**Option 2 — Deprecate and remove the XML-RPC server**\n\nThe XML-RPC server is a legacy interface. The REST API (`glances -w`) provides a superset of functionality, is actively maintained, and has all current security controls. Deprecating the XML-RPC server in the next major release and directing users to the REST API would eliminate this attack surface entirely.\n\n---\n\n### Responsible Disclosure\nThe AFINE Team is committed to responsible / coordinated disclosure. The AFINE Team will not publish details of this vulnerability or release exploit code publicly until a fix has been released, or 90 days have elapsed from the date of this report, whichever comes first. \n---\n\n### Credits\n\nThis issue was identified by Michał Majchrowicz and Marcin Wyczechowski, members of the AFINE Team.\n\n---","additionalType":"https://schema.org/SoftwareApplication","sameAs":["https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-46611"]},"keywords":"CVE-2026-46611, medium, CWE-346, CWE-350, Nicolargo Glances","mentions":[{"@type":"SoftwareApplication","name":"Glances","applicationCategory":"SecurityApplication","publisher":{"@type":"Organization","name":"Nicolargo"}}],"isAccessibleForFree":true},{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://portal.vyprsec.ai/"},{"@type":"ListItem","position":2,"name":"CVEs","item":"https://portal.vyprsec.ai/cves"},{"@type":"ListItem","position":3,"name":"CVE-2026-46611","item":"https://portal.vyprsec.ai/cves/CVE-2026-46611"}]}]}
Medium severityNVD Advisory· Published Jun 22, 2026

Glances: XML-RPC Server Missing Host Header Validation Enables DNS Rebinding Attack

CVE-2026-46611

Description

Summary

The Glances XML-RPC server (glances -s, implemented in glances/server.py) does not validate the HTTP Host header, leaving it vulnerable to DNS rebinding attacks. CVE-2026-32632 (patched in 4.5.2) added TrustedHostMiddleware to the REST/WebUI server; the MCP server has had equivalent protection since 4.5.1. The XML-RPC server received neither fix and has no allowed-hosts configuration key. Combined with the unrestricted Access-Control-Allow-Origin: * header (see companion advisory for CVE-2026-33533 and its incomplete fix), an attacker can exploit DNS rebinding to exfiltrate the full system monitoring dataset from a victim's browser.

---

Details

Affected component: glances/server.pyGlancesXMLRPCHandler / GlancesXMLRPCServer

Direct URL (commit 04579778e733d705898a169e049dc84772c852da): - https://github.com/nicolargo/glances/blob/04579778e733d705898a169e049dc84772c852da/glances/server.py

Contrast — patched backends: - https://github.com/nicolargo/glances/blob/04579778e733d705898a169e049dc84772c852da/glances/outputs/glances_restful_api.py - https://github.com/nicolargo/glances/blob/04579778e733d705898a169e049dc84772c852da/glances/outputs/glances_mcp.py

The GlancesXMLRPCHandler class inherits from Python's xmlrpc.server.SimpleXMLRPCRequestHandler and does not override parse_request() to inspect or validate the Host header.

Contrast this with the two other Glances server backends, both of which received host-validation hardening:

REST / WebUI server (glances/outputs/glances_restful_api.py) — patched in 4.5.2:

# glances_restful_api.py
if self.webui_allowed_hosts:
    self._app.add_middleware(
        TrustedHostMiddleware,
        allowed_hosts=self.webui_allowed_hosts,
    )

MCP server (glances/outputs/glances_mcp.py) — protected since 4.5.1:

# glances_mcp.py
TransportSecuritySettings(
    allowed_hosts=self.mcp_allowed_hosts,
    ...
)

XML-RPC server (glances/server.py) — no equivalent exists:

class GlancesXMLRPCHandler(SimpleXMLRPCRequestHandler, GlancesAPI):
    # No Host header check; any Host value is accepted
    rpc_paths = ('/RPC2',)
    ...

There is no xmlrpc_allowed_hosts (or equivalent) configuration key in glances.conf, and the server ignores the Host header on every incoming request.

Confirmed on: x86_64 Linux, Python 3.13, Glances 4.5.5_dev1 (commit 04579778e733d705898a169e049dc84772c852da).

Test results:

| Server type | Host header | HTTP status | Data returned | |-------------|----------------------|-------------|---------------| | XML-RPC | attacker.example.com | 200 OK | Yes — VULNERABLE | | XML-RPC | 127.0.0.1:61209 | 200 OK | Yes (baseline) | | REST API | attacker.example.com | 400 Bad Request | No — patched |

---

PoC

Attack overview

DNS rebinding breaks the browser Same-Origin Policy by making attacker.example.com temporarily resolve to the target's IP address (e.g. 127.0.0.1). From that point the victim's browser treats the attacker's page as same-origin with http://attacker.example.com:61209/RPC2, forwarding the attacker-controlled Host header to the local Glances XML-RPC server, which accepts it without validation.

Special configuration required

No special glances.conf settings are needed. The vulnerability is present in a default Glances XML-RPC server start (glances -s). For the comparison test (Step 3) the REST server must also be started; that step requires Glances to be installed with web dependencies (pip install "glances[web]").

---

Step 1 — Start the Glances XML-RPC server

glances -s -p 61209

Step 2 — Confirm the server accepts an arbitrary Host header

curl -s -D - -X POST "http://127.0.0.1:61209/RPC2" \
     -H "Host: attacker.example.com" \
     -H "Content-Type: text/plain" \
     -d '<?xml version="1.0"?>
         getAllPlugins'

Expected result (secure): HTTP/1.0 400 Bad Request Actual result: HTTP/1.0 200 OK with full XML-RPC response body.

Step 3 — Confirm the REST API is patched (comparison)

# Start REST server with the same machine as allowed host:
glances -w -p 61210 --webui-port 61210

curl -s -o /dev/null -w "%{http_code}\n" \
     "http://127.0.0.1:61210/api/4/status" \
     -H "Host: attacker.example.com"
# Returns: 400   (TrustedHostMiddleware rejects the spoofed Host)

Step 4 — Full DNS rebinding exploitation (real-world path)

  1. Attacker registers attacker.example.com with a low-TTL (1 second) DNS record initially pointing to their own server IP.
  2. Attacker serves the following page from http://attacker.example.com:

  1. Victim visits http://attacker.example.com in their browser.
  2. After TTL expiry, the attacker's DNS server responds with 127.0.0.1.
  3. The browser's fetch() call is sent to 127.0.0.1:61209 with Host: attacker.example.com; the XML-RPC server accepts it.
  4. The Access-Control-Allow-Origin: * header (see companion advisory) allows the browser to read the response body.
  5. The attacker receives the complete system monitoring snapshot.

Tools that simplify DNS rebinding for research/testing include: - Singularity - rbndr.us

Step 5 — Confirm absence of Host check in source

import sys, inspect
sys.path.insert(0, '/path/to/glances')   # adjust to local clone
import glances.server as s

src = inspect.getsource(s.GlancesXMLRPCHandler)
print('Host check present:', 'allowed_hosts' in src or 'Host' in src)
# Host check present: False

---

Impact

Vulnerability type: Insufficient Verification of Data Authenticity / DNS Rebinding (CWE-350)

Who is impacted: Any user whose browser can reach a Glances XML-RPC server and who can be lured to visit an attacker controlled web page. This includes deployments where:

  • Glances is bound to 127.0.0.1 (loopback) — DNS rebinding bypasses the loopback restriction.
  • Glances is bound to a LAN IP — any browser on that LAN is at risk.
  • Glances is exposed on a public IP — any browser on the internet is at risk.

Data exposed through the XML-RPC API includes: hostname, OS and kernel version, full process list with command-line arguments (frequently containing API keys, database passwords, and access tokens passed as environment variables or CLI flags), CPU/memory/disk/network statistics, open file descriptors, listening ports, and Docker/Kubernetes container metadata.

Impact: - Confidentiality: High — complete system monitoring data readable remotely without credentials. - Integrity: None — read-only XML-RPC API. - Availability: None — no denial-of-service component.

The attack is amplified by the companion CORS wildcard issue (vuln03): without Access-Control-Allow-Origin: *, the browser would still block the response read. Both issues must be fixed together for effective remediation.

---

Suggested

Fix

Option 1 — Add Host validation to the XML-RPC handler (preferred)

Add a webui_allowed_hosts (or new xmlrpc_allowed_hosts) configuration key, and validate the Host header in GlancesXMLRPCHandler:

# server.py
class GlancesXMLRPCHandler(SimpleXMLRPCRequestHandler, GlancesAPI):

    allowed_hosts: list[str] = []   # populated from config

    def parse_request(self) -> bool:
        if not super().parse_request():
            return False
        if self.allowed_hosts:
            host = self.headers.get('Host', '').split(':')[0]
            if host not in self.allowed_hosts:
                self.send_error(400, 'Bad Request: invalid Host header')
                return False
        return True

Populate allowed_hosts from the existing webui_allowed_hosts config key (already used by the REST server), so operators have a single knob.

Option 2 — Deprecate and remove the XML-RPC server

The XML-RPC server is a legacy interface. The REST API (glances -w) provides a superset of functionality, is actively maintained, and has all current security controls. Deprecating the XML-RPC server in the next major release and directing users to the REST API would eliminate this attack surface entirely.

---

Responsible

Disclosure The AFINE Team is committed to responsible / coordinated disclosure. The AFINE Team will not publish details of this vulnerability or release exploit code publicly until a fix has been released, or 90 days have elapsed from the date of this report, whichever comes first. ---

Credits

This issue was identified by Michał Majchrowicz and Marcin Wyczechowski, members of the AFINE Team.

---

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
glancesPyPI
< 4.5.54.5.5

Affected products

1

Patches

Vulnerability mechanics

AI mechanics synthesis has not run for this CVE yet.

References

3

News mentions

0

No linked articles in our index yet.