{"id":"CVE-2026-68520","aliases":[],"url":"https://o3.security/vulnerability/CVE-2026-68520","summary":"Glances: as_dict_secure() Value-Level Bypass Leaks Credentials in URL Values via /api/4/config","details":"## Summary\n\nGlances provides `as_dict_secure()` explicitly designed for unauthenticated API access, with a docstring stating it returns \"a sanitised copy of the configuration dict\" where \"Sensitive keys in remaining sections are replaced by '********'\". However, the implementation only checks KEY names against a regex pattern and never inspects VALUE content. The documented `[ip]` config section supports `public_api` (URL), `public_username` (login), and `public_password` (password). While `public_password` is correctly masked, both `public_api` (when containing embedded credentials like `https://user:pass@host/`) and `public_username` are returned in full to unauthenticated users via `GET /api/4/config`.\n\n## Affected Versions\n\nGlances latest (Docker: `nicolargo/glances:latest`)\n\n## Root Cause\n\nIn `glances/config.py`, `as_dict_secure()`:\n```python\n_SECURE_SENSITIVE_KEY_RE = re.compile(r\"password|token|secret|api_key|apikey|ssl_keyfile\", re.IGNORECASE)\n\ndef as_dict_secure(self):\n    \"\"\"Return a sanitised copy of the configuration dict.\n    Intended for unauthenticated API access.\n    - Sensitive keys in remaining sections are replaced by '********'.\n    \"\"\"\n    sanitized = {}\n    for section, options in self.as_dict().items():\n        if section in _SECURE_BLOCKED_SECTIONS: continue\n        sanitized[section] = {\n            key: \"********\" if _SECURE_SENSITIVE_KEY_RE.search(key) else value\n            for key, value in options.items()\n        }\n    return sanitized\n```\n\nIn `glances/outputs/glances_restful_api.py`:\n```python\n# Line 1294\nargs_json = self.config.as_dict() if self.args.password else self.config.as_dict_secure()\n```\n\nThe `[ip]` config section documents: `public_api` (URL), `public_username` (login), `public_password` (password).\n- `public_password` → matches \"password\" → masked ✓\n- `public_api` → no match → returned in full (contains `user:pass@` in URL) ✗\n- `public_username` → no match → returned in full ✗\n\n## Impact\n\n- Unauthenticated credential disclosure via `GET /api/4/config` or `GET /api/4/config/ip`\n- `as_dict_secure()` exists specifically to protect credentials in no-auth mode but fails to mask `public_username` and credential-bearing URLs in `public_api`\n\n## Prerequisites\n\n- Glances in web server mode without `--password` (default, no auth)\n- `glances.conf` `[ip]` section with `public_api` containing embedded credentials and/or `public_username` set\n\n## Environment\n\n- Glances latest (Docker: `nicolargo/glances:latest`)\n- Remote Docker lab at `http://10.140.200.102:8080`\n\n## Reproduction Steps\n\n```bash\ndocker run -d --name glances-test -p 8080:61208 -e GLANCES_OPT='-w' nicolargo/glances:latest\nsleep 20\ndocker exec glances-test sed -i 's|public_api=https://ipv4.ipleak.net/json/|public_api=https://admin:secret123@ipv4.ipleak.net/json/|' /etc/glances/glances.conf\ndocker exec glances-test sed -i 's|#public_username=<myname>|public_username=myname|' /etc/glances/glances.conf\ndocker exec glances-test sed -i 's|#public_password=<mysecret>|public_password=mysecret|' /etc/glances/glances.conf\ndocker restart glances-test\nsleep 15\ncurl -s \"$TARGET/api/4/config/ip\"\n# Returns: {\"public_api\": \"https://admin:secret123@...\", \"public_username\": \"myname\", \"public_password\": \"********\"}\n```\n\n## Evidence\n\nSee `C:/Tools/glances-config-leak-evidence.txt`.\n\n## Dedup Check\n\n- GHSA-gfc2-9qmw-w7vh covers CORS but NOT value-level credential leak\n- No existing GHSA covers `as_dict_secure()` value-level filtering gap\n- 13 published GHSA, none covering this issue\n\n## Suggested Remediation\n\nAdd \"username\" and \"login\" to sensitive key pattern, and check values for embedded credentials in URLs.\n\n## Disclosure Timeline\n\n- 2026-07-28: Vulnerability discovered and verified via Docker deployment\n\n## Reporter\n\nGitHub username: Todor","published":"2026-08-17T17:20:48Z","modified":"2026-08-17T17:30:07.222061064Z","cvss":{"score":5.3,"severity":"MEDIUM","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N"},"epss":null,"cisaKev":null,"exploitsKnown":null,"affectedPackages":[{"ecosystem":"PyPI","name":"glances","fixedVersion":"4.5.6"}],"fix":{"url":"https://github.com/nicolargo/glances/commit/8d0f8276c2abd2e9d400bd6c84bdfba0dfcab065","label":"nicolargo/glances@8d0f827"},"references":[{"type":"WEB","url":"https://github.com/nicolargo/glances/security/advisories/GHSA-4h34-v6r8-mmjc"},{"type":"WEB","url":"https://github.com/nicolargo/glances/commit/8d0f8276c2abd2e9d400bd6c84bdfba0dfcab065"},{"type":"PACKAGE","url":"https://github.com/nicolargo/glances"},{"type":"WEB","url":"https://github.com/nicolargo/glances/releases/tag/v4.5.6"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-08-17T17:30:07.222061064Z"}}