ClickCease “Everything” and the Node.js kitchen sink too

Content Table

Join Our Popular Newsletter

Join 4,500+ Linux & Open Source Professionals!

2x a month. No spam.

“Everything” and the Node.js kitchen sink too

Joao Correia

January 11, 2024 - Technical Evangelist

  • *The Supply Chain is vulnerable at all levels, from the code to the distribution
  • *Node.js repository was effectively locked after a developer uploaded a malicious package

It’s often hard to differentiate between intended and unintended consequences. A recent “prank” over the holidays complicated life for Node.js developers, underscoring a familiar adage: no good deed goes unpunished. 

There is some story telling involved, so popcorn is definitely recommended for this one.

In the faraway times of 2016…

 

…a Node.js developer created a package named “leftpad,” a mere 11 lines of code. Padding strings is a common task for developers, who typically prefer not to reinvent the wheel (the Don’t Repeat Yourself – DRY – programming principle). 

Naturally, many chose to import “leftpad” into their projects. But this reliance introduced a vulnerability – exposure to any issues with “leftpad,” whether bugs, security gaps, or the whims of its creator. In a dramatic turn, the developer of “leftpad,” citing the right to remove his work, did just that. This action crashed a significant number of major websites, highlighting the fragility of such dependencies. In fairness, the author did provide some reasons to do so, and whether you agree with commercialization of open source code by corporations will shift your view on it (you can read more about it here, if you’re so inclined).*

Ultimately, the removal of “leftpad” caused severe disruption across numerous third-party packages and websites. To prevent a recurrence, the npm registry implemented a policy: a package can’t be unpublished if it’s a dependency for another package. This rule seemed effective for some time.

 

That’s all good, but what happened recently?

 

Since we obviously can’t have nice things, people went looking for potential ways to abuse the change introduced by the registry. And, by reversing the logic, if I can’t remove a package that someone else depends on, maybe someone else can’t remove theirs if my code depends on their package…and, of course, it worked.

So, in what the developer later described as a “test” and a “prank,” a package called “everything” was added to the registry. It didn’t do anything other than including, as dependencies, a group of other packages called “everything chunk 1,” “everything chunk 2,” etc. These, in turn, included every single package on the registry. This made it impossible to unpublish any package, by anyone, since there would always be a dependency on it.

But it gets better. Or worse, depending on the amount of left-over popcorn you still have on hand.

The dependency declaration on an npm package allows developers to “depend” on a specific version. Usually, it’s a tested version that does what it claims to do, correctly, and the developer including that package has run extensive testing to ensure the behavior is the necessary one for their package or application. 

But you’re not restricted to specifying one single version. By setting “*” as the version value, you effectively tell npm that *any* version of that package can be used as a dependency. 

Well, “everything” included every single dependency… and every single version of those dependencies, as it used “*” on the declaration.

So, other developers were not simply locked out of removing their own packages (for example, if they had a bug), but any old version too. 

“Everything” was locked down tightly.

 

Was it resolved?

 

Yes, fortunately. The creator of “everything” collaborated with the npm support team to rectify the issue, necessitating intervention by marking the “everything chunk” repositories private, thus breaking the dependency chain (more on this, including a screenshot of the developer apologizing, can be seen here).

This incident was a close call for the collective cybersecurity and IT community. It raises a chilling possibility: instead of one developer creating this chaos as a prank (or a “test”), what if it had been a serious threat actor? What if an “everything”-style package was just the tip of the iceberg, used to prohibit the removal of another package with a log4j-level security vulnerability in its code?

The npm ecosystem, and, in fact, any similar package-dependency focused environment, still faces significant challenges in addressing these vulnerabilities. It’s possible there is no perfect solution, given the creativity with which people exploit flaws. 

Perhaps, in this ongoing battle, AI might offer some much-needed assistance.

 

* For more examples of seemingly trivial yet impactful packages, consider the “One liner rpm package “is-windows” has 2.5 million dependents, why on earth?!” thread on Reddit. A single developer is credited with over 1400 packages, most of which are simple one-liners, which showcases the surprising influence of minimal code.

 

Summary
“Everything” and the Node.js kitchen sink too
Article Name
“Everything” and the Node.js kitchen sink too
Description
It is often hard to differentiate between intended and unintended consequences. A recent "prank" complicated life for Node.js developers.
Author
Publisher Name
TuxCare
Publisher Logo

Looking to automate vulnerability patching without kernel reboots, system downtime, or scheduled maintenance windows?

Learn About Live Patching with TuxCare

Become a TuxCare Guest Writer

Get started

Mail

Join

4,500

Linux & Open Source
Professionals!

Subscribe to
our newsletter