On January 15, 2025, attackers compromised maintainer accounts in the Ant Design (AntV) ecosystem and published malicious versions of multiple npm packages. The campaign, tracked as sonatype-2026-003200, injected code that executed immediately upon installation—before any developer could review changes or run tests. The malicious packages targeted CI/CD credentials and attempted to establish remote command execution channels.
This incident highlights the urgent need for a shift in how the software industry approaches trust and security in package ecosystems. Attackers used compromised credentials to publish packages through npm's standard workflow, making them appear as legitimate updates from trusted maintainers.
Timeline
January 15, 2025 (estimated): Attackers gain access to maintainer accounts for packages in the Ant Design ecosystem. The method of compromise remains unconfirmed—potential methods include credential reuse, phishing, or session token theft.
January 15, 2025: Malicious package versions are published to the npm registry. The code executes in npm's preinstall hook, running before the package installation completes.
January 15-16, 2025: Sonatype's automated monitoring flags suspicious behavior patterns. Security teams begin investigating affected packages.
January 16, 2025: Public disclosure and package removal from the npm registry. Organizations that installed affected versions during the compromise window remain exposed until they identify and remove the malicious code.
Which Controls Failed or Were Missing
Access Control Failure: The maintainer accounts lacked multi-factor authentication (MFA) enforcement or had MFA implementations that could be bypassed. Once attackers obtained credentials, npm's publishing system treated them as authorized maintainers.
Package Signing Gap: The affected packages had no cryptographic signatures linking them to specific maintainer identities. While npm supports package signing through tools like Sigstore, adoption remains optional. Without signatures, there's no way to prove a package came from its claimed author versus someone with stolen credentials.
Installation-Time Execution: The malicious code ran in preinstall hooks—a feature that executes arbitrary code before package installation completes. Your dependency scanner never sees this code because it runs before the package lands in node_modules. Your code review process never catches it because it executes before you can review anything.
CI/CD Credential Exposure: The attack specifically targeted credentials stored in CI/CD environments. This suggests the attackers understood that developer workstations might have limited access, but CI/CD systems typically hold production deployment keys, cloud provider credentials, and package registry tokens.
Missing Network Egress Controls: The malicious code successfully established outbound connections to attacker-controlled infrastructure. Many development and CI/CD environments allow unrestricted outbound traffic, making data exfiltration trivial.
What the Standards Require
ISO/IEC 27001:2022, Control 5.17 (Authentication Information) requires organizations to manage authentication information through a formal process, including MFA where appropriate. For package maintainer accounts—which control code that runs in thousands of downstream systems—MFA should be mandatory, not optional.
NIST 800-53 Rev 5, Control SA-10 (Developer Configuration Management) addresses configuration management and integrity verification during development. This includes "integrity verification of software and information," which package signing directly supports. If you're subject to NIST 800-53, you need a way to verify that packages came from their claimed sources.
PCI DSS v4.0.1, Requirement 6.3.2 states that custom software must be reviewed prior to release to production. The challenge: when malicious code executes during npm install, it runs before your review process begins. If your CI/CD pipeline installs dependencies before running security scans, you've created a gap where Requirement 6.3.2's intent—catching malicious code before it reaches production—cannot be met.
SOC 2 Type II, Common Criteria CC6.1 requires logical access controls that restrict access to information assets. Your application's dependencies are information assets. When you npm install without verification, you're granting execute permissions to code you haven't reviewed from maintainers you haven't verified.
Lessons and Action Items
Enforce package signatures in your environment. Configure npm to require package provenance using npm config set audit-level high and implement signature verification through Sigstore. This won't prevent compromised maintainer accounts, but it ensures you can trace each package to a specific signing event and maintainer identity.
Isolate dependency installation from sensitive credentials. Run npm install in a sandboxed environment with no access to production credentials, API keys, or deployment tokens. Only after installation completes and security scans pass should you move the dependencies into your build environment. This breaks the attack chain that targets CI/CD credentials during installation.
Block preinstall and postinstall hooks by default. Use npm config set ignore-scripts true in CI/CD environments. When you need lifecycle scripts (rare for most projects), explicitly allow them per package after manual review. Yes, this breaks some legitimate packages. That's the point—you're forcing a conscious decision about which code can execute during installation.
Implement egress filtering in development and CI/CD networks. Restrict outbound connections to a defined list of necessary services: your package registries, cloud providers, and deployment targets. Malicious packages that successfully execute but cannot phone home are significantly less dangerous.
Monitor for unexpected package updates. Tools like Dependabot and Renovate create pull requests for dependency updates, giving you a review window. But they only help if someone reviews the changes. Train your team to check package diff sizes—a legitimate bug fix might change 50 lines, while a supply chain attack might inject 500 lines of obfuscated code.
Require MFA for all package publishing accounts. If you maintain internal packages or contribute to open source, enable MFA on your npm account through npm profile enable-2fa. For organizations, enforce this through your access management policy. A compromised maintainer account without MFA is a single phishing email away from becoming an attack vector.
Create a package quarantine workflow. When new versions of critical dependencies appear, hold them in a staging environment for 24-48 hours before production deployment. This window lets the security community identify obvious compromises before they reach your systems. It won't catch sophisticated attacks, but it stops the opportunistic ones.
The Ant Design compromise succeeded because it exploited the trust model that makes package ecosystems functional. You cannot eliminate this trust—modern development requires dependencies. But you can verify trust instead of assuming it, and you can limit the blast radius when trust breaks.



