GitHub Security Advisory: GHSA-hhcg-r27j-fhv9
Package: Glances (PIP)
Severity: MODERATE (CVSS 5.9)
CWE: CWE-346: Origin Validation Error
Vulnerable versions: < 4.5.2
Patched in: 4.5.2

Summary: Glances's REST/WebUI Lacks Host Validation and Remains Exposed to DNS Rebinding

Details:
## Summary

Glances recently added DNS rebinding protection for the MCP endpoint, but the main REST/WebUI FastAPI application still accepts arbitrary `Host` headers and does not apply `TrustedHostMiddleware` or an equivalent host allowlist.

As a result, the REST API, WebUI, and token endpoint remain reachable through attacker-controlled domains in classic DNS rebinding scenarios. Once the victim browser has rebound the attacker domain to the Glances service, same-origin policy no longer protects the API because the browser considers the rebinding domain to be the origin.

This is a distinct issue from the previously reported default CORS weakness. CORS is not required for exploitation here because DNS rebinding causes the victim browser to treat the malicious domain as same-origin with the rebinding target.

## Details

The MCP endpoint now has explicit host-based transport security:

```python
# glances/outputs/glances_mcp.py
self.mcp_allowed_hosts = ["localhost", "127.0.0.1"]
...
return TransportSecuritySettings(
    allowed_hosts=allowed_hosts,
    allowed_origins=allowed_origins,
)
```

However, the main FastAPI application for REST/WebUI/token routes is initialized without any host validation middleware:

```python
# glances/outputs/glances_restful_api.py
self._app = FastAPI(default_response_class=GlancesJSONResponse)
...
self._app.add_middleware(
    CORSMiddleware,
    allow_origins=config.get_list_value('outputs', 'cors_origins', default=["*"]),
    allow_credentials=config.get_bool_value('outputs', 'cors_credentials', default=True),
    allow_methods=config.get_list_value('outputs', 'cors_methods', default=["*"]),
    allow_headers=config.get_list_value('outputs', 'cors_headers', default=["*"]),
)
...
if self.args.password and self._jwt_handler is not None:
    self._app.include_router(self._token_router())
self._app.include_router(self._router())
```

There is no `TrustedHostMiddleware`, no comparison against the configured bind host, and no allowlist enforcement for HTTP `Host` values on the REST/WebUI surface.

The default bind configuration also exposes the service on all interfaces:

```python
# glances/main.py
parser.add_argument(
    '-B',
    '--bind',
    default='0.0.0.0',
    dest='bind_address',
    help='bind server to the given IPv4/IPv6 address or hostname',
)
```

This combination means the HTTP service will typically be reachable from the victim machine under an attacker-selected hostname once DNS is rebound to the Glances listener.

The token endpoint is also mounted on the same unprotected FastAPI app:

```python
# glances/outputs/glances_restful_api.py
def _token_router(self) -> APIRouter:
    ...
    router.add_api_route(f'{base_path}/token', self._api_token, methods=['POST'], dependencies=[])
```

## Why This Is Exploitable

In a DNS rebinding attack:

1. The attacker serves JavaScript from `https://attacker.example`.
2. The victim visits that page while a Glances instance is reachable on the victim network.
3. The