Security researchers tracking the NuGet ecosystem have flagged a fresh cluster of malicious packages uploaded to nuget.org in recent months, continuing a pattern that has now persisted across multiple documented campaigns since 2023: threat actors publishing typosquatted or trojanized .NET packages that sit quietly in the registry — sometimes for months — before triggering destructive or data-stealing payloads. The packages combined typosquatting of popular libraries, IL-weaving to inject code into legitimate DLLs, and NuGet-specific execution paths like MSBuild .targets files that run at build time with no function call required. Collectively, prior waves tracked by ReversingLabs, JFrog, and Socket researchers have accounted for hundreds of malicious or suspicious packages and, in at least one case, deliberately targeted industrial control system (ICS) environments with multi-year delayed logic bombs. For .NET teams that treat NuGet the way they'd treat any "trusted" package registry, the trend is a reminder that trust in a registry is not the same as trust in a package.
A Registry Built for Convenience, Now Exploited for Persistence
NuGet's appeal — one-line dotnet add package installs, automatic transitive dependency resolution, and tight Visual Studio/MSBuild integration — is precisely what makes it attractive to attackers. Unlike npm or PyPI, where malicious code typically has to execute through an install script or an imported function, NuGet packages can carry build/*.targets and buildMultitargeting/*.targets files that MSBuild imports and executes automatically during compilation. That means a malicious package doesn't need a victim to call any of its APIs — simply restoring and building a solution that references it can be enough to run arbitrary code on a developer workstation or, worse, inside a CI/CD pipeline with elevated credentials.
Researchers have also documented attackers using IL (Intermediate Language) weaving — modifying the compiled bytecode of a legitimate-looking DLL after it's built — to splice malicious instructions into otherwise normal-looking assemblies. This technique is harder to catch with a simple source-code review because the malicious behavior isn't visible in any .cs file; it's stitched directly into the binary that ships inside the package.
The Techniques Behind the Campaigns
Across the campaigns tracked over the past two years, a consistent playbook emerges:
Typosquatting and brandjacking. Packages with names deliberately close to popular libraries — subtle misspellings of names like Moq, Newtonsoft.Json, Discord.Net, and various crypto and cloud SDKs — are uploaded in bulk, betting that a fraction of developers will fat-finger an install command or copy a malicious name from a compromised tutorial, README, or AI-generated code snippet.
Author-account farming. Rather than one-off uploads, attackers have registered clusters of publisher accounts and pushed dozens of packages under different names to survive takedowns — if one account gets banned, the rest of the cluster keeps distributing.
Delayed, conditional execution. One of the more alarming discoveries involved packages that checked the system date and only activated their payload after a specific future trigger date — in the ICS-focused campaign researchers dissected, some packages contained logic set to activate years after upload, designed to eventually crash or destabilize industrial and manufacturing systems that depend on .NET components for HMI (human-machine interface) and SCADA-adjacent tooling. This "sleeper" approach is specifically engineered to defeat scanners that only test packages at the moment of publication.
Credential and wallet theft. Other packages have focused on more conventional financially motivated payloads: scanning for and exfiltrating browser-stored credentials, cryptocurrency wallet files, SSH keys, and environment variables, then phoning home to attacker-controlled infrastructure.
Dependency confusion. Because NuGet resolves package names globally by default, attackers have also targeted enterprises by publishing public packages that mimic the naming convention of a company's internal, private packages — hoping a misconfigured feed priority pulls the malicious public version instead of the legitimate internal one.
Why .NET Shops Are a Growing Target
.NET's footprint has shifted the risk calculus for attackers. It's no longer just a Windows desktop and enterprise-backend language — .NET is now deeply embedded in cloud-native services via ASP.NET Core, in cross-platform mobile via MAUI, and increasingly in industrial, healthcare, and financial infrastructure where uptime and integrity failures carry outsized real-world consequences. A malicious package that lands inside a build pipeline for one of these systems doesn't just risk a stolen API key — it risks operational disruption at a plant floor or a clinical system.
At the same time, NuGet's registry has historically had lighter automated malware scanning than some peer ecosystems, and its build-time execution model means a "do nothing but install it" test — the kind many teams informally rely on — is not a safe way to vet a package. Static review of a .nupkg's source isn't sufficient either, given IL-weaving can inject payloads that never appear in source form at all.
The Detection Gap
What makes these campaigns durable is the mismatch between how fast malicious packages get published and how slowly most organizations discover they've pulled one in. A typosquatted package might sit in nuget.org for weeks accumulating downloads before a researcher or automated scanner flags it, and by then it may already be pinned in a packages.lock.json file, cached in an internal Azure Artifacts or GitHub Packages feed, or baked into a container image that's already in production. Traditional vulnerability scanning — which checks whether a known-good package has a known CVE — does essentially nothing against a brand-new malicious package that has no CVE at all, because it was never a legitimate library to begin with. That's a fundamentally different detection problem than patch management, and it requires continuous composition monitoring rather than periodic scans.
What This Means for .NET Development Teams
The practical takeaway isn't "stop using NuGet" — it's that NuGet packages deserve the same scrutiny as any other untrusted code entering the build. Concretely, that means:
- Pinning exact package versions and reviewing diffs on every version bump, since attackers have also compromised previously-legitimate packages through maintainer account takeovers.
- Restricting which feeds can supply which package names to reduce dependency-confusion exposure, especially for organizations running private NuGet feeds alongside nuget.org.
- Treating
.targets,.props, and any build-time scripts shipped inside a package as executable code requiring review — not passive metadata. - Maintaining an accurate, continuously updated software bill of materials (SBOM) so that when a package is later flagged as malicious, security teams can immediately identify every affected repository, build pipeline, and shipped artifact instead of manually grepping lockfiles.
- Building a process to act on malicious-package intelligence feeds in near real time, since the window between publication and detection is where the damage in these campaigns tends to happen.
How Safeguard Helps
Safeguard is built to close exactly this detection-and-response gap for .NET teams and every other ecosystem where malicious packages hide in plain sight. Griffin AI, Safeguard's security reasoning engine, continuously cross-references your dependency graph against emerging malicious-package intelligence and flags newly identified threats the moment they're confirmed — not weeks later during a scheduled scan. Reachability analysis then determines whether a suspicious or vulnerable package is actually exercised in your application's call paths, so teams triaging a flagged NuGet dependency can immediately tell the difference between "referenced but dead code" and "loaded and running in production." Safeguard's SBOM generation and ingest capabilities give security and engineering teams a live, queryable inventory across every repo and build pipeline, so when a package like the ones described above surfaces on a threat feed, you can answer "where are we exposed?" in seconds rather than days. And where a fix is available — whether that's bumping to a patched version or removing a malicious dependency entirely — Safeguard's auto-fix pull requests let teams remediate directly in the repository, closing the loop from detection to resolution without manual dependency archaeology.