Introducing GardWatch

Patrik Nordlén

Patrik Nordlén

CTO & Co-Founder
cryptolodashpasslibCRITICALfetchjwtreqeustsCRITICALbcryptloggerretryauthyamldotenv

The Short Version

We're proud to release GardWatch, our solution for verifying the legitimacy of third-party dependencies before they are added to your project. This has so far been a blind spot which has made it possible for threat actors to achieve large-scale compromises, by publishing malicious dependencies that have subsequently been used in thousands of CI/CD pipelines and local development environments without any checks in place.

Background

Last week was a rough one for software supply chain security. Between late February and March 22nd, a threat actor known as TeamPCP managed to compromise Aqua Security's Trivy vulnerability scanner, its GitHub Actions, and over 60 npm packages. Shortly thereafter, Checkmarx's kics tool suffered the same fate. By March 20th, TeamPCP had deployed a self-propagating worm that spread through the pypi and npm ecosystems. The current estimate is over 60,000 compromised servers globally, with credential theft from CI/CD pipelines across thousands of repositories.

⚠️ What makes this particularly nasty is that a tool that organizations install specifically to find vulnerabilities now became the attack vector.

This isn't an isolated incident, rather it's part of a pattern we've been seeing more and more of. It's always been important to monitor third-party dependencies but the efforts have largely revolved around managing vulnerabilities in them, with hijacking attacks being more of a theoretical risk than a real one. In the past few years that has changed to the software supply chain becoming a primary target, and we need to talk about why and what we can do about it.

How Did We Get Here?

Modern software relies heavily on third-party dependencies. An average npm package pulls in 4.39 other packages as dependencies. The average project uses 86.55 packages. When you install a single npm package, research shows you're implicitly trusting 79 third-party packages and 39 maintainers.

$ npm install express← you typed thisexpressv4.21.0debugbody-parserfinalhandleracceptsqsserve-staticraw-body···iconv-lite···bytes···side-channel···get-intrinsic···call-bind···+ 25 more direct dependencies (cookie, etag, methods, …)1command you typed64packages installed~30maintainers trustedEach of these packages has its own maintainers, CI/CD pipelines, and trust assumptions.

That's for one package!

Most projects have dozens or hundreds of direct dependencies. Sure, there's overlap in the dependency trees, but you're still talking about hundreds or thousands of packages from hundreds or thousands of maintainers. And with AI coding assistants becoming more common, it's easier than ever to just add another dependency without thinking too hard about it.

What Could Go Wrong?

When you install a package, you're making a bunch of trust assumptions:

You found the right package. Typosquatting has been a problem for years, but now we're also seeing "slopsquatting" where AI agents hallucinate plausible-sounding package names that don't actually exist. Attackers have caught on and started publishing malicious packages with those hallucinated names. We've seen examples like "starlette-reverse-proxy", "requests-httpx", "typesutil", and "pystyle".

The package was written securely. One study found that in-house code typically makes up 10-20% of an enterprise codebase. The other 80-90% is third-party code. To the extent that you enforce security practices in your own code, you now have 4-5 times as much code to apply those standards to.

The package is actively maintained. Maintainers need to respond to security issues, assign CVEs, and release updates. Abandoned packages are a real problem.

The repository and CI/CD pipeline are secure. Almost every package these days is built from a CI/CD pipeline connected to a git repo. You're trusting that setup is locked down so only authorized people can publish new versions.

Maintainers follow security best practices. Their accounts need to be secure. We've seen multiple incidents where attackers compromised maintainer accounts and used them to publish malicious versions.

Maintainers aren't malicious. This one's uncomfortable to think about, but you're ultimately trusting that the people maintaining these packages aren't deliberately putting bad code in them.

When Trust Breaks Down

Each of these assumptions has been violated in practice:

Wrong Package

Slopsquatting Attacks

Attackers publish malicious packages using names AI models hallucinate — like "starlette-reverse-proxy", "requests-httpx", and "pystyle".

Read more →
Insecure Code

jQuery, lodash, log4j

Vulnerabilities in widely-used libraries that were trusted implicitly for years before critical flaws surfaced.

Read more →
Abandoned Package

Rust's tokio-tar

The hunt for maintainers of a popular Rust library left it vulnerable with no one to fix discovered flaws.

Read more →
Malicious Maintainer

xz-utils Backdoor & colors.js

A "helpful" new maintainer planted a backdoor in xz-utils. The colors.js maintainer intentionally added denial-of-service code.

Read more →
Compromised Account

September 2025 npm Hack

18 popular code packages hijacked via a compromised GitHub account, rigged to steal cryptocurrency.

Read more →
Insecure CI/CD

Shai-Hulud → CanisterWorm

A progression of CI/CD supply chain attacks from September 2024's Shai-Hulud through to the TeamPCP CanisterWorm campaign.

Read more →

What Can You Do?

Before installing a package, there are things you can and should check:

Is the project well-established and popular?
Is it actively maintained?
Is it used by other reputable projects?
Does it follow good security practices?
Does this specific version follow a normal progression from previous versions, or did v1.2.3 suddenly jump to v12.58.99?

Sites like scorecard.dev and deps.dev are useful for this kind of metadata analysis.

But you can go deeper. Download the package and look at how it's configured to act during installation. Watch for these red flags:

Runs system commands during installation
Executes base64-encoded content
Reads credential files
Downloads and executes remote binaries

The problem is, this is a lot to check manually. And you need to do it for every package you install, including all the transitive dependencies. It's not realistic to expect developers to do this consistently, especially when AI agents can spin up code that uses new packages in seconds.

GardWatch

That's why we built GardWatch! It automates these checks and instantly flags if there are package health concerns worthy of your attention.

GardWatch uses a scoring system. Each package starts with a perfect score. Tests remove points based on what they find. Some tests cause immediate failure - if a package appears on a list of known malicious packages, that's it. Others just lower the score - things like low popularity or no recent updates.

gardwatch
$gardwatch scanexpress--npm
Scanning express (npm)...
Malware Database0
Age0
Downloads0
Repository0
Security Score0
Maintenance0
Metadata0
Community0
SCORE
100/100
SAFE
$gardwatch scanpasslib--pypi
Scanning passlib (pypi)...
Malware Database0
Age0
Downloads0
Repository-15
Security Score-10
Metadata-10
Maintenance-25
Community-5
SCORE
35/100
CRITICAL

GardWatch has two scanning modes:

Metadata scanning is fast. It checks package information from registries and metadata services. This catches hallucinated packages, packages with low trust scores, poor security practices, and suspicious version jumps.

Deep scanning downloads the package and analyzes it with static analysis. This catches malicious install scripts, credential extraction attempts, suspicious system calls, and obfuscated payloads.

For example, when we ran deep scanning on the compromised litellm package from the CanisterWorm campaign, GardWatch correctly identified the malicious .pth file that executes every time you run the Python interpreter.

⚡ Metadata Scan

Fast. Checks package information from registries and metadata services.

  • Hallucinated package detection
  • Low trust score flagging
  • Poor security practices
  • Suspicious version jumps

🔬 Deep Scan

Thorough. Downloads the package and performs static analysis.

  • Malicious install scripts
  • Credential extraction attempts
  • Suspicious system calls
  • Obfuscated payloads

You can use GardWatch in a few different ways:

⌨️

CLI Tool

Manual checks & CI/CD integration

🧩

VS Code Extension

Monitors lockfiles in real time

🤖

MCP Server

Integrates with AI coding assistants

Try It

The software supply chain is only as strong as its weakest link.

Don't let your dependencies be that link.


Sources:

Have questions or feedback? Get in touch.