JavaScript developers targeted by hundreds of malicious code libraries

PhilipStorry

Ars Scholae Palatinae
1,197
Subscriptor++
The problems with "batteries" included is one, you can never include everything - people are always coming up with new things - new batteries if you will. Two, you then add significant bloat to programs for all the 'batteries' they don't use.
I think you've misunderstood my point, and I can only apologise that I didn't express it well enough.

I was not advocating for everything to be in the standard library. I was advocating for good, broad standard libraries as that increases the utility of the programming language/platform, and decreases the amount of work that the individual developer has to do.

Naturally not everything can be in the standard library.

But if the standard library is broad, then that leaves more time for other work - whether that be developiong your own libraries, or doing due diligence and checks on other people's.

Java struggled with this - historically you need a full, hundreds of megabytes JRE even for the simplest of programs to run - although, more recently, they are making Java more modular - so you can download the core JVM and then add which modules you actually want to use.
Storage is cheap.

I remember not liking .NET Framework 1.x because the FTP program that required it was a 600Kb download, but the framework was ~80Mb. In those early days of low bandwidth and smaller storage, .NET felt very much like a bloated version of the Visual Basic runtime DLLs.

But it was at least shared across programs, and once installed it was available to all of them. I slowly came around to the idea - I just wished Microsoft had done a better job with distribution.

These days you can use a Raspberry Pi as a desktop. In this context the issue of storage or RAM is only a huge problem with microcontrollers. Where Node.js, Python, Java and .NET are probably not necessarily your first choice precisely because microcontrollers are so constrained.

Then the other problem is, sometimes the implementations included in a language leave something to be desired. For example, Java has long included implementations of XML parsers for various APIs, but some of the early Java parser implementations built into Java weren't very fast/optimized, so you started getting other implementations competing with the Java XML implementations. Also, then people created new APIs - new approaches to how to interact with XML data (e.g. early on you had SAX or DOM, then people wanted easier ways to work with XML than SAX, but that didn't required the entire document to be parsed into memory at once like DOM does, so they created STAX and Trax, new schema languages for validation (originally we had DTDs, then XSDs, then Schematron and Relax NG (not sure the order those arrived)), etc.
Just as not everything needs to be in the standard library, not every standard library entry needs to be the fastest/leanest/smartest. A good standard library module should be robust, easy to use, and standards compliant (where that matters).

if you need more than the standard library provides, go grab it. Not a problem. But to use your example - at least everyone that wants to parse XML knows one standard way to do it. If you need higher performance or some other feature, you can make the choice to use a different module - but you're also choosing to take on the maintenance for that in terms of security vetting and updates. You're also acknowledging that any new hires/newcomers to your project will need to learn that other module.

Having a broad standard library makes all options better, because you can focus on the parts you care about - and not have to worry about the security, maintenance and provenance of the parts that are less important but still necessary.

And XML is an example where a lot of apps have no need for XML functionality at all. So, why bloat up the runtime with XML functionality that's not being used by your app?
A good runtime won't load them into RAM, they're just there on the disk. Not taking up a huge amount of space in modern terms. And you now have the option. Maybe you're not parsing XML now, but in a future version you want to be able to import an competitor's configuration file or data file? You can at least prototype and possibly even ship that without needing to add anything else. And certainly without adding more work due to new items on your SBOM.

It's really impossible for any language to be all things to all people.
Absolutely. But a good broad standard library benefits almost all people anyway, even if they're not using 100% of it.

Better to have a clean core, and to add to it good libraries that implement what you need.
Here is the point on which we truly disagree. I think you're underestimating the effort in selecting, maintaining and checking those additional libraries. If more of them were from a standard library, you can assume that the vendor or project behind the language/platform is maintaining them and keeping them secure. It's quite literally not your problem.

Whereas with a smaller standard library, everything you import is your problem. And it's a problem that a lot of developers - as well as sysadmins, companies and other organisations - are very badly set up to deal with.

If that weren't the case, we wouldn't be seeing attacks like this. Good luck slipping something like this into the .NET Framework or Java Standard Libraries - I'm not saying it's impossible, but it'll be a lot of work.

And when it comes to exploits, I'd rather that the attackers have to do the work than me. ;)
 
Last edited:
Upvote
20 (21 / -1)

Navalia Vigilate

Ars Praefectus
3,143
Subscriptor++
This is one reason why I'm wary of automated build systems that pull in 500 packages from a remote repository that I don't control.

Give me locally hosted libraries and (shakes cane, yells at cloud) get off my lawn!
If I cannot run 'make' on every package before installation, I, I...

...I, ummm, what was I,...

...nice weather we're having today, isn't it?
 
Upvote
-3 (2 / -5)

sidrus

Seniorius Lurkius
21
Subscriptor++
Yes, this would mean devs would have to spend a few seconds more on coming up with names for their stuff

