OneDragon-Anything / ZenlessZoneZero-OneDragon
Privacy Policy Violation & Undisclosed Data Exfiltration
| FIELD | VALUE |
|---|---|
| Repository | OneDragon-Anything/ZenlessZoneZero-OneDragon |
| Repository URL | github.com/OneDragon-Anything/ZenlessZoneZero-OneDragon |
| Discovery Method | Automated secret scanner (Grafana token) → manual code review |
| Initial Finding | Hardcoded Grafana Cloud auth token in config.py |
| Escalated Finding | Telemetry system with privacy policy violations and data exfiltration |
| Original Severity | CRITICAL |
| Reported To | GitHub Issues (public issue filed) |
| Status | Partially remediated — three of four findings patched, one remains |
| Files Involved | telemetry_manager.py, event_collector.py, config.py, game_account_config.py |
ZenlessZoneZero-OneDragon is an open-source game automation tool for the miHoYo title Zenless Zone Zero. It automates daily tasks, manages multiple game accounts, and handles auto-login using stored credentials. The software is distributed on GitHub and has an active user base primarily in China.
This report was initiated when an automated secret scanner flagged a hardcoded Grafana Cloud authentication token in the repository. Manual review of the surrounding codebase revealed a significantly more serious issue: a purpose-built telemetry system that contradicted the project's published privacy policy in multiple ways, including the collection and transmission of game login usernames to an Alibaba Cloud server without user disclosure or consent.
The initial discovery came from running an automated secret scanner against recently updated public GitHub repositories. The scanner flagged a Grafana Cloud authentication token hardcoded in src/zzz_od/telemetry/config.py. This token authenticated against a Loki log aggregation instance and was also being written to users' local config/telemetry.yml files on first run.
After finding the Grafana token, the full telemetry subdirectory was retrieved and analysed across 15 source files. Review revealed that the Grafana/Loki backend was fully commented out and inactive — the real active backend was Alibaba Cloud SLS (Simple Log Service). This shifted the investigation from a credential leak to a data collection audit.
The project's PRIVACY.md was retrieved and compared against the code behaviour. The policy explicitly states that collected data is anonymous and that running configuration information is stored only on the user's local device. Both claims were found to be directly contradicted by the code.
The PrivacySettings data model defines anonymize_user_data: bool = True as the default. However, TelemetryManager.initialize() explicitly overrode this value after loading settings from disk, making it impossible for any user configuration to take effect. All three data collection flags were also force-enabled in the same function regardless of saved user preferences.
With the flag set to False, the PrivacyController fell back to a weaker filter-only mode that still passed many values through unmodified. Removed in commit b99f5ff1 on 2026-04-16.
The method _report_multi_account_usage() fired during initialization for any user with more than three game accounts configured. It read the account field from GameAccountConfig for each instance — the same credential used by the auto-login feature to authenticate with game servers. The payload included a list of raw login usernames, account count, and a persistent device identifier.
Critically, the two methods responsible for applying privacy filtering and sanitization to all other telemetry events explicitly skipped this event:
At time of disclosure, track_app_launch() in event_collector.py constructed a machine_id string using socket.gethostname() and platform.machine(), then sent it as a plaintext property on every application launch. The hostname was not in PrivacyController.SENSITIVE_KEYS, so even the partial filtering that ran on other events did not redact this value.
Status: Partially patched. event_collector.py was deleted in commit b99f5ff1, but the current telemetry_manager.py continues to send platform.node() (the raw computer hostname) on every launch:
Users are still trackable across sessions via a stable identifier derived from their computer name. There is no opt-out mechanism visible in the current codebase. The Alibaba Cloud SLS endpoint remains active and unchanged.
The Grafana Cloud authentication token was hardcoded as a fallback value in config.py and written to users' local config/telemetry.yml on first run. The Loki backend was inactive at time of discovery, so this did not affect users directly, but the token was publicly exposed in the repository. _load_from_env() was removed in commit 7228bc70 on 2026-03-22. The token should be rotated.
For a user with more than three game accounts configured, on every application launch:
TelemetryManager.initialize() is called silently
anonymize_user_data forcibly set to False, overriding any saved user preference
AliyunWebTrackingClient initialized pointing to zzz-od-1.cn-hangzhou.log.aliyuncs.com
socket.gethostname() + platform.machine()
app_launched event fires, sending the raw hostname string to Alibaba Cloud
_report_multi_account_usage() reads the account field (login username) for each configured instance
| POLICY CLAIMS | CODE BEHAVIOUR (AT DISCLOSURE) | CURRENT STATUS |
|---|---|---|
| Data collected is anonymous | anonymize_user_data force-set to False at runtime |
Patched |
| Configuration info stored only on local device | Login usernames sent to Alibaba Cloud SLS | Patched |
| Only anonymous error logs and performance metrics collected | Hostname, login usernames, and machine UUID collected | Partially patched — hostname persists |
- Password exfiltration — the
.passwordfield exists inGameAccountConfigalongside.account, but no telemetry code was found reading the password field - Active Grafana/Loki collection — the token was leaked but the backend was inactive
- Payment data collection — miHoYo handles payments in-browser; the app does not have access to that flow
- The
TelemetryUISupportclass had a full privacy settings backend built, suggesting anonymization was intended to be user-controllable — it was never surfaced in the UI and has since been deleted - Neither remediation commit references the disclosed issue; critical fixes were folded into unrelated commit messages
A maintainer (m1boy) responded to the GitHub issue with the following (reproduced for accuracy):
The acknowledgment that data was stored on external servers confirms collection occurred. The response does not address the privacy policy contradictions directly, does not commit to updating the policy, and does not mention the persistent hostname collection that remains in the current codebase.
Findings 1, 2, and 4 have been patched. Finding 3 (hostname collection) persists in the refactored telemetry_manager.py. Users are still tracked by a deterministic UUID derived from their computer name on every launch, transmitted to Alibaba Cloud SLS with no opt-out mechanism and no disclosure in the current privacy policy.
Users who ran this software with more than three game accounts configured between the initial telemetry implementation and the April 16 patch should assume their game login usernames were transmitted to Alibaba Cloud SLS.