GitHub Security Advisory: GHSA-cvwp-r2g2-j824
Package: Glances (PIP)
Severity: HIGH (CVSS 7.5)
CWE: CWE-200: Exposure of Sensitive Information to an Unauthorized Actor
Vulnerable versions: < 4.5.2
Patched in: 4.5.2

Summary: Glances has Incomplete Secrets Redaction: /api/v4/args Endpoint Leaks Password Hash and SNMP Credentials

Details:
## 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:

```python
# 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:

```python
# 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:

```python
# 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):
```python
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:
```python
if self.args.[CREDENTIAL_REDACTED] = APIRouter(prefix=self.url_prefix, dependencies=[Depends(self.authentication)])
else:
    router = APIRouter(prefix=self.url_prefix)
```

## PoC

**Scenario 1: No password configured (default