On a Tuesday morning, a developer ran pip install on what appeared to be a legitimate Python package. Instantly, before any of their code executed, a credential harvester was active—extracting AWS keys, GitHub tokens, and SSH credentials from their development machine.
This is the Hades attack. Between package installation and your first import statement, 37 malicious wheel artifacts across 19 PyPI packages executed a Bun-based payload targeting the exact credentials your CI/CD pipeline relies on.
What Happened
The Hades campaign deployed malicious Python packages to PyPI using a technique that bypasses the usual execution flow. Instead of embedding malicious code in setup.py or requiring the developer to call a specific function, the attackers used a *-setup.pth file in each wheel artifact.
Python processes .pth files automatically during interpreter startup—before your code runs, before your virtual environment activates. The .pth file triggered a Bun JavaScript runtime payload that:
- Enumerated environment variables for cloud provider credentials
- Scraped
.ssh,.aws, and.configdirectories - Harvested Git configuration and GitHub tokens
- Exfiltrated everything to attacker-controlled endpoints
The attack targeted developer workstations and CI/CD runners. If your build agent installed any of these 19 packages, the credential theft executed during the dependency resolution phase.
Timeline
Initial Compromise: The 19 packages appeared in PyPI with names similar to legitimate libraries—using typosquatting and dependency confusion techniques.
Execution Vector: Each package contained wheel artifacts with .pth files. Python's site module processes these files at startup, executing arbitrary Python code before the interpreter finishes initializing.
Payload Delivery: The .pth file invoked Bun (a JavaScript runtime) to execute the credential stealer. Using Bun instead of pure Python allowed the attackers to use JavaScript obfuscation and evade Python-focused security tools.
Exfiltration: Stolen credentials were sent to GitHub repositories and external endpoints, allowing attackers to infiltrate victim environments with valid credentials.
Detection: Security researchers identified the malicious artifacts after observing unusual network behavior from Python installations.
Which Controls Failed
Package Verification: The affected organizations lacked automated verification of package integrity before installation. There was no hash verification, no signature checking, no comparison against known-good package lists.
Runtime Monitoring: The .pth execution occurred during Python startup—before application logging or monitoring typically begins. Standard runtime application security tools missed the execution entirely because they hook into application code, not interpreter initialization.
Network Egress Controls: The credential exfiltration succeeded because developer machines and CI/CD runners had unrestricted outbound network access. There was no egress filtering, no allowlist of approved external endpoints, no DNS-level blocking.
Least Privilege: The compromised credentials included production AWS keys and GitHub tokens with broad permissions. The principle of least privilege wasn't enforced—developers and CI/CD runners had access to credentials they didn't need for their specific tasks.
Dependency Pinning: The affected systems installed the latest versions of packages without pinning to specific, verified versions. No lock files, no hash verification, no review process for dependency updates.
What the Standards Require
PCI DSS v4.0.1 Requirement 6.3.2 mandates that bespoke and custom software is developed securely, including secure coding techniques and developer training. This requirement explicitly covers software development environments and build processes. If your build pipeline handles cardholder data or connects to systems that do, this requirement applies to your CI/CD security posture.
NIST 800-53 Rev 5 Control SA-12 (Supply Chain Protection) requires organizations to employ security safeguards to protect against supply chain threats. This includes validating the integrity and authenticity of software packages, maintaining provenance records, and implementing controls to detect malicious code in acquired software components.
ISO/IEC 27001:2022 Control 8.30 (Outsourced Development) addresses the security of externally developed software, including open-source components. The control requires organizations to supervise and monitor development activities, verify software integrity, and implement secure configuration management.
SOC 2 Type II CC6.8 (Logical and Physical Access Controls) requires that the entity restricts the transmission, movement, and removal of information to authorized users and processes. This applies to credential management and the exfiltration vector used in Hades.
Lessons and Action Items
Implement Package Hash Verification Today
Stop installing packages without verifying their integrity. Use pip install --require-hashes and maintain a requirements.txt with SHA256 hashes for every dependency. This adds necessary friction to your process.
# requirements.txt
requests==2.31.0 --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f
Lock Your Python Interpreter Startup
The .pth attack vector works because Python automatically processes .pth files in site-packages. Set the PYTHONNOUSERSITE environment variable in your CI/CD runners to disable user site-packages directory. This prevents .pth files in user-installed packages from executing.
Audit Your CI/CD Credential Scope
Map every credential your build pipeline uses to the specific jobs that need it. If a job builds a frontend component, it doesn't need AWS credentials for your production database. Create service accounts with narrow IAM policies for each pipeline stage.
Deploy Network Egress Controls
Your CI/CD runners should not have unrestricted internet access. Create an allowlist of approved external endpoints: your package registry, your artifact storage, your deployment targets. Block everything else. Use DNS filtering to prevent exfiltration via dynamic domains.
Monitor Interpreter-Level Execution
Traditional application monitoring starts too late to catch startup-time attacks. Deploy system-level monitoring that logs process execution, network connections, and file access from the moment the Python interpreter launches. Tools like Falco or osquery can capture this activity.
Review Your Package Sources
If you're pulling packages directly from PyPI in production builds, you're trusting the entire internet. Set up a private package repository (Artifactory, Nexus, or AWS CodeArtifact). Mirror only the packages you've verified, and configure pip to use only your internal repository.
The Hades attack succeeded because it exploited the gap between package installation and code execution—a window where most security controls aren't watching. Close that gap.