I'm going to assume you've never had the sweat-inducing anxiety of staring at that blinking cursor, silently mocking you, as you struggle to conquer one of programming's most daunting challenges: naming things. ;)
 
Upvote
27 (28 / -1)
This is one reason why I'm wary of automated build systems that pull in 500 packages from a remote repository that I don't control.

Give me locally hosted libraries and (shakes cane, yells at cloud) get off my lawn!

Download first, then scan for malware, then install offline in a test machine and scan that. Then go online with a network monitoring tool plus firewalk to see if the machine tries to connect to places it shouldn't. And only if everything is okay then do install in the mainline machine.
 
Upvote
-3 (2 / -5)

WereCatf

Ars Tribunus Militum
2,883
I'm going to assume you've never had the sweat-inducing anxiety of staring at that blinking cursor, silently mocking you, as you struggle to conquer one of programming's most daunting challenges: naming things. ;)
Not really, no. When programming, I just name everything by what its function is. Sometimes I end up with rather long names for functions or variables, but that's not really an issue with modern IDEs that do autocomplete, either.

Now if you were talking about e.g. naming my characters in RPGs, that's where I struggle...
 
Upvote
8 (8 / 0)

adamsc

Ars Praefectus
4,281
Subscriptor++
This is one reason why I'm wary of automated build systems that pull in 500 packages from a remote repository that I don't control.

Give me locally hosted libraries and (shakes cane, yells at cloud) get off my lawn!

The problem is that we tried that in the 90s, 2000s, etc. and it mostly meant old bugs not getting fixed for years and people reinventing wheels which didn’t even end up round (think of all those terrible parsers where someone half-assed a complex format using regexes or string operations because it was “too hard” to find a library). NPM metastasized in part as an overreaction to that problem (also because JavaScript was even more limited as a language than Java) and a lot of these risks are basically because a generation of programmers was trained to install a module for everything.

What I think we need is to back away from the current extreme and have more focus around curated collections from trustworthy sources. Namespacing helps there (I might have questions about the corporate agenda behind an oracle/ package but it’s a low risk of malware) along with things like the way many registries have a verified user concept where you could imagine clients wanting a way to say “by default, only install packages which come from verified publishers who build their packages on trusted CI infrastructure” where you’d have to do something like “npm install --I-am-being-unsafe rando/package” to install something.

As an open source developer who got started without major corporate backing, I don’t completely love what that does for newcomers getting started but the barriers could be kept relatively low. The analogy I go to as GenX is that our current model of running random code from internet strangers feels a lot like boomers talking about going to wild parties and having sex with strangers, which just sounds insane to anyone who grew up after the AIDS epidemic.
 
Upvote
12 (13 / -1)

Cax

Ars Centurion
209
Has the Apache Maven repos ever suffered a supply chain attack like this? Seems to me that maven automatic dependency downloading is pretty similar in concept to NPM, and yet, I don't think I've ever heard of an attack like this? Entirely possible I just missed it.
I don’t recall that happening. Maven at least has namespaces, because it is made by grownups for grownups, and they may be controlled somehow at maven central, I don’t know. You could still typosquat namespaces though.

Why can’t we sign packages like we «sign» TLS endpoints? OSGI supports signing I think.
 
Upvote
0 (1 / -1)

J.King

Ars Praefectus
4,424
Subscriptor
Can we all agree that the node.js ecosystem is a micro-dependency disaster and needs to start over from scratch with a proper standard library this time?
Honestly, no. There's always going to be enough people invested in the status quo, enough disagreement about what should go in the standard library, enough pressure to just get things done, and enough of a disconnect between the Node world and the browser world that no such square-one attempt will even get beyond the conceptual stage. What we can get is a slow evolution toward a more useful standard library.
 
Upvote
5 (5 / 0)

adamsc

Ars Praefectus
4,281
Subscriptor++
I have one word for you: Namespacing. That at least requires two typos.

It’s a partial solution but it’s not enough on its own, especially in the JavaScript world. The harder problem is transitive trust in a world where installing a package gives it access to your local file system. The JS world is notorious for having more dependencies than anyone can monitor, but it’s not like the rest of the programming world doesn’t have dense trust depth issues se anyone who’s tried to keep a Java app patched can confirm.

Better identity verification can make these squatting attacks harder but ultimately we need to change the development model so it takes more than a single mistake to breach everything you care about. For example, these attackers are focused on cryptocurrency because cryptocurrencies are insecure by design but the same approach would also work for cloud credentials, SSH keys, etc. or more sophisticated attacks like modifying your source code. We should be sandboxing development environments more so code doesn’t have arbitrary local access, making it so installing packages doesn’t run code or add commands without confirmation, etc. just as we don’t say browser security ends with telling people to be careful which links they click on.
 
Upvote
2 (2 / 0)
I'm going to assume you've never had the sweat-inducing anxiety of staring at that blinking cursor, silently mocking you, as you struggle to conquer one of programming's most daunting challenges: naming things. ;)
there are three eternal problems in computer science. naming things, and off-by-one errors.
 
