Hiding in Plain Sight: How a Blatant Cryptominer Survived 3 Years on PyPI

By Paul McCarty

Hiding in Plain Sight: How a Blatant Cryptominer Survived 3 Years on PyPI

The Uncomfortable Truth

For approximately three years, a package called tensorflow-opt sat on the Python Package Index (PyPI), quietly mining cryptocurrency on victims' machines.

tensorflow-opt

When we analyzed this malware, we expected to find sophisticated obfuscation, clever evasion techniques, or at least some attempt to hide its true nature.

We found none of that.

Instead, what we discovered raises a more troubling question: How did such an obviously malicious package survive on PyPI for three years and across at least 26 versions?

many-versions-tensorflow-opt

A Malware Sample That Wasn't Even Trying

Let's be clear about what tensorflow-opt was doing. This wasn't a sophisticated supply chain attack with multi-stage payloads and advanced evasion. The entire malicious codebase in optimize.py was 9 lines of Python:

That's it. Nine lines that:

  • Copy files to the TensorFlow directory
  • Execute a batch file with subprocess.Popen and shell=True
  • Capture output to hide it
  • There's no obfuscation. No dynamic imports. No base64 encoding. No encrypted payloads. The function is literally called start() and it copies files from a /bin/ directory and executes a .bat file.

    The batch file itself? Equally blatant:

    It's setting GPU environment variables to maximize mining performance and then executing a binary called tensor_core.exe with hardcoded mining pool credentials. The attacker's wallet address is right there in plaintext. The mining pool domain is visible. The executable has GPU optimization flags.

    This malware was hiding in plain sight because it wasn't hiding at all.

    The Package Structure Red Flags

    Beyond the obvious malicious code, the package structure itself was suspicious:

    Let's count the red flags:

  • An 8.27 MB executable in a Python package that claims to be an "optimization library"
  • Windows DLL files and drivers (.dll, .sys files) in what should be a cross-platform Python package
  • Batch files that execute on installation
  • Configuration files for a cryptominer (config.txt, dpools.txt)
  • A binary called tensor_core.exe - clearly trying to mimic legitimate TensorFlow components
  • No actual optimization code - just the malicious launcher
  • Any automated scanning system looking for:

  • Large binaries in Python packages
  • Subprocess execution with shell=True
  • Batch file execution
  • Network connections to mining pools
  • GPU configuration settings
  • ...would have immediately flagged this package.

    Who is the threat actor?

    A PyPI user named kwanazizmahood published this package way back in August of 2022:

    tensorflow-opt-author

    This user only ever published the one package, and while PyPI has removed the package, they haven’t removed the user, which we find strange.

    The Three-Year Question

    Here's what makes this case study significant: tensorflow-opt existed across 26 versions for approximately three years.

    tensorflow-opt-ecosystems

    That's three years of:

  • ✗ No automated malware scanning
  • ✗ No community reporting (or ignored reports)
  • ✗ No maintainer verification
  • ✗ No binary analysis
  • ✗ No behavioral analysis during installation
  • The package was even actively maintained across multiple versions, suggesting the attacker felt comfortable enough to continue updating it without fear of detection or removal.

    What This Reveals About the PyPI Ecosystem

    The tensorflow-opt case isn't interesting because the malware was sophisticated. It's interesting because the malware was trivial and it still succeeded.

    Detection Gap #1: No Meaningful Binary Analysis

    PyPI allows package maintainers to upload arbitrary binaries. While there are legitimate uses for this (C extensions, platform-specific optimizations), there's apparently no systematic analysis of what these binaries do.

    An 8.27 MB executable named tensor_core.exe that:

  • Connects to ethash.unmineable.com
  • Uses GPU mining-specific command-line flags
  • Sets environment variables for mining optimization
  • Contains PhoenixMiner signatures
  • ...should have been trivially detectable with even basic static analysis.

    Virustotal knew that this was a cryptominer for years!

    virustotal-tensorflow-opt

    Detection Gap #2: No Code Behavior Analysis

    The optimize.py file exhibits clear malicious patterns:

  • Subprocess execution with shell=True (command injection vector)
  • Copying binaries to unexpected locations (the legitimate TensorFlow installation)
  • Executing batch files on import or function call
  • Capturing and suppressing output
  • These are textbook malicious behaviors. Tools like Bandit, semgrep, or even simple pattern matching could detect these issues. Yet the package sat on PyPI for years.

    Detection Gap #3: No Network Behavior Monitoring

    The batch file connects to a known cryptocurrency mining pool. The wallet address is hardcoded. The worker name identifies the campaign ("tf_opt").

    Any post-installation behavioral analysis - even just monitoring network connections during test installations - would have caught this immediately. But there's no evidence such monitoring exists at scale on PyPI.

    Detection Gap #4: No Naming Similarity Protection

    tensorflow-opt is an obvious typosquat/brandjacking attempt targeting tensorflow, one of the most popular machine learning frameworks in existence. While PyPI has begun implementing some name similarity checks, this package predated those protections and exploited the naming trust users have in the TensorFlow ecosystem.

    The Broader Implication: How Many More Are Out There?

    This is the critical question. If a package this blatantly malicious can survive for three years across multiple versions, how many others are currently on PyPI right now?

    Consider:

  • Packages with better obfuscation would be even harder to detect
  • Packages using more sophisticated techniques might never be caught
  • Packages targeting smaller, less-watched libraries would draw even less scrutiny
  • Packages with legitimate functionality plus malicious features would be harder to identify
  • The tensorflow-opt case suggests we're only seeing the tip of the iceberg - the packages that are so obvious that they eventually get reported by vigilant users, not caught by systematic defenses.

    The Ecosystem Challenge

    PyPI faces a genuine challenge:

  • Scale: Tens of thousands of packages are uploaded monthly
  • Legitimate Use Cases: Binary files, native extensions, and platform-specific code are valid
  • False Positives: Aggressive scanning could flag legitimate packages
  • Resource Constraints: Comprehensive malware analysis is expensive
  • Attacker Adaptation: Malware authors will evolve to evade detection
  • But the tensorflow-opt case shows that even basic, low-cost security measures would catch the most blatant attacks:

  • Automated Static Analysis
  • Scan for subprocess.Popen with shell=True
  • Flag packages with executables + batch files
  • Check for hardcoded wallet addresses or mining pool domains
  • Binary Reputation Checking
  • Hash-based lookups against known malware databases
  • Signature matching for known mining software
  • Size-based anomaly detection (8 MB binaries in "optimization" packages)
  • Behavioral Sandboxing
  • Test package installation in isolated environments
  • Monitor network connections during and after installation
  • Flag packages that modify files outside their own directory
  • Community-Powered Detection
  • Clear reporting mechanisms for suspicious packages
  • Public security review process
  • Bug bounty programs for malware discovery
  • Name Similarity Enforcement
  • Stronger protections against typosquatting popular packages
  • Verification requirements for packages with similar names to established projects
  • Maintainer verification for high-similarity package names
  • The Technical Reality of Modern Malware

    Here's what makes the tensorflow-opt case particularly concerning: the attacker didn't need to be sophisticated.

    Modern package repository malware doesn't require:

  • Advanced obfuscation techniques
  • Zero-day exploits
  • Complex multi-stage payloads
  • Custom malware development
  • An attacker can:

  • Take an existing tool (PhoenixMiner)
  • Write 9 lines of Python to execute it
  • Upload to PyPI
  • Wait for victims
  • The barrier to entry is frighteningly low, and the detection rate is apparently even lower.

    Cryptocurrency Mining: Not dumb if it works?

    Cryptomining malware has several advantages for attackers:

  • Low Detection Risk: Unlike ransomware or data theft, mining is often noticed only through performance degradation
  • Direct Monetization: No need to sell stolen data or wait for ransom payments
  • Difficult Attribution: Cryptocurrency provides pseudonymity
  • Persistent Payoff: As long as the malware runs, the attacker profits
  • Scaling Value: More victims = more mining power = more profit
  • For the tensorflow-opt attacker:

  • Wallet address: TRX:TD5TrHLdGyhz85aK9yjQKEKv3sFt5JsRuz.tf_opt
  • Worker identifier: tf_opt
  • Pool: ethash.unmineable.com:3333
  • Every developer who installed this package and had a GPU became an unwitting cryptocurrency miner, with all profits going directly to the attacker's TRON wallet.

    The worker name "tf_opt" allowed the attacker to track exactly how much revenue this specific campaign generated. Based on the three-year timeline and multiple package versions, this was clearly profitable enough to maintain.

    What Developers Can Do Right Now

    While we wait for ecosystem-level improvements, developers need to protect themselves:

    1. Audit Your Dependencies

    Run regular security audits:

    # Check for known vulnerabilities pip-audit # Static analysis of installed packages safety check # List all installed packages and review them pip list

    2. Use Safety Firewall

    Traditional vulnerability scanning happens too late - after potentially malicious code is already in your system. Which means that ASPM and EDR solutions don't protect you from this type of threat.

    But all is not lost, as the Safety Firewall protects developers and CI pipelines proactively. Every package installation request is analyzed before reaching public repositories. Malicious, vulnerable, and policy-violating packages are automatically blocked before they can enter your systems, preventing rather than just detecting threats.

    You can sign up for a free Safety account and try the Safety Firewall HERE.

    Feel free to reach out to me with any questions!

    Conclusion: The Malware We Can't Afford to Miss

    tensorflow-opt wasn't a sophisticated attack. It was nine lines of Python, an executable, and a batch file. No encryption, no obfuscation, no advanced techniques.

    And it worked for three years, and was downloaded hundreds or thousands of times.

    This case study isn't about appreciating clever malware engineering. It's about recognizing a fundamental truth: if this malware can survive on PyPI for three years, the problem isn't just one bad package - it's a systemic detection and response gap.

    Somewhere on PyPI right now, there are packages with:

  • Better obfuscation than tensorflow-opt
  • More subtle behavior than tensorflow-opt
  • Harder-to-detect payloads than tensorflow-opt
  • And if we can't even catch the obvious ones, what hope do we have of catching those?

    The tensorflow-opt campaign succeeded not because the attacker was particularly skilled, but because the defenses were particularly absent. Until that changes - until basic security scanning, behavioral analysis, and community reporting become standard infrastructure for package repositories - we can expect many more campaigns just like this one.

    The malware hiding in plain sight is bad enough. But the real threat is the malware we're not seeing at all.

    Indicators of Compromise

    If you've ever installed tensorflow-opt, check for:

    Package names:

  • tensorflow-opt
  • Files:

  • tensor_core.exe - sha256 hash: e8e775add50c67e1c6f6ca20db318f745e22b085afcbdf5634015e6ef91e8853
  • start_opt_engine.bat - sha256 hash: b4fab8abeef714d730108be8cd4fd3781125a7f9eccc922a472b975f2b414dc1
  • EIO.dll - sha256 hash: 287e44f5067a4e770e8a0605f5720d3d1477ecc4aa4f3a26ce5d3a489ae79780
  • EIO.exe - sha256 hash: 402438684406d1e3b2d1d5629151259ad864ffc55c8e6ab176f4c47c543d4fee
  • IOMap64.sys - sha256 hash: ad20e44954960278ad965b05e8c67d9d314c200809b99b1b5a219a916ce06b21
  • dpools.txt - sha256 hash: c7ca250f97d5e06773a03b03e37367598b9d060a3f0aaaca2ff9d6d77ca9ccd9
  • Network connections:

  • ethash.unmineable.com:3333
  • Wallet address:

  • TRX:TD5TrHLdGyhz85aK9yjQKEKv3sFt5JsRuz.tf_opt
  • Processes:

  • PhoenixMiner
  • tensor_core.exe
  • Environmental indicators:

  • Unexplained 90%+ GPU utilization
  • GPU_MAX_HEAP_SIZE=90 environment variable
  • GPU_MAX_ALLOC_PERCENT=90 environment variable
  • About This Analysis: This research was conducted on archived malware samples for educational and defensive security purposes. The tensorflow-opt package has been removed from PyPI. All IOCs are provided to enable detection and blocking.

    How can Safety help protect you from these attacks?

    Traditional vulnerability scanning happens too late - after potentially malicious code is already in your system. Which means that ASPM and EDR solutions don't protect you from this type of threat.

    But all is not lost, as the Safety Firewall protects develoeprs and CI pipelines proactively. Every package installation request is analyzed before reaching public repositories. Malicious, vulnerable, and policy-violating packages are automatically blocked before they can enter your systems, preventing rather than just detecting threats.

    You can sign up for a free Safety account and try the Safety Firewall HERE.

    Feel free to reach out to me with any questions!

    Read the full article