PT-2026-25847 · Pypi · Glance

Published

2026-03-16

·

Updated

2026-03-16

·

CVE-2026-32609

CVSS v3.1
7.5
VectorAV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

Summary

The GHSA-gh4x fix (commit 5d3de60) addressed unauthenticated configuration secrets exposure on the
/api/v4/config
endpoints by introducing
as dict secure()
redaction. However, the
/api/v4/args
and
/api/v4/args/{item}
endpoints were not addressed by this fix. These endpoints return the complete command-line arguments namespace via
vars(self.args)
, which includes the password hash (salt + pbkdf2 hmac), SNMP community strings, SNMP authentication keys, and the configuration file path. When Glances runs without
--password
(the default), these endpoints are accessible without any authentication.

Details

The secrets exposure fix (GHSA-gh4x, commit 5d3de60) modified three config-related endpoints to use
as dict secure()
when no password is configured:
# glances/outputs/glances restful api.py:1168 (FIXED)
args json = self.config.as dict() if self.args.password else self.config.as dict secure()
However, the
 api args
and
 api args item
endpoints were not part of this fix and still return all arguments without any sanitization:
# glances/outputs/glances restful api.py:1222-1237
def api args(self):
  try:
    # Get the RAW value of the args dict
    # Use vars to convert namespace to dict
    args json = vars(self.args)
  except Exception as e:
    raise HTTPException(status.HTTP 404 NOT FOUND, f"Cannot get args ({str(e)})")

  return GlancesJSONResponse(args json)
And the item-specific endpoint:
# glances/outputs/glances restful api.py:1239-1258
def api args item(self, item: str):
  ...
  args json = vars(self.args)[item]
  return GlancesJSONResponse(args json)
The
self.args
namespace contains sensitive fields set during initialization in
glances/main.py
:
  1. password
    (line 806-819): When
    --password
    is used, this contains the salt + pbkdf2 hmac hash. An attacker can use this for offline brute-force attacks.
  2. snmp community
    (line 445): Default
    "public"
    , but may be set to a secret community string for SNMP monitoring.
  3. snmp user
    (line 448): SNMP v3 username, default
    "private"
    .
  4. snmp auth
    (line 450): SNMP v3 authentication key, default
    "password"
    but typically set to a secret value.
  5. conf file
    (line 198): Path to the configuration file, reveals filesystem structure.
  6. username
    (line 430/800): The Glances authentication username.
Both endpoints are registered on the authenticated router (line 504-505):
f'{base path}/args': self. api args,
f'{base path}/args/{{item}}': self. api args item,
When
--password
is not set (the default), the router has NO authentication dependency (line 479-480), making these endpoints completely unauthenticated:
if self.args.password:
  router = APIRouter(prefix=self.url prefix, dependencies=[Depends(self.authentication)])
else:
  router = APIRouter(prefix=self.url prefix)

PoC

Scenario 1: No password configured (default deployment)
# Start Glances in web server mode (default, no password)
glances -w

# Access all command line arguments without authentication
curl -s http://localhost:61208/api/4/args | python -m json.tool

# Expected output includes sensitive fields:
# "password": "",
# "snmp community": "public",
# "snmp user": "private",
# "snmp auth": "password",
# "username": "glances",
# "conf file": "/home/user/.config/glances/glances.conf",

# Access specific sensitive argument
curl -s http://localhost:61208/api/4/args/snmp community
curl -s http://localhost:61208/api/4/args/snmp auth
Scenario 2: Password configured (authenticated deployment)
# Start Glances with password authentication
glances -w --password --username admin

# Authenticate and access args (password hash exposed to authenticated users)
curl -s -u admin:mypassword http://localhost:61208/api/4/args/password
# Returns the salt$pbkdf2 hmac hash which enables offline brute-force

Impact

  • Unauthenticated network reconnaissance: When Glances runs without
    --password
    (the common default for internal/trusted networks), anyone who can reach the web server can enumerate SNMP credentials, usernames, file paths, and all runtime configuration.
  • Offline password cracking: When authentication is enabled, an authenticated user can retrieve the password hash (salt + pbkdf2 hmac) and perform offline brute-force attacks. The hash uses pbkdf2 hmac with SHA-256 and 100,000 iterations (see
    glances/password.py:45
    ), which provides some protection but is still crackable with modern hardware.
  • Lateral movement: Exposed SNMP community strings and v3 authentication keys can be used to access other network devices monitored by the Glances instance.
  • Supply chain for CORS attack: Combined with the default CORS misconfiguration (finding 001), these secrets can be stolen cross-origin by a malicious website.

Recommended Fix

Apply the same redaction pattern used for the
/api/v4/config
endpoints:
# glances/outputs/glances restful api.py

 SENSITIVE ARGS = frozenset({
  'password', 'snmp community', 'snmp user', 'snmp auth',
  'conf file', 'password prompt', 'username used',
})

def api args(self):
  try:
    args json = vars(self.args).copy()
    if not self.args.password:
      for key in SENSITIVE ARGS:
        if key in args json:
          args json[key] = "********"
    # Never expose the password hash, even to authenticated users
    if 'password' in args json and args json['password']:
      args json['password'] = "********"
  except Exception as e:
    raise HTTPException(status.HTTP 404 NOT FOUND, f"Cannot get args ({str(e)})")
  return GlancesJSONResponse(args json)

def api args item(self, item: str):
  if item not in self.args:
    raise HTTPException(status.HTTP 400 BAD REQUEST, f"Unknown argument item {item}")
  try:
    if item in SENSITIVE ARGS:
      if not self.args.password:
        return GlancesJSONResponse("********")
      if item == 'password':
        return GlancesJSONResponse("********")
    args json = vars(self.args)[item]
  except Exception as e:
    raise HTTPException(status.HTTP 404 NOT FOUND, f"Cannot get args item ({str(e)})")
  return GlancesJSONResponse(args json)

Fix

Information Disclosure

Weakness Enumeration

Related Identifiers

CVE-2026-32609
GHSA-CVWP-R2G2-J824

Affected Products

Glance