|
|
Log in / Subscribe / Register

A single Node of failure

A single Node of failure

Posted Mar 31, 2016 13:13 UTC (Thu) by tshow (subscriber, #6411)
In reply to: A single Node of failure by hummassa
Parent article: A single Node of failure

> Am I interpreting the whole thing wrong, or are people complaining of "too much code reuse"??

The choice here is between (a) writing what ought to be a three line function at worst (calc length of padding, concat that many spaces together, concat string on the end), and (b) dragging in the arbitrary dependency graph of some micro-package to do it for you, while hoping both it and all its dependencies are both well written and available.

The moment you start depending on external packages, you open yourself up to version mismatches, packages getting unpublished, packages getting updated in ways incompatible with your code. Every once in a while, things will just break because of something done by someone you've never met, somewhere out there in the vast dark.

And part of the "reuse" here is eventually going to be security exploits, if it hasn't already. Looking at the way these dependency trees fan out, it would be trivial for someone to slip an exploit in to a commonly used micropackage somewhere way down in the weeds. With the complexity of the dep tree and the apparently cavalier attitude of "why write a couple of lines of code when I can use someone else's" happening at nearly all levels, we've got a security nightmare on our hands. Active exploits could lurk for years, because nobody is taking the time to validate all the code in the massive dependency fan-out.

And that's assuming that nobody making exploits is clever enough to obfuscate things using version trickery or DNS poisoning, or what have you. There's no way to security audit this.


to post comments

A single Node of failure

Posted Mar 31, 2016 19:22 UTC (Thu) by samroberts (subscriber, #46749) [Link] (8 responses)

Right, because writing it yourself rather than using well-known libraries is good security practice?

With npm, if a package has a security vulnerability, then the package can be updated, and the security fix can be pulled in with a single update to all its dependencies. If you don't want that, shrinkwrap your projects, to pin the versions of your dependencies. Then you get to hear about how a security fix was released... but your app didn't get it.

A single Node of failure

Posted Mar 31, 2016 21:03 UTC (Thu) by ibukanov (subscriber, #3942) [Link]

There is a difference between a security bug and a deliberately put exploit. Npm model protects against the former as it makes it trivial to update after a bug is discovered via running a single command. The price for that is that it turns npm into a vehicle to deliver an exploit right into thousands of developers' computers.

Compare that with a model where all dependencies are explicitly copied into the source tree. Surely it makes it harder to upgrade especially if one manually applies patches for security bugs. But then one avoids exposure to deliberate exploits as the delivery is simply not there.

A single Node of failure

Posted Apr 1, 2016 13:17 UTC (Fri) by tshow (subscriber, #6411) [Link] (6 responses)

> Right, because writing it yourself rather than using well-known libraries is good security practice?

In this case? Absolutely. You're thinking about bugs when you should be thinking about the intentional addition of malicious code. What if instead of just left-padding, this code had left-padded but oh by the way checked to see if the input string looked like an email address and if so harvested it and sent it off to a spam server? Or kept a copy around in case it saw something that looked like a password string... Would anyone have noticed, until the maintainer pulled it and broke things?

These micro-packages are for things like left-padding strings and determining if something is an array. Trivial things. Things that are unlikely to cause security bugs even if badly coded, given we're talking about a garbage-collected language with proper string support.

And you aren't just using "well-known" libraries, you're using everything that their deptree drags in. THAT is the problem here; how many people who's projects broke were actually even aware that left-pad was a dependency? The "well-known" library they used dragged in a bunch of other possibly less-known libraries which in turn dragged in a bunch more even less known libraries, and pretty soon you have hundreds of dependencies, most of which are never going to see serious security scrutiny.

ANY one of those trivial sub-sub-sub-dependencies is a vector for malicious code insertion, because who'd ever find it? And with the way the deptree fans out, a bit of trivial social engineering and some patience in getting your not-yet-malicious-but-just-wait-'til-you-trust-me module worked into the system (or taking over as maintainer of an existing module that's well-connected but in a dark corner of the deptree) basically gives you everything using NPM on a platter.

This is not like (say) the Linux kernel, where there are tiers of reviewers to get past before you can get your malicious code in. Once a micropackage is trusted, it doesn't seem like there's any mechanism to check that the code does no more than it says on the label. Unit tests do nothing to check for side effects, and besides, unit tests can be malicious too.

So yes, writing it yourself is by far the better security practice here.

A single Node of failure

Posted Apr 1, 2016 16:24 UTC (Fri) by samroberts (subscriber, #46749) [Link] (5 responses)

I think this is a tempest in a teapot. Comparing this to the Linux tree, or debian packages is overkill, most webapps don't have that kind of control or review of their dependencies, in any language.

Compare it instead to a Rails app, something in the same application space. The situation here is:

1. node app with 400 dependencies, many of them small
2. rails app with 20 dependencies, most of them large

Assume total code size would be aproximately the same for an app with same function (assuming you believe js and ruby are equivalently concise for a similar application, which is a different debate).

In rails, you'd pull in a huge gem that does 50 things, many of which you don't use, but which may have security issues that effect you. You have less gems, but each one is much larger.

In node, you'd pull in small npm packages, that do single things. You have many more of them, but the total code size should be the same.

Arguably, its easier to review one large pile of code than many small piles of code. That can be argued, but I don't think you can claim that it is many factors easier.

Reviewing left-pad for security defects, for example, should be a matter of minutes.

All of which assumes that everybody reviews their dependencies for security defects, which isn't true for any language.

The many eyes make bugs shallow hypothesis is disproved every day for security.

Also, there is reference to social engineering. Again, compare many small packages with one or two developers, to a few large gems with many developers. Total developer count will probably be aproximately equal, so even the social engineering attack surface is similar.

npm can pull up its socks in some ways: signed package uploads, email notification of a publish to any owned repo (so we know if someone hijacked our repo or stole our credentials), and some other things, have all been excellent suggestions.

Everyone who has ever done `curl ...; tar -xf ..; ./configure` should be asking right now: how different is this?

A single Node of failure

Posted Apr 1, 2016 17:28 UTC (Fri) by bronson (subscriber, #4806) [Link] (2 responses)

It's not as similar as you imply. Those few Rails gems are used by tons of people and updated a few times per year, tops. Those many Node gems are in a constant state of churn.

> Reviewing left-pad for security defects, for example, should be a matter of minutes.

Multiply that by 400 dependencies, remember?

A single Node of failure

Posted Apr 1, 2016 21:32 UTC (Fri) by samroberts (subscriber, #46749) [Link] (1 responses)

rails line count of .rb files (excluding anything with test in the name or path): 111895 (1003 files)

express line count of lib/**/*.js: 3879 (11 files, I counted by hand)

And, yeah, your average express app uses a bunch of middleware... none of which will be as big and complex (<4000 lines) as express itself.

You can multiply by 400 all you want, and raise fear about OMG look how many modules node uses, its INSANE... but the fact remains, rails itself contains more code even before you add some gems than the 100s of package dependencies of many node projects.

Its just a different way of doing things. Node does a package per function or small set of functions, other languages have package systems that are so clunky and hard to use, they have to deliver code in large libraries, composed of dozens to 100s of files, and 100s to 1000s of APIs.

And sure, rails is used by a lot of people... but so is express and the set of packages around it, including, implicitly and recursively, all the dependencies.

A single Node of failure

Posted Apr 1, 2016 22:31 UTC (Fri) by bronson (subscriber, #4806) [Link]

I must be misunderstanding you... It sounds like you're talking about rails/rails? That's nine gems, plus database adapters, etc... How does it make any sense at all to compare it to the Express package?

Even if it did, I'm not sure how your comment applies to anything I said... Where am I talking about lines of code?

A single Node of failure

Posted Apr 2, 2016 0:37 UTC (Sat) by rgmoore (✭ supporter ✭, #75) [Link]

If you're worried mostly about errors that lead to security holes, your analysis may be correct. But in terms of malicious code, I'd take a large project over a host of small ones any day.

Somebody trying to slip malicious code into a big project has to get it by the other people working on the project, many of whom are likely to take a look at it before it gets into a shipping product. If they want to insert malicious code, they have to be clever enough to get it past the other developers on the project and, ideally, defend it as an innocent mistake if it's discovered.

In contrast, a tiny project with just one developer could put in malicious code with much less risk of detection. It would only get found if one of the projects that uses it decides to dig into the code and see what makes it tick, which is less likely because the whole point of including the code in the first place is to not have to think about what makes it work.

A single Node of failure

Posted Apr 7, 2016 7:42 UTC (Thu) by Wol (subscriber, #4433) [Link]

> The many eyes make bugs shallow hypothesis is disproved every day for security.

Like so many sayings, this one is misapplied every day, too ...

Read it carefully. It says "bugs are shallow". That means "IFF you're looking, they're easy to spot". It does NOT mean they will be stumbled across by chance. So no, it's not disproved. It's just totally irrelevant.

I'm sorry, but using sayings and claiming they mean something completely different does annoy me ... :-)

Cheers,
Wol


Copyright © 2026, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds