MAL-2026-16044Critical▾ Abyssal⚠ Exploited in the wildMalicious code in tsshare (PyPI)
▾ Abyssal zone — Critical with a public exploit or in-the-wild use
impact 52.3 · likelihood 0 · exploitation 18
Need a working PoC? Pro members can cast a request and our team develops one — it lands right here.
Disclosure to exploitation, from the record and what we observed since indexing it.
Disclosed via OSV
Last analysed / modified upstream
The PyPI package tsshare is malicious. It impersonates the popular Chinese market-data library tushare — its docstrings advertise compatibility with Tushare pro_bar and it ships MyShareClient/MyShareError aliases. tsshare/client.py conceals its default API endpoint by base64-decoding it at runtime: in 1.0.5–1.0.18 the value decodes to the hardcoded raw IP https://47.112.191.75 (Alibaba Cloud, China), and in 1.0.19 it rotates to the domain https://fszzw56.com. On use, the client builds a persistent cross-platform hardware fingerprint (Windows disk-drive serial via Win32_DiskDrive, macOS Hardware UUID via system_profiler, Linux /etc/machine-id) and routes the request — carrying the user's Tushare auth_code token — to that hidden endpoint, so the operator receives the paid API token together with a stable machine identifier. There is no install-time hook; exfiltration occurs on API use.
-= Per source details. Do not edit below this line.=-
The package presents itself as a drop-in replacement for Tushare's pro_api, but every method call is dispatched through a query() that POSTs to a hardcoded default backend at https://47.112.191.75/api/v1/proxy rather than to tushare.pro. The destination URL is stored base64-encoded (_E = b"aHR0cHM6Ly80Ny4xMTIuMTkxLjc1") and decoded at runtime by _default_base_url, and the destination is a bare IP unrelated to the credential's issuer. set_token() stores the caller's Tushare auth_code, and every subsequent proxied call includes {'auth_code': self.auth_code,...} in the POST body to that endpoint, so the paid third-party credential leaves the trust boundary it was issued for and can be logged or replayed by the operator of 47.112.191.75. The client also collects a persistent hardware fingerprint on first use — PowerShell Win32_Processor ProcessorId and Win32_DiskDrive SerialNumber on Windows, system_profiler Hardware UUID on macOS, /etc/machine-id on Linux — SHA-256 hashes it, caches it under ~/.tsshare/device_id.json, and attaches it as meta.device_id to every request, giving the backend operator a stable per-machine identifier unnecessary for the advertised proxy function. TLS certificate verification on the requests.Session is disabled by default (session.verify defaults to false via TSSHARE_SSL_VERIFY/MYSHARE_SSL_VERIFY) and urllib3 InsecureRequestWarning is silenced, so the auth_code and hardware ID are transmitted to the bare-IP HTTPS endpoint without cert validation.
tsshareRefer to the advisory for the patched release.