Malicious code in tsshare (PyPI)
MAL-2026-16044
Published · Modified
Dependency scanning
Check whether tsshare is in your codebase
Corgea flags malicious and compromised dependencies with reachability analysis, so you fix the packages that actually run in your application instead of working through the whole lockfile.
Description
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.
__
Source: amazon-inspector (539c8fdb69887b093801655215f1857f53abb20e6dc763198c543def86c39387)
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.
References
- ADVISORY https://research.codelake.dev/advisories/clr-2026-3053-tsshare
- PACKAGE https://pypi.org/project/tsshare/1.0.7/
- PACKAGE https://pypi.org/project/tsshare/1.0.5/
- PACKAGE https://pypi.org/project/tsshare/1.0.11/
- PACKAGE https://pypi.org/project/tsshare/1.0.18/
- PACKAGE https://pypi.org/project/tsshare/1.0.6/
- PACKAGE https://pypi.org/project/tsshare/1.0.14/
- PACKAGE https://pypi.org/project/tsshare/1.0.10/
- PACKAGE https://pypi.org/project/tsshare/1.0.16/
- PACKAGE https://pypi.org/project/tsshare/1.0.2/
- PACKAGE https://pypi.org/project/tsshare/1.0.8/
- PACKAGE https://pypi.org/project/tsshare/1.0.1/
- PACKAGE https://pypi.org/project/tsshare/1.0.4/
- PACKAGE https://pypi.org/project/tsshare/1.0.15/
- PACKAGE https://pypi.org/project/tsshare/1.0.17/
- PACKAGE https://pypi.org/project/tsshare/1.0.9/
- PACKAGE https://pypi.org/project/tsshare/1.0.3/
- PACKAGE https://pypi.org/project/tsshare/1.0.13/
- PACKAGE https://pypi.org/project/tsshare/1.0.12/
- PACKAGE https://pypi.org/project/tsshare/1.0.0/
Ready to move
Start Securing
Free, no credit card | First findings in minutes