Upvote
8 (9 / -1)

Adam Joones

Smack-Fu Master, in training
1
This is a serious concern for JavaScript developers, especially those involved in Web Development in Dubai. Malicious libraries can easily slip into the npm ecosystem, posing risks to developers. To reduce these risks, it's important to always check the package details to ensure it's actively maintained and up-to-date. Tools like npm audit can help identify vulnerabilities in your dependencies, while locking your dependencies with a package-lock.json or yarn.lock file ensures you're not exposed to unexpected updates. For professionals in Web Development Dubai, regularly removing unused or outdated dependencies is also essential to maintaining a secure project. Staying vigilant and properly managing your dependencies is key to preventing attacks and ensuring the security of your web development projects in Dubai.
 
Upvote
-4 (0 / -4)

Bigdoinks

Ars Scholae Palatinae
1,013
Can we all agree that the node.js ecosystem is a micro-dependency disaster and needs to start over from scratch with a proper standard library this time?
Node is pretty much just a JS wrapper over C, similar to C-python. The problem is that ECMA is the standard for JS, and they want JS to be as accessible to non-programmers as possible so anybody regardless of programming experience can make a basic website. To accomplish that, the ECMA std library has tons of wacky things that make it easy for "random Joe" to make a website, like loose types and opaque auto type-casting(like string "0" vs the int 0 vs boolean false) so that even if it's wrong it still doesn't just crash. However, it makes it more difficult for experienced programmers trying to build a API server and ensure their code is interpreted in the way that they explicitly intended. This is somewhat solved by typescript, but even then, JS has no mechanism for evaluating types at runtime, so we need these shimmy micro dependencies, or otherwise write repetitivive functions type-checking each value type at runtime to make sure the JS engine isn't janking things up.
 
Upvote
2 (2 / 0)
Node is pretty much just a JS wrapper over C, similar to C-python. The problem is that ECMA is the standard for JS, and they want JS to be as accessible to non-programmers as possible so anybody regardless of programming experience can make a basic website. To accomplish that, the ECMA std library has tons of wacky things that make it easy for "random Joe" to make a website, like loose types and opaque auto type-casting(like string "0" vs the int 0 vs boolean false) so that even if it's wrong it still doesn't just crash. However, it makes it more difficult for experienced programmers trying to build a API server and ensure their code is interpreted in the way that they explicitly intended. This is somewhat solved by typescript, but even then, JS has no mechanism for evaluating types at runtime, so we need these shimmy micro dependencies, or otherwise write repetitivive functions type-checking each value type at runtime to make sure the JS engine isn't janking things up.
None of what you said is relevant to the fact that Node should have a better standard library so that one doesn't need to pull twenty billion dependencies to do anything.
 
Upvote
4 (4 / 0)

OrvGull

Ars Legatus Legionis
11,881
The “make it easy to type code” philosophy of JS is antithetical to actually making robust programs. Python and other dynamically typed languages can suffer from some of that as well. But JS has it in spades. Stupid language.
Eh, JS is a language that gives you lots of opportunities to shoot yourself in the foot. You can write really elegant code in it. You can also write incomprehensible code that's subtly incorrect in ways that will bite you later. It's up to you. Its looseness was partly a result of people's unhappiness with Java, a language that often feels like it has more punctuation than code.

There are actually lots of languages that are very loosely confined and will let you do all sorts of things that make your code wrong or hard to read; the classic example being C, which is just full of footguns.

The opposite are languages like Rust that are strongly typed with lots of guard rails, enforce specific syntax, and carefully try to limit the ways you can do anything incorrect. But those languages are hard to learn and tedious to code in. They might make sense for critical things like a kernel, but you're kind of insane if you write a web app in one.
 
Upvote
-1 (0 / -1)

Faanchou

Ars Tribunus Angusticlavius
9,227
The opposite are languages like Rust that are strongly typed with lots of guard rails, enforce specific syntax, and carefully try to limit the ways you can do anything incorrect. But those languages are hard to learn and tedious to code in. They might make sense for critical things like a kernel, but you're kind of insane if you write a web app in one.
The counterpoint of course being that once you have written a web app in one, you have something you can modify without automatically breaking the sandbox assumptions just by stating your new intentions.
 
Upvote
0 (0 / 0)

OrvGull

Ars Legatus Legionis
11,881
The counterpoint of course being that once you have written a web app in one, you have something you can modify without automatically breaking the sandbox assumptions just by stating your new intentions.
Yeah, although in the case of Rust all the safety guarantees go away the moment you interface with anything outside your program. ;)
 
Upvote
0 (1 / -1)
Yeah, although in the case of Rust all the safety guarantees go away the moment you interface with anything outside your program. ;)
That’s not how it works. It’s the job of the wrapper that interfaces with the foreign library to ensure safety. Most Rust applications should never have unsafe code themselves.
 
Upvote
1 (1 / 0)