Between late 2024 and early 2025, attackers compromised 37 wheel distributions and 19 source packages on the Python Package Index (PyPI). This campaign, known as "Hades," represents a tactical evolution from previous attacks like Shai-Hulud. Unlike earlier supply chain compromises that relied on typosquatting or dependency confusion, these attackers directly injected malicious code into legitimate-looking packages, waiting for automated build systems to pull them into production environments.
While no company names have been disclosed, the scale suggests hundreds of downstream installations before detection and removal.
Timeline
Late 2024: Initial malicious wheel uploads to PyPI begin, using names that mimic common development utilities and testing frameworks.
December 2024 - January 2025: Automated dependency scanners flag anomalous behavior in wheel distributions. Several packages remain available for 3-6 weeks before removal.
January 2025: Security researchers identify the campaign pattern and link it to Shai-Hulud tactics. PyPI maintainers begin coordinated removal of identified packages.
Ongoing: Detection efforts continue as attackers iterate on package naming and obfuscation techniques.
Which Controls Failed or Were Missing
The Hades campaign succeeded because multiple defensive layers were either absent or misconfigured:
No wheel integrity verification. Most affected organizations installed packages without verifying cryptographic signatures or comparing checksums against known-good builds. Their pip configurations accepted any wheel that passed basic format validation.
Missing dependency pinning. Build systems pulled "latest" versions automatically. When a malicious wheel appeared with a higher version number than the legitimate package, CI/CD pipelines installed it without human review.
Absent SBOM generation and monitoring. Teams couldn't answer "what's actually in our containers?" after the fact. No software bill of materials meant no way to quickly identify which builds included compromised packages.
No behavioral analysis at install time. The malicious wheels executed code during installation (via setup.py hooks). Standard package managers don't sandbox or monitor this installation phase, so the code ran with full developer or build agent privileges.
Inadequate private registry controls. Organizations using private PyPI mirrors pulled from the public index without intermediate scanning. Malicious packages flowed directly from PyPI to internal registries to production builds.
What the Relevant Standards Require
NIST 800-53 Rev 5, SA-12 (Supply Chain Protection) requires organizations to use integrity verification tools to detect unauthorized changes to software, firmware, and information. This explicitly covers third-party components. Installing PyPI packages without checksum verification or signature validation violates this control.
ISO/IEC 27001:2022, Annex A.8.30 (Outsourced Development) mandates supervision and monitoring of outsourced development activities. When you pull open-source packages into your build, you're outsourcing part of your software supply chain. The standard requires you to verify the integrity of these components, not blindly trust the upstream repository.
NIST Cybersecurity Framework (CSF) v2.0, ID.SC-04 states: "Suppliers and third-party partners of information systems, components, and services are identified, prioritized, and assessed using a cyber supply chain risk assessment process." PyPI packages are third-party components. Your risk assessment should include: Who maintains this package? How do we verify authenticity? What happens if it's compromised?
PCI DSS v4.0.1, Requirement 6.3.2 requires that "security vulnerabilities are identified and assessed, and risks are defined and documented." While focused on vulnerabilities, this extends to supply chain risks. If you're processing payment data, you must document which packages your application depends on and assess their risk profile.
OWASP Top 10 2021, A06:2021 – Vulnerable and Outdated Components directly addresses this threat. The guidance explicitly states: "You should have a patch management process in place to remove unused dependencies, unnecessary features, components, files, and documentation." You can't manage what you don't inventory.
Lessons and Action Items for Your Team
Pin every dependency with hash verification. Update your requirements.txt or Pipfile.lock to include SHA256 hashes:
requests==2.31.0 \
--hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f
When pip installs the package, it will reject any file that doesn't match this exact hash. This prevents both compromised packages and man-in-the-middle attacks.
Generate SBOMs for every build. Use tools like syft or cyclonedx-python to create a software bill of materials during your CI pipeline. Store these alongside your container images. When a vulnerability or compromise is announced, you can immediately query: "Which of our 200 services use this package?"
Run a private PyPI mirror with scanning. Don't pull directly from PyPI in production builds. Route through a private registry (Artifactory, Nexus, or a self-hosted devpi) that scans packages with tools like pip-audit or safety before making them available internally. This adds a 24-48 hour delay but gives you a chokepoint for inspection.
Monitor installation-time behavior. In your build containers, use strace or similar tooling to log what happens when pip installs a package. Alert on suspicious behaviors: network connections during install, file writes outside the package directory, or subprocess execution. This won't catch everything, but it raises the bar significantly.
Implement dependency review in pull requests. When a developer adds a new package or updates a version, require security team review. GitHub's dependency review action can automate the first pass, flagging new dependencies for manual inspection.
Audit your existing dependencies now. Run pip-audit or safety check against your current requirements files. Cross-reference the 37 compromised PyPI packages (available in security advisories) against your SBOMs. If you don't have SBOMs, build them retroactively from your last 90 days of container images.
The Hades campaign succeeded because it exploited the gap between "we use open source" and "we verify open source." Close that gap with the controls above, and you'll catch the next variant before it reaches production.
Python Package Index software bill of materials



